Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coop coordination #280

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion nanoqm/workflows/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,10 @@ def merge(d1: Dict[str, Any], d2: Dict[str, Any]) -> Dict[str, Any]:
#: Input for a Crystal Orbital Overlap Population calculation
dict_coop = {
# List of the two elements to calculate the COOP for
"coop_elements": list}
"coop_elements": list,
# Coordination number to be considered for each of the two elements
Optional("elements_coordination", default=None): Or(None, list)
}


dict_merged_single_points = merge(dict_general_options, dict_single_points)
Expand Down
27 changes: 22 additions & 5 deletions nanoqm/workflows/workflow_coop.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
__all__ = ['workflow_crystal_orbital_overlap_population']

import logging
from typing import List, Tuple
from typing import List, Tuple, Union

import numpy as np

from scm.plams import Molecule

from qmflows.parsers.xyzParser import readXYZ

from nanoCAT.recipes import coordination_number
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nanoCAT must be included in the library requirements at setup.py


from ..common import (DictConfig, MolXYZ, h2ev,
number_spherical_functions_per_atom, retrieve_hdf5_data)
from ..integrals.multipole_matrices import compute_matrix_multipole
Expand Down Expand Up @@ -44,11 +48,14 @@ def workflow_crystal_orbital_overlap_population(config: DictConfig):
# Converting the xyz-file to a mol-file
mol = readXYZ(config.path_traj_xyz)

if config.elements_coordination is not None:
geometry = Molecule(config.path_traj_xyz)

# Computing the indices of the atomic orbitals of the two selected
# elements, and the overlap matrix that contains only elements related to
# the two elements
el_1_orbital_ind, el_2_orbital_ind, overlap_reduced = compute_overlap_and_atomic_orbitals(
mol, config)
mol, config, geometry)

# Compute the crystal orbital overlap population between the two selected
# elements
Expand Down Expand Up @@ -83,7 +90,8 @@ def get_eigenvalues_coefficients(config: DictConfig) -> Tuple[np.ndarray, np.nda


def compute_overlap_and_atomic_orbitals(
mol: MolXYZ, config: DictConfig) -> Tuple[List[int], List[int], List[int]]:
mol: MolXYZ, config: DictConfig,
geometry: Union[Molecule, None]) -> Tuple[List[int], List[int], List[int]]:
"""Compute the indices of the atomic orbitals of the two selected elements.

Computes the overlap matrix, containing only the elements related to those two elements.
Expand All @@ -102,8 +110,17 @@ def compute_overlap_and_atomic_orbitals(
element_1 = config["coop_elements"][0]
element_2 = config["coop_elements"][1]

element_1_index = [i for i, s in enumerate(mol) if element_1.lower() in s]
element_2_index = [i for i, s in enumerate(mol) if element_2.lower() in s]
if config["elements_coordination"] is None:
element_1_index = [i for i, s in enumerate(mol) if element_1.lower() in s]
element_2_index = [i for i, s in enumerate(mol) if element_2.lower() in s]

# For the two selected elements, only the indices corresponding to a given coordination number
else:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi, you can also make nano-CAT an optional dependency and then raise any potential ImportErrors whenever a code branch is reached that does require nano-CAT:

from typing import Optional
try:
    from nanoCAT import coordination_number
    NANOCAT_EX: Optional[ImportError] = None
except ImportError as ex:
    NANOCAT_EX = ex


def compute_overlap_and_atomic_orbitals(...):
    if config["elements_coordination"] is None:
        ...
    elif NANOCAT_EX is not None:
        raise NANOCAT_EX
    else:
        coord = coordination_number(geometry)
        ...

coord = coordination_number(geometry)
cn_1 = config["elements_coordination"][0]
cn_2 = config["elements_coordination"][1]
element_1_index = [i - 1 for i in coord[element_1][cn_1]]
element_2_index = [i - 1 for i in coord[element_2][cn_2]]

# Making a list of the indices of the atomic orbitals for each of the two
# elements
Expand Down