@@ -58,11 +58,13 @@ def __init__(
58
58
structure : Structure ,
59
59
filename_ICOHP : str = "ICOHPLIST.lobster" ,
60
60
are_coops : bool = False ,
61
+ are_cobis : bool = False ,
61
62
valences : list [int | float ] | None = None ,
62
63
limits : tuple [float , float ] | None = None ,
63
64
additional_condition : int = 0 ,
64
65
only_bonds_to : list [str ] | None = None ,
65
66
perc_strength_ICOHP : float = 0.15 ,
67
+ noise_cutoff : float = 0.1 ,
66
68
valences_from_charges : bool = False ,
67
69
filename_CHARGE : str | None = None ,
68
70
which_charge : str = "Mulliken" ,
@@ -76,12 +78,13 @@ def __init__(
76
78
"""
77
79
78
80
Args:
79
- filename_ICOHP: (str) Path to ICOHPLIST.lobster
80
- structure: (Structure): typically constructed by Structure.from_file("POSCAR")
81
+ filename_ICOHP: (str) Path to ICOHPLIST.lobster or ICOOPLIST.lobster or ICOBILIST.lobster
82
+ structure: (Structure) typically constructed by Structure.from_file("POSCAR")
81
83
are_coops: (bool) if True, the file is a ICOOPLIST.lobster and not a ICOHPLIST.lobster; only tested for
82
84
ICOHPLIST.lobster so far
85
+ are_cobis: (bool) if True, the file is a ICOBILIST.lobster and not a ICOHPLIST.lobster
83
86
valences: (list[int | float]): gives valence/charge for each element
84
- limits (tuple[float, float] | None): limit to decide which ICOHPs should be considered
87
+ limits (tuple[float, float] | None): limit to decide which ICOHPs (ICOOP or ICOBI) should be considered
85
88
additional_condition (int): Additional condition that decides which kind of bonds will be considered
86
89
NO_ADDITIONAL_CONDITION = 0
87
90
ONLY_ANION_CATION_BONDS = 1
@@ -93,7 +96,8 @@ def __init__(
93
96
only_bonds_to: (list[str]) will only consider bonds to certain elements (e.g. ["O"] for oxygen)
94
97
perc_strength_ICOHP: if no limits are given, this will decide which icohps will still be considered (
95
98
relative to
96
- the strongest ICOHP)
99
+ the strongest ICOHP (ICOOP or ICOBI)
100
+ noise_cutoff: if provided hardcodes the lower limit of icohps considered
97
101
valences_from_charges: if True and path to CHARGE.lobster is provided, will use Lobster charges (
98
102
Mulliken) instead of valences
99
103
filename_CHARGE: (str) Path to Charge.lobster
@@ -108,16 +112,18 @@ def __init__(
108
112
id_blist_sg2: (str) Identity of data in filename_blist_sg2,
109
113
e.g., "icoop" or "icobi".
110
114
"""
111
- self .ICOHP = Icohplist (are_coops = are_coops , filename = filename_ICOHP )
115
+ self .ICOHP = Icohplist (are_coops = are_coops , are_cobis = are_cobis , filename = filename_ICOHP )
112
116
self .Icohpcollection = self .ICOHP .icohpcollection
113
117
self .structure = structure
114
118
self .limits = limits
115
119
self .only_bonds_to = only_bonds_to
116
120
self .adapt_extremum_to_add_cond = adapt_extremum_to_add_cond
117
121
self .are_coops = are_coops
122
+ self .are_cobis = are_cobis
118
123
self .add_additional_data_sg = add_additional_data_sg
119
124
self .filename_blist_sg1 = filename_blist_sg1
120
125
self .filename_blist_sg2 = filename_blist_sg2
126
+ self .noise_cutoff = noise_cutoff
121
127
122
128
allowed_arguments = ["icoop" , "icobi" ]
123
129
if id_blist_sg1 .lower () not in allowed_arguments or id_blist_sg2 .lower () not in allowed_arguments :
@@ -152,9 +158,6 @@ def __init__(
152
158
are_cobis = are_cobis_id2 ,
153
159
)
154
160
155
- if are_coops :
156
- raise ValueError ("Algorithm only works correctly for ICOHPLIST.lobster" )
157
-
158
161
# will check if the additional condition is correctly delivered
159
162
if additional_condition not in range (7 ):
160
163
raise ValueError (f"Unexpected { additional_condition = } , must be one of { list (range (7 ))} " )
@@ -364,12 +367,12 @@ def get_info_icohps_to_neighbors(self, isites=None, onlycation_isites=True):
364
367
"""
365
368
This method returns information on the icohps of neighbors for certain sites as identified by their site id.
366
369
This is useful for plotting the relevant cohps of a site in the structure.
370
+ (could be ICOOPLIST.lobster or ICOHPLIST.lobster or ICOBILIST.lobster)
367
371
368
372
Args:
369
373
isites: list of site ids. If isite==None, all isites will be used to add the icohps of the neighbors
370
374
onlycation_isites: if True and if isite==None, it will only analyse the sites of the cations
371
375
372
-
373
376
Returns: ICOHPNeighborsInfo
374
377
"""
375
378
if self .valences is None and onlycation_isites :
@@ -415,7 +418,8 @@ def plot_cohps_of_neighbors(
415
418
integrated = False ,
416
419
):
417
420
"""
418
- Will plot summed cohps (please be careful in the spin polarized case (plots might overlap (exactly!)).
421
+ Will plot summed cohps or cobis or coops
422
+ (please be careful in the spin polarized case (plots might overlap (exactly!)).
419
423
420
424
Args:
421
425
isites: list of site ids, if isite==[], all isites will be used to add the icohps of the neighbors
@@ -429,12 +433,12 @@ def plot_cohps_of_neighbors(
429
433
integrated: bool, if true will show integrated cohp instead of cohp
430
434
431
435
Returns:
432
- plt of the cohps
436
+ plt of the cohps or coops or cobis
433
437
"""
434
438
# include COHPPlotter and plot a sum of these COHPs
435
439
# might include option to add Spin channels
436
440
# implement only_bonds_to
437
- cp = CohpPlotter ()
441
+ cp = CohpPlotter (are_cobis = self . are_cobis , are_coops = self . are_coops )
438
442
439
443
plotlabel , summed_cohp = self .get_info_cohps_to_neighbors (
440
444
path_to_COHPCAR ,
@@ -465,19 +469,19 @@ def get_info_cohps_to_neighbors(
465
469
summed_spin_channels = False ,
466
470
):
467
471
"""
468
- Return info about the cohps as a summed cohp object and a label
472
+ Return info about the cohps (coops or cobis) as a summed cohp object and a label
469
473
from all sites mentioned in isites with neighbors.
470
474
471
475
Args:
472
- path_to_COHPCAR: str, path to COHPCAR
476
+ path_to_COHPCAR: str, path to COHPCAR or COOPCAR or COBICAR
473
477
isites: list of int that indicate the number of the site
474
478
only_bonds_to: list of str, e.g. ["O"] to only show cohps of anything to oxygen
475
479
onlycation_isites: if isites=None, only cation sites will be returned
476
480
per_bond: will normalize per bond
477
481
summed_spin_channels: will sum all spin channels
478
482
479
- Returns: label for cohp (str), CompleteCohp object which describes all cohps of the sites as given by isites
480
- and the other parameters
483
+ Returns: label for cohp (str), CompleteCohp object which describes all cohps (coops or cobis) of the sites
484
+ as given by isites and the other parameters
481
485
"""
482
486
# TODO: add options for orbital-resolved cohps
483
487
(
@@ -497,7 +501,13 @@ def get_info_cohps_to_neighbors(
497
501
self .structure .to (filename = path , fmt = "POSCAR" )
498
502
499
503
if not hasattr (self , "completecohp" ):
500
- self .completecohp = CompleteCohp .from_file (fmt = "LOBSTER" , filename = path_to_COHPCAR , structure_file = path )
504
+ self .completecohp = CompleteCohp .from_file (
505
+ fmt = "LOBSTER" ,
506
+ filename = path_to_COHPCAR ,
507
+ structure_file = path ,
508
+ are_coops = self .are_coops ,
509
+ are_cobis = self .are_cobis ,
510
+ )
501
511
502
512
# will check that the number of bonds in ICOHPLIST and COHPCAR are identical
503
513
# further checks could be implemented
@@ -1117,6 +1127,19 @@ def _determine_unit_cell(site):
1117
1127
1118
1128
return unitcell
1119
1129
1130
+ def _adapt_extremum_to_add_cond (self , list_icohps , percentage ):
1131
+ """
1132
+ Convinicence method for returning the extremum of the given icohps or icoops or icobis list
1133
+
1134
+ Args:
1135
+ list_icohps: can be a list of icohps or icobis or icobis
1136
+
1137
+ Returns: min value of input list of icohps / max value of input list of icobis or icobis
1138
+ """
1139
+
1140
+ which_extr = min if not self .are_coops and not self .are_cobis else max
1141
+ return which_extr (list_icohps ) * percentage
1142
+
1120
1143
def _get_limit_from_extremum (
1121
1144
self ,
1122
1145
icohpcollection ,
@@ -1130,12 +1153,14 @@ def _get_limit_from_extremum(
1130
1153
1131
1154
Args:
1132
1155
icohpcollection: icohpcollection object
1133
- percentage: will determine which ICOHPs will be considered (only 0.15 from the maximum value)
1156
+ percentage: will determine which ICOHPs or ICOOP or ICOBI will be considered
1157
+ (only 0.15 from the maximum value)
1134
1158
adapt_extremum_to_add_cond: should the extrumum be adapted to the additional condition
1135
1159
additional_condition: additional condition to determine which bonds are relevant
1136
- Returns: [-float('inf'), min(max_icohp*0.15,-0.1)]
1160
+
1161
+ Returns: [-inf, min(strongest_icohp*0.15,-noise_cutoff)] / [max(strongest_icohp*0.15, noise_cutoff),inf]
1137
1162
"""
1138
- # TODO: make it work for COOPs/COBIs
1163
+
1139
1164
if not adapt_extremum_to_add_cond or additional_condition == 0 :
1140
1165
extremum_based = icohpcollection .extremum_icohpvalue (summed_spin_channels = True ) * percentage
1141
1166
elif additional_condition == 1 :
@@ -1150,15 +1175,16 @@ def _get_limit_from_extremum(
1150
1175
if (val1 < 0.0 < val2 ) or (val2 < 0.0 < val1 ):
1151
1176
list_icohps .append (value .summed_icohp )
1152
1177
1153
- extremum_based = min (list_icohps ) * percentage
1178
+ extremum_based = self . _adapt_extremum_to_add_cond (list_icohps , percentage )
1154
1179
1155
1180
elif additional_condition == 2 :
1156
1181
# NO_ELEMENT_TO_SAME_ELEMENT_BONDS
1157
1182
list_icohps = []
1158
1183
for value in icohpcollection ._icohplist .values ():
1159
1184
if value ._atom1 .rstrip ("0123456789" ) != value ._atom2 .rstrip ("0123456789" ):
1160
1185
list_icohps .append (value .summed_icohp )
1161
- extremum_based = min (list_icohps ) * percentage
1186
+
1187
+ extremum_based = self ._adapt_extremum_to_add_cond (list_icohps , percentage )
1162
1188
1163
1189
elif additional_condition == 3 :
1164
1190
# ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 3
@@ -1175,13 +1201,17 @@ def _get_limit_from_extremum(
1175
1201
and value ._atom1 .rstrip ("0123456789" ) != value ._atom2 .rstrip ("0123456789" )
1176
1202
):
1177
1203
list_icohps .append (value .summed_icohp )
1178
- extremum_based = min (list_icohps ) * percentage
1204
+
1205
+ extremum_based = self ._adapt_extremum_to_add_cond (list_icohps , percentage )
1206
+
1179
1207
elif additional_condition == 4 :
1180
1208
list_icohps = []
1181
1209
for value in icohpcollection ._icohplist .values ():
1182
1210
if value ._atom1 .rstrip ("0123456789" ) == "O" or value ._atom2 .rstrip ("0123456789" ) == "O" :
1183
1211
list_icohps .append (value .summed_icohp )
1184
- extremum_based = min (list_icohps ) * percentage
1212
+
1213
+ extremum_based = self ._adapt_extremum_to_add_cond (list_icohps , percentage )
1214
+
1185
1215
elif additional_condition == 5 :
1186
1216
# DO_NOT_CONSIDER_ANION_CATION_BONDS=5
1187
1217
list_icohps = []
@@ -1193,7 +1223,8 @@ def _get_limit_from_extremum(
1193
1223
1194
1224
if (val1 > 0.0 and val2 > 0.0 ) or (val1 < 0.0 and val2 < 0.0 ):
1195
1225
list_icohps .append (value .summed_icohp )
1196
- extremum_based = min (list_icohps ) * percentage
1226
+
1227
+ extremum_based = self ._adapt_extremum_to_add_cond (list_icohps , percentage )
1197
1228
1198
1229
elif additional_condition == 6 :
1199
1230
# ONLY_CATION_CATION_BONDS=6
@@ -1206,13 +1237,17 @@ def _get_limit_from_extremum(
1206
1237
1207
1238
if val1 > 0.0 and val2 > 0.0 :
1208
1239
list_icohps .append (value .summed_icohp )
1209
- extremum_based = min (list_icohps ) * percentage
1210
1240
1211
- # if not self.are_coops:
1212
- max_here = min (extremum_based , - 0.1 )
1213
- return - float ("inf" ), max_here
1214
- # else:
1215
- # return extremum_based, 100000
1241
+ extremum_based = self ._adapt_extremum_to_add_cond (list_icohps , percentage )
1242
+
1243
+ if not self .are_coops and not self .are_cobis :
1244
+ max_here = min (extremum_based , - self .noise_cutoff ) if self .noise_cutoff is not None else extremum_based
1245
+ return - float ("inf" ), max_here
1246
+ if self .are_coops or self .are_cobis :
1247
+ min_here = max (extremum_based , self .noise_cutoff ) if self .noise_cutoff is not None else extremum_based
1248
+ return min_here , float ("inf" )
1249
+
1250
+ return None
1216
1251
1217
1252
1218
1253
class LobsterLightStructureEnvironments (LightStructureEnvironments ):
0 commit comments