@@ -1063,20 +1063,65 @@ def spin(self) -> float | None:
1063
1063
1064
1064
@property
1065
1065
def full_electronic_structure (self ) -> list [tuple [int , str , int ]]:
1066
- """Full electronic structure as tuple. Not implemented for Species as of now."""
1067
- raise NotImplementedError
1066
+ """
1067
+ Full electronic structure as tuple.
1068
+
1069
+ If the oxidation state is non-zero, it is assumed that the Species adopts
1070
+ the same electronic configuration as the element with the same number of total
1071
+ electrons as the Species. For example, Fe+3 would have the same electronic
1072
+ structure as V, which has 23 electrons (26 for Fe minus 3 to get the +3 oxidation
1073
+ state)
1074
+ """
1075
+ if self .oxi_state != 0 :
1076
+ # adopt the electronic configuration of the element with the same atomic number
1077
+ # as this element, +/- the associated number of electrons
1078
+ return Element .from_Z (self .element .Z - self .oxi_state ).full_electronic_structure
1079
+
1080
+ return self .element .full_electronic_structure
1068
1081
1069
1082
@property
1070
- def electronic_structure (self ) -> list [tuple [int , str , int ]]:
1071
- """Electronic structure as tuple. Not implemented for Species as of now."""
1072
- raise NotImplementedError
1083
+ def electronic_structure (self ) -> str :
1084
+ """
1085
+ Electronic structure as string, with only valence electrons.
1086
+ e.g. The electronic structure for Fe+3 is represented as '[Ar].4s2.3d3'.
1087
+
1088
+ If the oxidation state is non-zero, it is assumed that the Species adopts
1089
+ the same electronic configuration as the element with the same number of total
1090
+ electrons as the Species. For example, Fe+3 would have the same electronic
1091
+ structure as V, which has 23 electrons (26 for Fe minus 3 to get the +3 oxidation
1092
+ state)
1093
+ """
1094
+ if self .oxi_state != 0 :
1095
+ # adopt the electronic configuration of the element with the same atomic number
1096
+ # as this element, +/- the associated number of electrons
1097
+ return Element .from_Z (self .element .Z - self .oxi_state ).electronic_structure
1098
+
1099
+ return self .element .electronic_structure
1073
1100
1074
1101
@property
1075
1102
def valence (self ) -> tuple [int | np .nan , int ]:
1076
1103
"""Valence subshell angular moment (L) and number of valence e- (v_e),
1077
- obtained from full electron config. Not implemented for Species as of now.
1104
+ obtained from full electron config.
1105
+
1106
+ L=0 for s orbital, 1 for p, 2 for d, and 3 for 4.
1078
1107
"""
1079
- raise NotImplementedError
1108
+ if self .group == 18 :
1109
+ return np .nan , 0 # The number of valence of noble gas is 0
1110
+
1111
+ L_symbols = "SPDFGHIKLMNOQRTUVWXYZ"
1112
+ valence : list [tuple [int , int ]] = []
1113
+ full_electron_config = self .full_electronic_structure
1114
+ last_orbital = full_electron_config [- 1 ]
1115
+ for n , l_symbol , ne in full_electron_config :
1116
+ idx = L_symbols .lower ().index (l_symbol )
1117
+ if ne < (2 * idx + 1 ) * 2 or (
1118
+ (n , l_symbol , ne ) == last_orbital and ne == (2 * idx + 1 ) * 2 and len (valence ) == 0
1119
+ ): # check for full last shell (e.g. column 2)
1120
+ valence .append ((idx , ne ))
1121
+ if len (valence ) > 1 :
1122
+ raise ValueError (f"{ self } has ambiguous valence" )
1123
+
1124
+ return valence [0 ]
1080
1125
1081
1126
@property
1082
1127
def ionic_radius (self ) -> float | None :
0 commit comments