1919import numpy as np
2020from monty .dev import deprecated , requires
2121from monty .serialization import loadfn
22- from ruamel .yaml import YAML
23- from scipy .spatial import Voronoi
24-
2522from pymatgen .analysis .bond_valence import BV_PARAMS , BVAnalyzer
2623from pymatgen .analysis .graphs import MoleculeGraph , StructureGraph
2724from pymatgen .analysis .molecule_structure_comparator import CovalentRadius
2825from pymatgen .core import Element , IStructure , PeriodicNeighbor , PeriodicSite , Site , Species , Structure
26+ from ruamel .yaml import YAML
27+ from scipy .spatial import Voronoi
2928
3029try :
3130 from openbabel import openbabel
3534if TYPE_CHECKING :
3635 from typing import Any
3736
38- from typing_extensions import Self
39-
4037 from pymatgen .core .composition import SpeciesLike
4138 from pymatgen .util .typing import Tuple3Ints
39+ from typing_extensions import Self
4240
4341
4442__author__ = "Shyue Ping Ong, Geoffroy Hautier, Sai Jayaraman, "
@@ -1161,7 +1159,7 @@ def _is_in_targets(site, targets):
11611159 targets ([Element]) List of elements
11621160
11631161 Returns:
1164- bool : Whether this site contains a certain list of elements
1162+ boolean : Whether this site contains a certain list of elements
11651163 """
11661164 elems = _get_elements (site )
11671165 return all (elem in targets for elem in elems )
@@ -1218,7 +1216,7 @@ def __init__(
12181216
12191217 # Update any user preference elemental radii
12201218 if el_radius_updates :
1221- self .el_radius |= el_radius_updates
1219+ self .el_radius . update ( el_radius_updates )
12221220
12231221 @property
12241222 def structures_allowed (self ) -> bool :
@@ -1984,7 +1982,7 @@ def get_okeeffe_distance_prediction(el1, el2):
19841982 """Get an estimate of the bond valence parameter (bond length) using
19851983 the derived parameters from 'Atoms Sizes and Bond Lengths in Molecules
19861984 and Crystals' (O'Keeffe & Brese, 1991). The estimate is based on two
1987- experimental parameters: r and c. The value for r is based off radius,
1985+ experimental parameters: r and c. The value for r is based off radius,
19881986 while c is (usually) the Allred-Rochow electronegativity. Values used
19891987 are *not* generated from pymatgen, and are found in
19901988 'okeeffe_params.json'.
@@ -2755,7 +2753,7 @@ def get_type(self, index):
27552753 raise ValueError ("Index for getting order parameter type out-of-bounds!" )
27562754 return self ._types [index ]
27572755
2758- def get_parameters (self , index : int ) -> list [ float ] :
2756+ def get_parameters (self , index ) :
27592757 """Get list of floats that represents
27602758 the parameters associated
27612759 with calculation of the order
@@ -2764,10 +2762,12 @@ def get_parameters(self, index: int) -> list[float]:
27642762 inputted because of processing out of efficiency reasons.
27652763
27662764 Args:
2767- index (int): index of order parameter for which to return associated params.
2765+ index (int):
2766+ index of order parameter for which associated parameters
2767+ are to be returned.
27682768
27692769 Returns:
2770- list [float]: parameters of a given OP.
2770+ [float]: parameters of a given OP.
27712771 """
27722772 if index < 0 or index >= len (self ._types ):
27732773 raise ValueError ("Index for getting parameters associated with order parameter calculation out-of-bounds!" )
@@ -3990,7 +3990,7 @@ def get_nn_data(self, structure: Structure, n: int, length=None):
39903990 nn_info .append (entry )
39913991 cn = len (nn_info )
39923992 cn_nninfo [cn ] = nn_info
3993- cn_weights [cn ] = self ._semicircle_integral (dist_bins , idx )
3993+ cn_weights [cn ] = self ._quadrant_integral (dist_bins , idx )
39943994
39953995 # add zero coord
39963996 cn0_weight = 1 - sum (cn_weights .values ())
@@ -4047,10 +4047,13 @@ def get_cn_dict(self, structure: Structure, n: int, use_weights: bool = False, *
40474047 return super ().get_cn_dict (structure , n , use_weights )
40484048
40494049 @staticmethod
4050- def _semicircle_integral (dist_bins , idx ) :
4050+ def _semicircle_integral (dist_bins : list , idx : int ) -> float :
40514051 """
40524052 An internal method to get an integral between two bounds of a unit
40534053 semicircle. Used in algorithm to determine bond probabilities.
4054+ This function has an issue, which is detailed at
4055+ https://github.com/materialsproject/pymatgen/issues/3973.
4056+ Therefore, _quadrant_integral is now the method of choice.
40544057
40554058 Args:
40564059 dist_bins: (float) list of all possible bond weights
@@ -4075,6 +4078,35 @@ def _semicircle_integral(dist_bins, idx):
40754078
40764079 return (area1 - area2 ) / (0.25 * math .pi * radius ** 2 )
40774080
4081+ @staticmethod
4082+ def _quadrant_integral (dist_bins : list , idx : int ) -> float :
4083+ """
4084+ An internal method to get an integral between two bounds of a unit
4085+ quadrant. Used in algorithm to determine bond probabilities.
4086+
4087+ Args:
4088+ dist_bins: (float) list of all possible bond weights
4089+ idx: (float) index of starting bond weight
4090+
4091+ Returns:
4092+ float: integral of portion of unit quadrant
4093+ """
4094+ radius = 1
4095+
4096+ x1 = dist_bins [idx ]
4097+ x2 = dist_bins [idx + 1 ]
4098+
4099+ areaquarter = 0.25 * math .pi * radius ** 2
4100+
4101+ area1 = areaquarter - 0.5 * (radius ** 2 * math .acos (
4102+ 1 - x1 / radius ) - (radius - x1 ) * math .sqrt (
4103+ 2 * radius * x1 - x1 ** 2 ))
4104+ area2 = areaquarter - 0.5 * (radius ** 2 * math .acos (
4105+ 1 - x2 / radius ) - (radius - x2 ) * math .sqrt (
4106+ 2 * radius * x2 - x2 ** 2 ))
4107+
4108+ return (area2 - area1 ) / areaquarter
4109+
40784110 @staticmethod
40794111 def transform_to_length (nn_data , length ):
40804112 """
0 commit comments