Basis function specifications#

The BasisFunctionSpecs class is used to specify the type and order of basis functions that CASM generates.

Selection of degrees of freedom (DoF)#

By default, all DoF present in the prim are coupled. The dofs parameter allows specifying that only the given subset of DoFs should be included in the basis functions.

from casm.bset.cluster_functions import BasisFunctionSpecs

basis_functions_specs = BasisFunctionSpecs(
    dofs=["occ"],
)

DoF specifications#

The occupation and magnetic spin DoF types require specific parameterization using the dof_specs parameter, which takes the form of a dictionary with keys corresponding to DoF types. For example:

dof_spces = {
    "occ": {
        "site_basis_functions": "occupation"
    }
}
dof_spces = {
    "NCmagspin": {
        "max_poly_order": 5
    }
}

Occupation site basis functions#

Formulation#

For occupation DoF (“occ”), the dof_specs parameter is used to specify the value of the discrete site basis functions. The following is a summary of the formulation described in detail in TODO.

The occupation site basis functions are specified in terms of the site occupation index, \(s_\nu\), which takes on the values \(0, 1, \dots, m-1\), where \(m\) is the number of allowed occupants on the site.

It is convenient to define the particular choice of occupation site basis functions using occupation indicator functions, \(p^j_\nu\), as a common reference. The occupation indicator functions take on value \(1\) when site \(\nu\) is occupied by the \(j\)-th allowed occupant, and \(0\) otherwise.

For example, site \(\nu\) in a binary A-B alloy would have two indicator functions, \(p^A_\nu\) and \(p^B_\nu\), though only one is independent, since \(p^A_\nu + p^B_\nu = 1\). Similarly, a ternary A-B-C alloy would have \(p^A_\nu + p^B_\nu + p^C_\nu = 1\).

Generalizing, each site has a vector of indicator functions, \(\vec{p}\), and we consider site basis functions \(\vec{\varphi}\) that can be linearly combined to give the indicator functions according to

\[\vec{p} = \pmb{B} \vec{\varphi},\]

with equivalent matrix representation

\[\pmb{P} = \pmb{B} \pmb{\varphi},\]

where \(\pmb{P}\) and \(\pmb{\varphi}\) are \(m \times m\) matrices with element \(ij\) being the value of the \(i\)-th function when the site occupation index is the \(j\)-th possible value. By definition, \(\pmb{P}\) is the \(m \times m\) identity matrix, and therefore \(\pmb{B} = \left( \pmb{\varphi} \right)^{-1}\).

Cluster expansion basis functions are then constructed as polynomials with the site basis functions, \(\varphi_i\), at each site in the cluster included as variables.

Example, binary spin occupation variables

A common choice for occupation variables in a binary alloy cluster expansion are \(\varphi(A)=-1\) and \(\varphi(B)=1\). Using the above notation, this is

\[\begin{split}\pmb{P} = \begin{bmatrix} 1 & 0\\ 0 & 1 \end{bmatrix}, \pmb{\varphi} = \begin{bmatrix} 1 & 1\\ -1 & 1 \end{bmatrix},\end{split}\]

where the constant function \(\varphi_1(s_j)=1\) that allows cluster expansion is explicitly included and \(\varphi_2(s_j)\) is a site basis function with values equal to the spin occupation variables (\(\varphi_2(A)=-1\), \(\varphi_2(B)=1\)).

Example, “occupation” site basis variables

For a binary alloy, the “occupation” site basis variables take the form \(\varphi(A)=0\) and \(\varphi(B)=1\). In general, using the above notation this becomes \(\varphi_{1} = 1\) and \(\varphi_{i \neq 1}(s_j) = \delta_{ij}\). For a ternary alloy cluster expansion this is

\[\begin{split}\pmb{P} = \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1\\ \end{bmatrix}, \pmb{\varphi} = \begin{bmatrix} 1 & 1 & 1\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}.\end{split}\]

Symmetry#

The indicator variables transform under symmetry according to

