Example #1
0
    def __init__(
        self,
        n_radial=43,
        n_ap=21,
        cutoff_radius=8.0,
        cutoff_react=None,
        cutoff_prod=None,
        sym_start=0.8,
        sym_cut=5.5,
        width_adjust=(0.5)**(0.5),
        width_adjust_ap=(2)**(0.5),
        elements=frozenset((1, 6, 7, 8, 9)),
        centered=False,
        sharez=True,
        trainz=False,
        mode="Behler",
        cutoff=snn.CosineCutoff,
        len_embedding=1,
        atom_t=None,
        atom_react=None,
        atom_prod=None,
        morse_beta=10.0,
    ):
        super(APNet_mod, self).__init__()

        # Determine mode.
        if mode == "weighted":
            initz = "weighted"
            pairwise_elements = False
        elif mode == "Behler":
            initz = "onehot"
            pairwise_elements = True
        else:
            raise NotImplementedError("Unrecognized symmetry function %s" %
                                      mode)

        self.n_radial = n_radial
        self.n_ap = n_ap
        self.len_embedding = len_embedding
        self.n_elements = None

        self.cutoff_radius = cutoff_radius
        self.cutoff = cutoff(cutoff=self.cutoff_radius)
        if atom_t is not None:
            self.atom_t = torch.tensor(atom_t).reshape(-1)
            if isinstance(atom_react, int):
                if atom_react < self.atom_t:
                    self.atom_react = torch.tensor(atom_react).reshape(-1)
                else:
                    self.atom_react = torch.tensor(atom_react - 1).reshape(-1)
                    #self.atom_react = torch.tensor(atom_react).reshape(-1)
            else:
                atom_react = torch.tensor(atom_react).reshape(-1)
                inc = -torch.ones_like(atom_react)
                zero = torch.zeros_like(atom_react)
                zero[atom_react > self.atom_t] = inc[atom_react > self.atom_t]
                self.atom_react = atom_react + zero
            if isinstance(atom_prod, int):
                if atom_prod < self.atom_t:
                    self.atom_prod = torch.tensor(atom_prod).reshape(-1)
                else:
                    self.atom_prod = torch.tensor(atom_prod - 1).reshape(-1)
                    #self.atom_prod = torch.tensor(atom_prod).reshape(-1)
            else:
                atom_prod = torch.tensor(atom_prod).reshape(-1)
                inc = -torch.ones_like(atom_prod)
                zero = torch.zeros_like(atom_prod)
                zero[atom_prod > self.atom_t] = inc[atom_prod > self.atom_t]
                self.atom_prod = atom_prod + zero
            self.fd_react = FermiDirac(mu=cutoff_react, beta=morse_beta)
            self.fd_prod = FermiDirac(mu=cutoff_prod, beta=morse_beta)

        else:
            self.cutoff2 = None
        self.sym_cut = sym_cut

        # Check for general stupidity:
        if self.n_ap < 1 and self.n_radial < 1:
            raise ValueError("At least one type of SF required")

        if self.n_radial > 0:
            # Get basic filters (if centered Gaussians are requested, start is set to 0.5
            if centered:
                radial_start = 1.0
            else:
                radial_start = 0.5
            self.radial_filter = snn.GaussianSmearing(
                start=sym_start,
                stop=self.sym_cut - 0.5,
                n_gaussians=n_radial,
                centered=centered,
                width_adjust=width_adjust)
            self.RDF = snn.RadialDistribution(self.radial_filter,
                                              cutoff_function=self.cutoff)
        else:
            self.RDF = None

        if self.n_ap > 0:
            self.radial_filter_ap = snn.GaussianSmearing(
                start=-1.0,
                stop=1.0,
                n_gaussians=n_ap,
                centered=centered,
                width_adjust=width_adjust_ap)
            self.APF = snn.APDistribution_Mod(self.radial_filter_ap,
                                              cutoff_functions=self.cutoff)

        else:
            self.APF = None

        self.radial_Z = self.initz(initz, elements)

        # check whether angular functions should use the same embedding
        if sharez:
            self.ap_Z = self.radial_Z
        else:
            self.ap_Z = self.initz(initz, elements)

        # Turn of training of embeddings unless requested explicitly
        if not trainz:
            # Turn off gradients
            self.radial_Z.weight.requires_grad = False
            self.ap_Z.weight.requires_grad = False

        # Compute total number of symmetry functions
        self.n_symfuncs = (self.n_radial + self.n_ap) * self.n_elements