(1)#\[\left(\vec{p}_{\nu}\right)' = \pmb{M}_{b^{\ast}}(\hat{s}) \vec{p}_{\nu^{\ast}},\]

where:

  • \(\hat{s}\) is a space group operation

  • \(\vec{p}_{\nu^{\ast}}\) is the vector of indicator variables on site \(\nu^{\ast}\), which is on sublattice \(b^{\ast}\), before transformation by \(\hat{s}\),

  • \(\left(\vec{p}_{\nu}\right)'\) is the vector of indicator variables on site \(\nu\), which is on sublattice \(b\), after transformation by \(\hat{s}\),

  • \(\pmb{M}_{b^{\ast}}(\hat{s})\) is the matrix representation of \(\hat{s}\) used to transform indicator variables occupying sites on sublattice \(b^{\ast}\).

The matrix representations \(\pmb{M}_{b^{\ast}}(\hat{s})\) for transforming indicator variables by factor group operations is determined when constructing a libcasm.configuration.Prim by transforming each allowed occupant on \(b^{\ast}\) and finding the permutation (if it exists) that results in the allowed occupants on \(b\). These matrix representations can be accessed using Prim.local_dof_matrix_rep with

M = prim.local_dof_matrix_rep("occ")[i_factor_group][i_sublat]

where i_factor_group is the index of the factor group operation that differs from \(\hat{s}\) by only a translation (i.e. index in prim.factor_group.elements), and i_sublat is the index of sublattice \(b^{\ast}\) (i.e. column index in prim.xtal_prim.coordinate_frac()).

Notes:

  • \(\pmb{M}_{b^{\ast}}(\hat{s})\) is a row permutation matrix. It permutes the rows of the column vector \(\vec{p}_{b^{\ast}}\) consistent with the order the transformed occupants are listed as allowed occupants on the final site.

  • The transpose of a permutation matrix is equal to its inverse.

  • The inverse of a row permutation matrix is the column permutation matrix which permutes columns in the same cycle that the row permutation matrix permutes rows.

  • Therefore, \(\pmb{M}_{b^{\ast}}(\hat{s})^{\top}\) is a column permutation matrix which can permute the columns of \(\pmb{\varphi}_{b^{\ast}}\) (which correspond to occupation index) to give symmetrically consistent site basis functions on \(b\) according to \(\pmb{\varphi}_{b} = \pmb{\varphi}_{b^{\ast}} \pmb{M}_{b^{\ast}}(\hat{s})^{\top}\).

Matrix representations, \(\pmb{\tilde{M}}_{b^{\ast}}(\hat{s})\), for transforming site basis functions, \(\vec{\varphi}\), can be determined in terms of \(\pmb{M}_{b^{\ast}}(\hat{s})\). First, write \(\vec{\varphi}\) before and after transformation in terms of \(\vec{p}\) as

\[\begin{split}\begin{align} \vec{p}_{\nu^{\ast}} &= \pmb{B}_{\nu^{\ast}} \vec{\varphi}_{\nu^{\ast}}, \\ \left(\vec{p}_{\nu}\right)' &= \pmb{B}_{\nu} \left(\vec{\varphi}_{\nu}\right)'. \end{align}\end{split}\]

Then substitute into Eq. (1) to obtain

\[\pmb{B}_{\nu} \left(\vec{\varphi}_{\nu}\right)' = \pmb{M}_{b^{\ast}}(\hat{s}) \pmb{B}_{\nu^{\ast}} \vec{\varphi}_{\nu^{\ast}}.\]

Finally, left multiply by \(\pmb{B}_{\nu}^{-1}\) and use \(\pmb{B} = \left( \pmb{\varphi} \right)^{-1}\) to obtain

(2)#\[\begin{split}\begin{align} \left(\vec{\varphi}_{\nu}\right)' &= \pmb{\tilde{M}}_{b^{\ast}}(\hat{s}) \vec{\varphi}_{\nu^{\ast}}, \\ \pmb{\tilde{M}}_{b^{\ast}}(\hat{s}) &= \pmb{\varphi}_{\nu} \pmb{M}_{b^{\ast}}(\hat{s}) \pmb{\varphi}_{\nu^{\ast}}^{-1}. \end{align}\end{split}\]

Specification#

Chebychev occupation site basis functions#

Chebychev site basis functions give an expansion (with correlation values all equal to 0) about the idealized random alloy where the probability of any of the allowed occupants on a particular site is the same. This choice of occupation site basis functions can be specified with:

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": "chebychev"
        }
    }
)