Example #2
0
    def __init__(
        self,
        n_radial=22,
        n_angular=5,
        zetas={1},
        cutoff=snn.CosineCutoff,
        cutoff_radius=5.0,
        centered=False,
        crossterms=False,
        elements=frozenset((1, 6, 7, 8, 9)),
        sharez=True,
        trainz=False,
        initz="weighted",
        len_embedding=5,
        pairwise_elements=False,
    ):

        super(SymmetryFunctions, self).__init__()

        self.n_radial = n_radial
        self.n_angular = n_angular
        self.len_embedding = len_embedding
        self.n_elements = None
        self.n_theta = 2 * len(zetas)

        # Initialize cutoff function
        self.cutoff_radius = cutoff_radius
        self.cutoff = cutoff(cutoff=self.cutoff_radius)

        # Check for general stupidity:
        if self.n_angular < 1 and self.n_radial < 1:
            raise ValueError("At least one type of SF required")

        if self.n_angular > 0:
            # Get basic filters
            self.theta_filter = snn.BehlerAngular(zetas=zetas)
            self.angular_filter = snn.GaussianSmearing(
                start=1.0,
                stop=self.cutoff_radius - 0.5,
                n_gaussians=n_angular,
                centered=True,
            )
            self.ADF = snn.AngularDistribution(
                self.angular_filter,
                self.theta_filter,
                cutoff_functions=self.cutoff,
                crossterms=crossterms,
                pairwise_elements=pairwise_elements,
            )
        else:
            self.ADF = None

        if self.n_radial > 0:
            # Get basic filters (if centered Gaussians are requested, start is set to 0.5
            if centered:
                radial_start = 1.0
            else:
                radial_start = 0.5
            self.radial_filter = snn.GaussianSmearing(
                start=radial_start,
                stop=self.cutoff_radius - 0.5,
                n_gaussians=n_radial,
                centered=centered,
            )
            self.RDF = snn.RadialDistribution(self.radial_filter,
                                              cutoff_function=self.cutoff)
        else:
            self.RDF = None

        # Initialize the atomtype embeddings
        self.radial_Z = self.initz(initz, elements)

        # check whether angular functions should use the same embedding
        if sharez:
            self.angular_Z = self.radial_Z
        else:
            self.angular_Z = self.initz(initz, elements)

        # Turn of training of embeddings unless requested explicitly
        if not trainz:
            # Turn off gradients
            self.radial_Z.weight.requires_grad = False
            self.angular_Z.weight.requires_grad = False

        # Compute total number of symmetry functions
        if not pairwise_elements:
            self.n_symfuncs = (self.n_radial +
                               self.n_angular * self.n_theta) * self.n_elements
        else:
            # if the outer product is used, all unique pairs of elements are considered, leading to the factor of
            # (N+1)/2
            self.n_symfuncs = (self.n_radial + self.n_angular * self.n_theta *
                               (self.n_elements + 1) // 2) * self.n_elements
Example #3
0
    def __init__(
        self,
        n_radial=43,
        n_ap=21,
        cutoff_radius=8.0,
        cutoff_radius2=None,
        sym_start=0.8,
        sym_cut=5.5,
        width_adjust=(0.5)**(0.5),
        width_adjust_ap=(2)**(0.5),
        elements=frozenset((1, 6, 7, 8, 9)),
        centered=False,
        sharez=True,
        trainz=False,
        mode="Behler",
        cutoff=snn.CosineCutoff,
        len_embedding=1,
        morse_bond=None,
        morse_mu=None,
        morse_res=None,
        morse_beta=10.0,
    ):
        super(APNet, self).__init__()

        # Determine mode.
        if mode == "weighted":
            initz = "weighted"
            pairwise_elements = False
        elif mode == "Behler":
            initz = "onehot"
            pairwise_elements = True
        else:
            raise NotImplementedError("Unrecognized symmetry function %s" %
                                      mode)

        self.n_radial = n_radial
        self.n_ap = n_ap
        self.len_embedding = len_embedding
        self.n_elements = None

        self.cutoff_radius = cutoff_radius
        self.cutoff_radius2 = cutoff_radius2
        self.cutoff = cutoff(cutoff=self.cutoff_radius)
        if self.cutoff_radius2 is not None:
            self.cutoff2 = cutoff(cutoff=self.cutoff_radius2)
        else:
            self.cutoff2 = None
        self.sym_cut = sym_cut

        if morse_bond is not None:
            g1 = [i for i in morse_bond if isinstance(i, int)]
            if len(g1) < len(morse_bond):
                g2 = [i for i in morse_bond if isinstance(i, list)][0]
                self.morse1 = torch.tensor(g1).reshape(-1)
                self.morse2 = torch.tensor(g2)
                inc = -torch.ones_like(self.morse2)
                zero = torch.zeros_like(self.morse2)
                zero[self.morse2 > self.morse1] = inc[
                    self.morse2 > self.morse1]
                self.morse2 = self.morse2 + zero
                self.morse1 += morse_res[0]
            else:
                morse1 = g1[0]
                morse2 = g1[1]
                if morse2 > morse1: morse2 -= 1
                self.morse1 = torch.tensor(morse1 + morse_res[0]).reshape(-1)
                self.morse2 = torch.tensor(morse2).reshape(-1)
            self.fermi_dirac = FermiDirac(mu=morse_mu, beta=morse_beta)

        # Check for general stupidity:
        if self.n_ap < 1 and self.n_radial < 1:
            raise ValueError("At least one type of SF required")

        if self.n_radial > 0:
            # Get basic filters (if centered Gaussians are requested, start is set to 0.5
            if centered:
                radial_start = 1.0
            else:
                radial_start = 0.5
            self.radial_filter = snn.GaussianSmearing(
                start=sym_start,
                stop=self.sym_cut - 0.5,
                n_gaussians=n_radial,
                centered=centered,
                width_adjust=width_adjust)
            self.RDF = snn.RadialDistribution(self.radial_filter,
                                              cutoff_function=self.cutoff)
        else:
            self.RDF = None

        if self.n_ap > 0:
            self.radial_filter_ap = snn.GaussianSmearing(
                start=-1.0,
                stop=1.0,
                n_gaussians=n_ap,
                centered=centered,
                width_adjust=width_adjust_ap)
            self.APF = snn.APDistribution(self.radial_filter_ap,
                                          cutoff_functions=self.cutoff)

        else:
            self.APF = None

        self.radial_Z = self.initz(initz, elements)

        # check whether angular functions should use the same embedding
        if sharez:
            self.ap_Z = self.radial_Z
        else:
            self.ap_Z = self.initz(initz, elements)

        # Turn of training of embeddings unless requested explicitly
        if not trainz:
            # Turn off gradients
            self.radial_Z.weight.requires_grad = False
            self.ap_Z.weight.requires_grad = False

        # Compute total number of symmetry functions
        self.n_symfuncs = (self.n_radial + self.n_ap) * self.n_elements