For a binary alloy, the Chebychev site basis functions used by CASM have the value:

\[\begin{split}\pmb{\varphi} = \begin{bmatrix} 1 & 1\\ -1 & 1 \end{bmatrix}.\end{split}\]

For a ternary alloy, the Chebychev site basis functions used by CASM have the value:

\[\begin{split}\pmb{\varphi} = \begin{bmatrix} 1 & 1 & 1\\ -3/\sqrt{6} & 0 & -3/\sqrt{6} \\ -\sqrt{2}/2 & \sqrt{2} & -\sqrt{2}/2 \end{bmatrix}.\end{split}\]

Occupation site basis functions#

The “occupation” site basis functions give an expansion (with correlation values all equal to 0) about the default configuration where each site is occupied by the first allowed occupant in the Prim.occ_dof list. This choice of occupation site basis functions can be specified with:

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": "occupation"
        }
    }
)

For a binary alloy, the “occupation” site basis functions used by CASM have the value:

\[\begin{split}\pmb{\varphi} = \begin{bmatrix} 1 & 1\\ 0 & 1 \end{bmatrix}.\end{split}\]

For a ternary alloy, the “occupation” site basis functions used by CASM have the value:

\[\begin{split}\pmb{\varphi} = \begin{bmatrix} 1 & 1 & 1\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}.\end{split}\]

Composition-centered site basis functions#

The composition-centered site basis functions give an expansion (with correlation values all equal to 0) for the idealized random configuration with a particular composition on each sublattice. The formulation is described in the documentation for the function make_orthonormal_discrete_functions(). The sublattice compositions can be specified using an array of dict, with the attributes:

  • “composition”: dict[str, float], Species the sublattice composition, using the the occupant names as keys (matching the prim occupants dictionary, occupants()), and sublattice composition as values. The values on a sublattice must sum to 1.0.

  • “sublat_indices”: list[int], Specifies the sublattices for which the composition values apply.

Example:

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": [
                {
                    "sublat_indices": [0, 1],
                    "composition": {"A": 0.25, "B": 0.75},
                },
                {
                    "sublat_indices": [2, 3],
                    "composition": {"A": 0.75, "B": 0.25},
                }
            ]
        }
    },
)

Only one sublattice in each asymmetric unit with >1 allowed occupant is required to be given. The specified composition is used to construct discrete basis functions on one site and then symmetry is used to construct an equivalent basis on other sites in the asymmetric unit.

For anisotropic occupants there may be multiple ways consistent with the prim factor group to construct the site basis functions on other sites (i.e. the choice of which spin state or molecular orientation of an occupant gets site basis function values of -1 or +1 may be arbitrary as long as it is done consistently). The particular choice made is based on the order in which symmetry operations are sorted in the prim factor group and should be consistent for a particular choice of prim.

An exception will be raised if sublattices in different asymmetric units are incorrectly grouped, or if no site is given for an asymmetric unit with >1 allowed occupant.

Directly-set site basis functions#

Warning

With this method it is possible to incorrectly use site basis functions that are not consistent with the symmetry of the prim. It should be considered a feature for developers and advanced users who understand how to check the results.

The site basis functions can be directly specified on each sublattice using an array of dict, with the attributes:

  • “value”: list[list[float], Species the site basis function values, \(\varphi_{ms}\), where the row index, \(m\), corresponds to a function index, and the column, \(s\), is the site occupation index. One row must be the vector of ones.

  • “sublat_indices”: list[int], Specifies the sublattices for which the site basis function values apply.

Example:

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": [
                {
                    "sublat_indices": [0, 1],
                    "value": [
                        [1., 1., 1.],
                        [0., 1., 0.],
                        [0., 0., 1.],
                    ]
                },
                {
                    "sublat_indices": [2, 3],
                    "value": [
                        [0., 1., 0.],
                        [0., 0., 1.],
                        [1., 1., 1.],
                    ]
                }
            ]
        }
    },
)

Magnetic spin site basis functions#

Tip

DoF specs as described in this section are planned but not yet implemented.

For magnetic spin DoF (“<flavor>magspin”), the dof_specs parameter is used to specify the maximum order of spherical harmonic site basis functions.

CASM generates spherical harmonic site basis functions of magnetic spin continuous DoFs. The maximum polynomial order of the site basis functions is given by the max_poly_order parameter.

Example:

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "NCmagspin": {
            "max_poly_order": 5
        }
    },
)

Maximum polynomial order#

By default, for a given cluster orbit, polynomials of order up to the cluster size are created. For functions of continuous degrees of freedom (DoF), higher order polynomials are usually necessary and can be requested either on a per-orbit-branch or global basis, where an “orbit branch” is the set of cluster orbits with the same number of sites per cluster. The most specific level specified is used. Orbit branches are specified using the string value of the cluster size as a key.

Examples#

Occupation DoF#

Example: Chebychev site basis functions#

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": "chebychev",
        }
    },
)

Example: Occupation site basis functions#

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": "occupation",
        }
    },
)

Example: Composition-centered site basis functions#

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": [
                {
                    "sublat_indices": [0, 1],
                    "composition": {"A": 0.25, "B": 0.75},
                },
                {
                    "sublat_indices": [2, 3],
                    "composition": {"A": 0.75, "B": 0.25},
                }
            ]
        }
    },
)

Example: Directly set site basis function values#

Warning

With this method it is possible to incorrectly use site basis functions that are not consistent with the symmetry of the prim. It should be considered a feature for developers and advanced users who understand how to check the results.

basis_function_specs = BasisFunctionSpecs(
    dof_specs={
        "occ": {
            "site_basis_functions": [
                {
                    "sublat_indices": [0, 1],
                    "value": [
                        [1., 1., 1.],
                        [0., 1., 0.],
                        [0., 0., 1.],
                    ]
                },
                {
                    "sublat_indices": [2, 3],
                    "value": [
                        [0., 1., 0.],
                        [0., 0., 1.],
                        [1., 1., 1.],
                    ]
                }
            ]
        }
    },
)

Strain DoF#

Example: Hencky strain DoF#

With maximum polynomial order 5:

basis_function_specs = BasisFunctionSpecs(
    max_poly_order=5,
)

Strain and occupation DoF#

Example: Coupled strain and occupation DoF (1)#

With:

  • “occupation” site basis functions for the discrete occupants

  • maximum polynomial order 5, which includes both strain and discrete DoF variables for the cluster functions.

basis_function_specs = BasisFunctionSpecs(
    dofs=["occ"],
    dof_specs={
        "occ": {
            "site_basis_functions": "occupation",
        }
    },
    global_max_poly_order=5,
)

Example: Coupled strain and occupation DoF (2)#

With:

  • “occupation” site basis functions for the discrete occupants

  • global maximum polynomial order 5, which includes both strain and discrete DoF variables for the cluster functions.

  • point- and pair-cluster branch maximum polynomial order 7,

  • null-cluster (strain-only) maximum polynomial order 8.

basis_function_specs = BasisFunctionSpecs(
    dofs=["occ"],
    dof_specs={
        "occ": {
            "site_basis_functions": "occupation",
        }
    },
    global_max_poly_order=5,
    orbit_branch_max_poly_order={
        "0": 8,
        "1": 7,
        "2": 7,
    }
)