From db20afb7cea1f5ff34959667ab32ce27ea15ab33 Mon Sep 17 00:00:00 2001 From: Anselm Hahn Date: Tue, 22 Oct 2024 22:25:42 +0200 Subject: [PATCH 1/4] docs(deps): complete docs --- tanabesugano/matrices.py | 552 ++++++++++++++++++++------------------- 1 file changed, 278 insertions(+), 274 deletions(-) diff --git a/tanabesugano/matrices.py b/tanabesugano/matrices.py index a14ae18..d00869c 100644 --- a/tanabesugano/matrices.py +++ b/tanabesugano/matrices.py @@ -1,7 +1,11 @@ from __future__ import print_function import numpy as np +from numpy._typing._array_like import NDArray from numpy.linalg import eigh +from numpy.typing import NDArray + +from typing import Dict _sqrt2 = np.sqrt(2.0) _sqrt3 = np.sqrt(3.0) @@ -13,105 +17,106 @@ _3sqrt3 = _sqrt3 * 3.0 _3sqrt6 = _sqrt6 * 3.0 +Float64Array = NDArray[np.float64] class d2(object): - def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3801.0): + """ + Class representing the d2 configuration in ligand field theory. + """ + + def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3801.0) -> None: """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - Eigen-Energies of the atomic states depending on the crystalfield + Initializes the d2 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) - def A_1_1_states(self): - # - diagonal elements - + def A_1_1_states(self) -> Float64Array: + """Calculate the A_1_1 states.""" + # Diagonal elements AA = -8 * self.Dq + 10 * self.B + 5 * self.C BB = +12 * self.Dq + 8 * self.B + 4 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = _sqrt6 * (2 * self.B + self.C) states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def E_1_states(self): - # - diagonal elements + def E_1_states(self) -> Float64Array: + """Calculate the E_1 states.""" + # Diagonal elements AA = -8 * self.Dq + self.B + 2 * self.C BB = +12 * self.Dq + 2 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -_2sqrt3 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def T_1_2_states(self): - # - diagonal elements + def T_1_2_states(self) -> Float64Array: + """Calculate the T_1_2 states.""" + # Diagonal elements AA = -8 * self.Dq + self.B + 2 * self.C BB = +2 * self.Dq + 2 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = +_2sqrt3 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def T_3_1_states(self): - # - diagonal elements + def T_3_1_states(self) -> Float64Array: + """Calculate the T_3_1 states.""" + # Diagonal elements AA = -8 * self.Dq - 5 * self.B BB = +2 * self.Dq + 4 * self.B - # non diagonal elements - + # Non-diagonal elements AB = BA = 6 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensiona l array == eigenvalues of the diagonalized Ligand field Hamiltonian - """ + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. - return eigh(M)[0] + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - def solver(self): - # Ligand field independent states + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. + """ + return eigh(M)[0] - # Ligendfield single depentent states + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ + # Ligand field independent states GS = self.T_3_1_states()[0] T_1_1 = np.array([+2 * self.Dq + 4 * self.B + 2 * self.C]) - GS T_3_2 = np.array([+2 * self.Dq - 8 * self.B]) - GS A_3_2 = np.array([12 * self.Dq - 8 * self.B]) - GS - # Ligandfield dependent + + # Ligand field dependent states A_1_1 = self.A_1_1_states() - GS E_1 = self.E_1_states() - GS T_1_2 = self.T_1_2_states() - GS @@ -127,42 +132,31 @@ def solver(self): "3_A_2": A_3_2, } - class d3(object): - def __init__(self, Dq: float = 0.0, B: float = 918.0, C: float = 4133.0): - """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - Eigen-Energies of the atomic states depending on the crystalfield + """Class representing the d3 configuration in ligand field theory.""" + + def __init__(self, Dq: float = 0.0, B: float = 918.0, C: float = 4133.0) -> None: + """Initializes the d3 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) - def T_2_2_states(self): - # - diagonal elements - + def T_2_2_states(self) -> Float64Array: + """Calculate the T_2_2 states.""" + # Diagonal elements AA = -12 * self.Dq + 5 * self.C BB = -2 * self.Dq - 6 * self.B + 3 * self.C CC = -2 * self.Dq + 4 * self.B + 3 * self.C DD = +8 * self.Dq + 6 * self.B + 5 * self.C EE = +8 * self.Dq - 2 * self.B + 3 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -_3sqrt3 * self.B AC = CA = -5 * _sqrt3 * self.B AD = DA = 4 * self.B + 2 * self.C @@ -189,17 +183,16 @@ def T_2_2_states(self): return self.eigensolver(states) - def T_2_1_states(self): - # - diagonal elements - + def T_2_1_states(self) -> Float64Array: + """Calculate the T_2_1 states.""" + # Diagonal elements AA = -12 * self.Dq - 6 * self.B + 3 * self.C BB = -2 * self.Dq + 3 * self.C CC = -2 * self.Dq - 6 * self.B + 3 * self.C DD = +8 * self.Dq - 6 * self.B + 3 * self.C EE = +8 * self.Dq - 2 * self.B + 3 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -3 * self.B AC = CA = +3 * self.B AD = DA = 0.0 @@ -226,16 +219,15 @@ def T_2_1_states(self): return self.eigensolver(states) - def E_2_states(self): - # - diagonal elements - + def E_2_states(self) -> Float64Array: + """Calculate the E_2 states.""" + # Diagonal elements AA = -12 * self.Dq - 6 * self.B + 3 * self.C BB = -2 * self.Dq + 8 * self.B + 6 * self.C CC = -2 * self.Dq - 1 * self.B + 3 * self.C DD = +18 * self.Dq - 8 * self.B + 4 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -6 * _sqrt2 * self.B AC = CA = -_3sqrt2 * self.B AD = DA = 0.0 @@ -251,33 +243,37 @@ def E_2_states(self): return self.eigensolver(states) - def T_4_1_states(self): - # - diagonal elements - + def T_4_1_states(self) -> Float64Array: + """Calculate the T_4_1 states.""" + # Diagonal elements AA = -2 * self.Dq - 3 * self.B BB = +8 * self.Dq - 12 * self.B - # non diagonal elements - + # Non-diagonal elements AB = BA = 6 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensiona l array == eigenvalues of the diagonalized Ligand field Hamiltonian - """ + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. - return eigh(M)[0] + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - def solver(self): - # Ligand field independent states + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. + """ + return eigh(M)[0] - # Ligendfield single depentent states + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ + # Ligand field independent states GS = np.array([-12 * self.Dq - 15 * self.B]) A_4_2 = np.array([0], dtype=np.float64) @@ -286,7 +282,7 @@ def solver(self): A_2_1 = np.array([-2 * self.Dq - 11 * self.B + 3 * self.C]) - GS A_2_2 = np.array([-2 * self.Dq + 9 * self.B + 3 * self.C]) - GS - # Ligandfield dependent + # Ligand field dependent states T_2_2 = self.T_2_2_states() - GS T_2_1 = self.T_2_1_states() - GS E_2 = self.E_2_states() - GS @@ -305,31 +301,25 @@ def solver(self): class d4(object): - def __init__(self, Dq: float = 0.0, B: float = 965.0, C: float = 4449.0): + """Class representing the d4 configuration in ligand field theory.""" + + def __init__(self, Dq: float = 0.0, B: float = 965.0, C: float = 4449.0) -> None: """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - * Eigen-Energies of the atomic states depending on the crystalfield + Initializes the d4 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) - def T_3_1_states(self): - # - diagonal elements + def T_3_1_states(self) -> Float64Array: + """Calculate the T_3_1 states.""" + # Diagonal elements AA = -16 * self.Dq - 15 * self.B + 5 * self.C BB = -6 * self.Dq - 11 * self.B + 4 * self.C CC = -6 * self.Dq - 3 * self.B + 6 * self.C @@ -338,8 +328,7 @@ def T_3_1_states(self): FF = +4 * self.Dq - 11 * self.B + 4 * self.C GG = +14 * self.Dq - 16 * self.B + 5 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -_sqrt6 * self.B AC = CA = -_3sqrt2 * self.B AD = DA = _sqrt2 * (2 * self.B + self.C) @@ -381,9 +370,9 @@ def T_3_1_states(self): return self.eigensolver(states) - def T_1_2_states(self): - # diagonal elements - + def T_1_2_states(self) -> Float64Array: + """Calculate the T_1_2 states.""" + # Diagonal elements AA = -16 * self.Dq - 9 * self.B + 7 * self.C BB = -6 * self.Dq - 9 * self.B + 6 * self.C CC = -6 * self.Dq + 3 * self.B + 8 * self.C @@ -392,8 +381,7 @@ def T_1_2_states(self): FF = +4 * self.Dq + 5 * self.B + 8 * self.C GG = +14 * self.Dq + 7 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = _3sqrt2 * self.B AC = CA = -5 * _sqrt6 * self.B AD = DA = 0.0 @@ -435,17 +423,16 @@ def T_1_2_states(self): return self.eigensolver(states) - def A_1_1_states(self): - # diagonal elements - + def A_1_1_states(self) -> Float64Array: + """Calculate the A_1_1 states.""" + # Diagonal elements AA = -16 * self.Dq + 10 * self.C BB = -6 * self.Dq + 6 * self.C CC = +4 * self.Dq + 14 * self.B + 11 * self.C DD = +4 * self.Dq - 3 * self.B + 6 * self.C EE = +24 * self.Dq - 16 * self.B + 8 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -12 * _sqrt2 * self.B AC = CA = _sqrt2 * (4 * self.B + 2 * self.C) AD = DA = _2sqrt2 * self.B @@ -472,17 +459,16 @@ def A_1_1_states(self): return self.eigensolver(states) - def E_1_1_states(self): - # diagonal elements - + def E_1_1_states(self) -> Float64Array: + """Calculate the E_1_1 states.""" + # Diagonal elements AA = -16 * self.Dq - 9 * self.B + 7 * self.C BB = -6 * self.Dq - 6 * self.B + 6 * self.C CC = +4 * self.Dq + 5 * self.B + 8 * self.C DD = +4 * self.Dq + 6 * self.B + 9 * self.C EE = +4 * self.Dq - 3 * self.B + 6 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = 6 * self.B AC = CA = _sqrt2 * (2 * self.B + self.C) AD = DA = -2 * self.B @@ -509,17 +495,16 @@ def E_1_1_states(self): return self.eigensolver(states) - def T_3_2_states(self): - # diagonal elements - + def T_3_2_states(self) -> Float64Array: + """Calculate the T_3_2 states.""" + # Diagonal elements AA = -6 * self.Dq - 9 * self.B + 4 * self.C BB = -6 * self.Dq - 5 * self.B + 6 * self.C CC = +4 * self.Dq - 13 * self.B + 4 * self.C DD = +4 * self.Dq - 9 * self.B + 4 * self.C EE = +14 * self.Dq - 8 * self.B + 5 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -5 * _sqrt3 * self.B AC = CA = _sqrt6 * self.B AD = DA = _sqrt3 * self.B @@ -546,16 +531,16 @@ def T_3_2_states(self): return self.eigensolver(states) - def T_1_1_states(self): - # diagonal elements + def T_1_1_states(self) -> Float64Array: + """Calculate the T_1_1 states.""" + # Diagonal elements AA = -6 * self.Dq - 3 * self.B + 6 * self.C BB = -6 * self.Dq - 3 * self.B + 8 * self.C CC = +4 * self.Dq - 3 * self.B + 6 * self.C DD = +14 * self.Dq - 16 * self.B + 7 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = 5 * _sqrt3 * self.B AC = CA = 3 * self.B AD = DA = _sqrt6 * self.B @@ -571,15 +556,14 @@ def T_1_1_states(self): return self.eigensolver(states) - def E_3_1_states(self): - # diagonal elements - + def E_3_1_states(self) -> Float64Array: + """Calculate the E_3_1 states.""" + # Diagonal elements AA = -6 * self.Dq - 13 * self.B + 4 * self.C BB = -6 * self.Dq - 10 * self.B + 4 * self.C CC = +4 * self.Dq - 11 * self.B + 4 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -4 * self.B AC = CA = 0.0 @@ -589,52 +573,51 @@ def E_3_1_states(self): return self.eigensolver(states) - def A_3_2_states(self): - # diagonal elements - + def A_3_2_states(self) -> Float64Array: + """Calculate the A_3_2 states.""" + # Diagonal elements AA = -6 * self.Dq - 8 * self.B + 4 * self.C BB = +4 * self.Dq - 2 * self.B + 7 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = -12 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def A_1_2_states(self): - # diagonal elements + def A_1_2_states(self) -> Float64Array: + """Calculate the A_1_2 states.""" + # Diagonal elements AA = -6 * self.Dq - 12 * self.B + 6 * self.C BB = +4 * self.Dq - 3 * self.B + 6 * self.C - # non diagonal elements - + # Non-diagonal elements AB = BA = 6 * self.B states = np.array([[AA, AB], [BA, BB]]) return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensional array == eigenvalues of the diagonalized Ligand field Hamiltonian - """ + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. - return eigh(M)[0] + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - def solver(self): - # Ligand field independent states + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. + """ + return eigh(M)[0] - # A_6_1 = np.array( [ 0 ] ) # Starting value is -35. * B, but has to set to zero per definition - # E_4 = self.E_4_states( ) + 35 * self.B - # A_4_1 = np.array( [ -25 * self.B + 5 * self.C ] ) + 35 * self.B - # A_4_2 = np.array( [ -13 * self.B + 7 * self.C ] ) + 35 * self.B - - # Ligendfield single depentent states + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ + # Ligand field independent states GS = np.array([-6 * self.Dq - 21 * self.B]) E_5_1 = np.array([0], dtype=np.float64) @@ -642,7 +625,7 @@ def solver(self): A_3_1 = np.array([-6 * self.Dq - 12 * self.B + 4 * self.C]) - GS - # Ligandfield dependent + # Ligand field dependent states T_1_2 = self.T_1_2_states() - GS T_3_1 = self.T_3_1_states() - GS A_1_1 = self.A_1_1_states() - GS @@ -666,6 +649,7 @@ def solver(self): T_5_2 -= T_3_1[0] A_3_1 -= T_3_1[0] T_3_1 -= T_3_1[0] + return { "3_T_1": T_3_1, "1_T_2": T_1_2, @@ -683,30 +667,24 @@ def solver(self): class d5(object): - def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3850.0): + """Class representing the d5 configuration in ligand field theory.""" + def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3850.0) -> None: """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - * Eigen-Energies of the atomic states depending on the crystalfield + Initializes the d5 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) - def T_2_2_states(self): + def T_2_2_states(self) -> Float64Array: + """Calculate the T_2_2 states.""" + + # diagonal elements AA = -20 * self.Dq - 20 * self.B + 10 * self.C @@ -793,7 +771,8 @@ def T_2_2_states(self): return self.eigensolver(states) - def T_2_1_states(self): + def T_2_1_states(self) -> Float64Array: + """Calculate the T_2_1 states.""" # diagonal elements AA = -10 * self.Dq - 22 * self.B + 9 * self.C @@ -857,7 +836,8 @@ def T_2_1_states(self): return self.eigensolver(states) - def E_2_states(self): + def E_2_states(self) -> Float64Array: + """Calculate the E_2 states.""" # diagonal elements AA = -10 * self.Dq - 4 * self.B + 12 * self.C @@ -911,7 +891,8 @@ def E_2_states(self): return self.eigensolver(states) - def A_2_1_states(self): + def A_2_1_states(self) -> Float64Array: + """Calculate the A_2_1 states.""" # diagonal elements AA = -10 * self.Dq - 3 * self.B + 9 * self.C @@ -936,7 +917,8 @@ def A_2_1_states(self): return self.eigensolver(states) - def A_2_2_states(self): + def A_2_2_states(self) -> Float64Array: + """Calculate the A_2_2 states.""" # diagonal elements AA = -10 * self.Dq - 23 * self.B + 9 * self.C @@ -954,7 +936,8 @@ def A_2_2_states(self): return self.eigensolver(states) - def T_4_1_states(self): + def T_4_1_states(self) -> Float64Array: + """Calculate the T_4_1 states.""" # diagonal elements AA = -10 * self.Dq - 25 * self.B + 6 * self.C @@ -972,7 +955,8 @@ def T_4_1_states(self): return self.eigensolver(states) - def T_4_2_states(self): + def T_4_2_states(self) -> Float64Array: + """Calculate the T_4_2 states.""" # diagonal elements AA = -10 * self.Dq - 17 * self.B + 6 * self.C @@ -991,7 +975,8 @@ def T_4_2_states(self): return self.eigensolver(states) - def E_4_states(self): + def E_4_states(self) -> Float64Array: + """Calculate the E_4 states.""" # diagonal elements AA = -22 * self.B + 5 * self.C @@ -1005,15 +990,24 @@ def E_4_states(self): return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensional array == eigenvalues of the diagonalized Ligand field Hamiltonian + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. + + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. + + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. """ return eigh(M)[0] - def solver(self): + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. + + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states GS = -35 * self.B @@ -1063,30 +1057,22 @@ def solver(self): class d6(object): + """Class representing the d6 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 1065.0, C: float = 5120.0): """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - Eigen-Energies of the atomic states depending on the crystalfield + Initializes the d6 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) - def T_3_1_states(self): + def T_3_1_states(self) -> Float64Array: + """Calculate the T_3_1 states.""" # - diagonal elements AA = +16 * self.Dq - 15 * self.B + 5 * self.C @@ -1140,7 +1126,8 @@ def T_3_1_states(self): return self.eigensolver(states) - def T_1_2_states(self): + def T_1_2_states(self) -> Float64Array: + """Calculate the T_1_2 states.""" # diagonal elements AA = +16 * self.Dq - 9 * self.B + 7 * self.C @@ -1194,7 +1181,8 @@ def T_1_2_states(self): return self.eigensolver(states) - def A_1_1_states(self): + def A_1_1_states(self) -> Float64Array: + """Calculate the A_1_1 states.""" # diagonal elements AA = +16 * self.Dq + 10 * self.C @@ -1231,7 +1219,8 @@ def A_1_1_states(self): return self.eigensolver(states) - def E_1_1_states(self): + def E_1_1_states(self) -> Float64Array: + """Calculate the E_1_1 states.""" # diagonal elements AA = +16 * self.Dq - 9 * self.B + 7 * self.C @@ -1268,7 +1257,8 @@ def E_1_1_states(self): return self.eigensolver(states) - def T_3_2_states(self): + def T_3_2_states(self) -> Float64Array: + """Calculate the T_3_2 states.""" # diagonal elements AA = +6 * self.Dq - 9 * self.B + 4 * self.C @@ -1305,7 +1295,8 @@ def T_3_2_states(self): return self.eigensolver(states) - def T_1_1_states(self): + def T_1_1_states(self) -> Float64Array: + """Calculate the T_1_1 states.""" # diagonal elements AA = +6 * self.Dq - 3 * self.B + 6 * self.C @@ -1330,7 +1321,8 @@ def T_1_1_states(self): return self.eigensolver(states) - def E_3_1_states(self): + def E_3_1_states(self) -> Float64Array: + """Calculate the E_3_1 states.""" # diagonal elements AA = +6 * self.Dq - 13 * self.B + 4 * self.C @@ -1348,7 +1340,8 @@ def E_3_1_states(self): return self.eigensolver(states) - def A_3_2_states(self): + def A_3_2_states(self) -> Float64Array: + """Calculate the A_3_2 states.""" # diagonal elements AA = +6 * self.Dq - 8 * self.B + 4 * self.C @@ -1362,7 +1355,8 @@ def A_3_2_states(self): return self.eigensolver(states) - def A_1_2_states(self): + def A_1_2_states(self) -> Float64Array: + """Calculate the A_1_2 states.""" # diagonal elements AA = +6 * self.Dq - 12 * self.B + 6 * self.C @@ -1376,23 +1370,25 @@ def A_1_2_states(self): return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensional array == eigenvalues of the diagonalized Ligand field Hamiltonian + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. + + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. + + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. """ return eigh(M)[0] - def solver(self): - # Ligand field independent states + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. - # A_6_1 = np.array( [ 0 ] ) # Starting value is -35. * B, but has to set to zero per definition - # E_4 = self.E_4_states( ) + 35 * self.B - # A_4_1 = np.array( [ -25 * self.B + 5 * self.C ] ) + 35 * self.B - # A_4_2 = np.array( [ -13 * self.B + 7 * self.C ] ) + 35 * self.B + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ - # Ligendfield single depentent states GS = np.array([-4 * self.Dq - 21 * self.B]) @@ -1446,30 +1442,22 @@ def solver(self): class d7(object): + """Class for d7 configuration.""" + def __init__(self, Dq: float = 0.0, B: float = 971.0, C: float = 4499.0): - """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - * Eigen-Energies of the atomic states depending on the crystalfield + """Initializes the d7 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) def T_2_2_states(self): + """Calculate the T_2_2 states.""" # - diagonal elements AA = +12 * self.Dq + 5 * self.C @@ -1507,6 +1495,7 @@ def T_2_2_states(self): return self.eigensolver(states) def T_2_1_states(self): + """Calculate the T_2_1 states.""" # - diagonal elements AA = +12 * self.Dq - 6 * self.B + 3 * self.C @@ -1544,6 +1533,7 @@ def T_2_1_states(self): return self.eigensolver(states) def E_2_states(self): + """Calculate the E_2 states.""" # - diagonal elements AA = +12 * self.Dq - 6 * self.B + 3 * self.C @@ -1569,6 +1559,7 @@ def E_2_states(self): return self.eigensolver(states) def T_4_1_states(self): + """Calculate the T_4_1 states.""" # - diagonal elements AA = +2 * self.Dq - 3 * self.B @@ -1582,15 +1573,24 @@ def T_4_1_states(self): return self.eigensolver(states) - def eigensolver(self, M: np.ndarray): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensiona l array == eigenvalues of the diagonalized Ligand field Hamiltonian + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. + + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. + + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. """ return eigh(M)[0] - def solver(self): + def solver(self) -> Dict[str, np.ndarray]: + """Solve for all states and return a dictionary of results. + + Returns: + Dict[str, np.ndarray]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states # Ligandfield multi depnedent state become GS @@ -1639,28 +1639,19 @@ def solver(self): class d8(object): def __init__(self, Dq: float = 0.0, B: float = 1030.0, C: float = 4850.0): """ - parameter - --------- - All parameters in wavenumbers (cm-) - Dq: float - Crystalfield-Splitting - B: float - Racah-Parameter - C: float - Racah-Parameter - - returns - ------- - dictionary with elements of: - * Atomic-Termsymbols: str - * Eigen-Energies: float numpy-array - * Eigen-Energies of the atomic states depending on the crystalfield + Initializes the d8 configuration with given parameters. + + Args: + Dq (float): Crystal field splitting in wavenumbers (cm-1). + B (float): Racah parameter B in wavenumbers (cm-1). + C (float): Racah parameter C in wavenumbers (cm-1). """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) def A_1_1_states(self): + """Calculate the A_1_1 states.""" # - diagonal elements AA = +8 * self.Dq + 10 * self.B + 5 * self.C @@ -1675,6 +1666,7 @@ def A_1_1_states(self): return self.eigensolver(states) def E_1_states(self): + """Calculate the E_1 states.""" # - diagonal elements AA = +8 * self.Dq + self.B + 2 * self.C @@ -1689,6 +1681,7 @@ def E_1_states(self): return self.eigensolver(states) def T_1_2_states(self): + """Calculate the T_1_2 states.""" # - diagonal elements AA = +8 * self.Dq + self.B + 2 * self.C @@ -1703,6 +1696,8 @@ def T_1_2_states(self): return self.eigensolver(states) def T_3_1_states(self): + """Calculate the T_3_1 states.""" + # - diagonal elements AA = +8 * self.Dq - 5 * self.B @@ -1716,15 +1711,24 @@ def T_3_1_states(self): return self.eigensolver(states) - def eigensolver(self, M): - """ - :param M: 2 dimensional square array == TS matrics of Ligand field Hamiltonian - :return: 1 dimensiona l array == eigenvalues of the diagonalized Ligand field Hamiltonian + def eigensolver(self, M: Float64Array) -> Float64Array: + """Solve for the eigenvalues of the given matrix. + + Args: + M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. + + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamilton """ return eigh(M)[0] - def solver(self): + def solver(self) -> Dict[str, Float64Array]: + """Solve for all states and return a dictionary of results. + + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states # Ligendfield single depentent states From 1d297326a4c37bee036fda96218a3ff96e454a14 Mon Sep 17 00:00:00 2001 From: Anselm Hahn Date: Wed, 23 Oct 2024 06:23:55 +0200 Subject: [PATCH 2/4] feat: update version to 1.4.4 and add future annotations - Updated package version in __init__.py - Added future annotations import in tools.py and cmd.py - Refactored calculation method signature in batch.py - Added new dependencies in pyproject.toml and updated poetry.lock --- poetry.lock | 53 +++++++++++- pyproject.toml | 16 ++++ tanabesugano/__init__.py | 3 +- tanabesugano/batch.py | 7 +- tanabesugano/cmd.py | 15 +--- tanabesugano/matrices.py | 168 ++++++++++++++------------------------- tanabesugano/tools.py | 1 + 7 files changed, 137 insertions(+), 126 deletions(-) diff --git a/poetry.lock b/poetry.lock index daa2600..c5772bf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1261,6 +1261,33 @@ typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.1 [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] +[[package]] +name = "ruff" +version = "0.7.0" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.7.0-py3-none-linux_armv6l.whl", hash = "sha256:0cdf20c2b6ff98e37df47b2b0bd3a34aaa155f59a11182c1303cce79be715628"}, + {file = "ruff-0.7.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:496494d350c7fdeb36ca4ef1c9f21d80d182423718782222c29b3e72b3512737"}, + {file = "ruff-0.7.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:214b88498684e20b6b2b8852c01d50f0651f3cc6118dfa113b4def9f14faaf06"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630fce3fefe9844e91ea5bbf7ceadab4f9981f42b704fae011bb8efcaf5d84be"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:211d877674e9373d4bb0f1c80f97a0201c61bcd1e9d045b6e9726adc42c156aa"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:194d6c46c98c73949a106425ed40a576f52291c12bc21399eb8f13a0f7073495"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:82c2579b82b9973a110fab281860403b397c08c403de92de19568f32f7178598"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9af971fe85dcd5eaed8f585ddbc6bdbe8c217fb8fcf510ea6bca5bdfff56040e"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b641c7f16939b7d24b7bfc0be4102c56562a18281f84f635604e8a6989948914"}, + {file = "ruff-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d71672336e46b34e0c90a790afeac8a31954fd42872c1f6adaea1dff76fd44f9"}, + {file = "ruff-0.7.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ab7d98c7eed355166f367597e513a6c82408df4181a937628dbec79abb2a1fe4"}, + {file = "ruff-0.7.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1eb54986f770f49edb14f71d33312d79e00e629a57387382200b1ef12d6a4ef9"}, + {file = "ruff-0.7.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dc452ba6f2bb9cf8726a84aa877061a2462afe9ae0ea1d411c53d226661c601d"}, + {file = "ruff-0.7.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4b406c2dce5be9bad59f2de26139a86017a517e6bcd2688da515481c05a2cb11"}, + {file = "ruff-0.7.0-py3-none-win32.whl", hash = "sha256:f6c968509f767776f524a8430426539587d5ec5c662f6addb6aa25bc2e8195ec"}, + {file = "ruff-0.7.0-py3-none-win_amd64.whl", hash = "sha256:ff4aabfbaaba880e85d394603b9e75d32b0693152e16fa659a3064a85df7fce2"}, + {file = "ruff-0.7.0-py3-none-win_arm64.whl", hash = "sha256:10842f69c245e78d6adec7e1db0a7d9ddc2fff0621d730e61657b64fa36f207e"}, + {file = "ruff-0.7.0.tar.gz", hash = "sha256:47a86360cf62d9cd53ebfb0b5eb0e882193fc191c6d717e8bef4462bc3b9ea2b"}, +] + [[package]] name = "six" version = "1.16.0" @@ -1272,6 +1299,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "style" +version = "1.1.0" +description = "🌈 Terminal string styling" +optional = false +python-versions = "*" +files = [ + {file = "style-1.1.0-py2.py3-none-any.whl", hash = "sha256:6485a4bcb84629341a5fd1587fe3ac4887daa4741f0c8a1d01b9c3c8a263afe7"}, + {file = "style-1.1.0.tar.gz", hash = "sha256:8eb365fc15039b19b728bd4e6e85fb7daf24e7aeeec6a15a666f97484c564005"}, +] + [[package]] name = "tenacity" version = "9.0.0" @@ -1320,6 +1358,19 @@ files = [ {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, ] +[[package]] +name = "update" +version = "0.0.1" +description = "" +optional = false +python-versions = "*" +files = [ + {file = "update-0.0.1-py2.py3-none-any.whl", hash = "sha256:a25522b4bf60e3e3c1a3ff3ca3a4f5a328ac4b8ff400fdc9614483147e313323"}, +] + +[package.dependencies] +style = "1.1.0" + [[package]] name = "wcwidth" version = "0.2.13" @@ -1356,4 +1407,4 @@ plotly = ["plotly"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "f59d1f558858104329eb04fe0e9392843c2995c689ef2228a3c169d481f9d3d6" +content-hash = "0f5462b3336d27bed4f4b51164d8f09a721ffb5c64f660103dd73d6e7bf0038c" diff --git a/pyproject.toml b/pyproject.toml index e74cdef..e60e049 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ exclude = ["test/**/*.py", "example/**", "ts-diagrams/**"] matplotlib = "^3.4.2" prettytable = ">=2.1,<4.0" plotly = { version = "^5.13.1", optional = true } + update = "^0.0.1" [tool.poetry.group.dev.dependencies] pytest = ">=7.2,<9.0" @@ -58,6 +59,7 @@ exclude = ["test/**/*.py", "example/**", "ts-diagrams/**"] black = ">=22.12,<25.0" isort = "^5.11.4" pytest-console-scripts = "^1.3.1" + ruff = "^0.7.0" [build-system] requires = ["poetry-core>=1.0.0"] @@ -68,3 +70,17 @@ tanabesugano = "tanabesugano.cmd:cmd_line" [tool.poetry.extras] plotly = ["plotly"] + +[tool.ruff] +lint.select = ["ALL"] +lint.ignore = ["N806"] +target-version = "py38" +src = ["tanabesugano"] + +[tool.ruff.lint.isort] +known-first-party = ["umf"] +force-single-line = true +lines-between-types = 1 +lines-after-imports = 2 +known-third-party = ["poetry.core"] +required-imports = ["from __future__ import annotations"] diff --git a/tanabesugano/__init__.py b/tanabesugano/__init__.py index a0e60d3..b04970e 100644 --- a/tanabesugano/__init__.py +++ b/tanabesugano/__init__.py @@ -1,2 +1,3 @@ """tanabesugano: A Python package for Tanabe-Sugano diagrams.""" -__version__ = "1.4.3" + +__version__ = "1.4.4" diff --git a/tanabesugano/batch.py b/tanabesugano/batch.py index a023b2b..5c3ee44 100644 --- a/tanabesugano/batch.py +++ b/tanabesugano/batch.py @@ -58,14 +58,11 @@ def __init__( self._size = 10 self.result: List[dict] = [] - def calculation(self): - """ - Is filling the self.result with the iTS states of over-iterated energy range - """ + def calculation(self) -> None: + """Is filling the self.result with the iTS states of over-iterated energy range.""" for _Dq in self.Dq: for _B in self.B: for _C in self.C: - if self.d_count == 2: # d3 states = matrices.d2(Dq=_Dq, B=_B, C=_C).solver() self.result.append( diff --git a/tanabesugano/cmd.py b/tanabesugano/cmd.py index d5207ea..9a027dd 100644 --- a/tanabesugano/cmd.py +++ b/tanabesugano/cmd.py @@ -1,4 +1,6 @@ #!/usr/bin/env python + +from __future__ import annotations import argparse import matplotlib.pyplot as plt @@ -47,7 +49,6 @@ def __init__( self.C = C if slater: - self.B, self.C = tools.racah(B, C) self.nroot = nroots energy = np.linspace(0.0, self.Dq, nroots) @@ -74,7 +75,6 @@ def __init__( ) def plot(self) -> None: - # Figure one for classical Tanabe-Sugano-Diagram with B-dependency plt.figure(1) @@ -107,7 +107,6 @@ def label_plot(self, arg0: str, arg1: str, arg2: str) -> None: plt.xlabel(arg2) def savetxt(self) -> None: - pd.concat( [ self.df["delta_B"], @@ -170,7 +169,8 @@ def calculation(self) -> None: ) ) else: - raise ValueError("`d_count` must be in {2,3,4,5,6,7,8}") + msg = "The number of unpaired electrons should be between 2 and 8." + raise ValueError(msg) # Transform list of dictionaries to dictionary of arrays result = { @@ -195,37 +195,30 @@ def ci_cut(self, dq_ci: float = None) -> None: Extracting the atomic-termsymbols for a specific dq depending on the oxidation state """ if self.d_count == 2: # d2 - states = matrices.d2(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 3: # d3 - states = matrices.d3(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 4: # d4 - states = matrices.d4(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 5: # d5 - states = matrices.d5(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 6: # d6 - states = matrices.d6(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 7: # d7 - states = matrices.d7(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) elif self.d_count == 8: # d8 - states = matrices.d8(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() self.ts_print(states, dq_ci=dq_ci) diff --git a/tanabesugano/matrices.py b/tanabesugano/matrices.py index d00869c..947a7dc 100644 --- a/tanabesugano/matrices.py +++ b/tanabesugano/matrices.py @@ -3,9 +3,9 @@ import numpy as np from numpy._typing._array_like import NDArray from numpy.linalg import eigh -from numpy.typing import NDArray -from typing import Dict + +from typing import Dict, TypeAlias _sqrt2 = np.sqrt(2.0) _sqrt3 = np.sqrt(3.0) @@ -17,9 +17,49 @@ _3sqrt3 = _sqrt3 * 3.0 _3sqrt6 = _sqrt6 * 3.0 -Float64Array = NDArray[np.float64] +Float64Array: TypeAlias = NDArray[np.float64] + + +class LigandFieldTheory: + """Parent class for ligand field theory configurations.""" + + def __init__(self, Dq: float, B: float, C: float) -> None: + """ + Initializes the configuration with given parameters. + + Args: + dq (float): Crystal field splitting in wavenumbers (cm-1). + b (float): Racah parameter B in wavenumbers (cm-1). + c (float): Racah parameter C in wavenumbers (cm-1). + """ + self.Dq = np.float64(Dq) + self.B = np.float64(B) + self.C = np.float64(C) + + def eigensolver(self, matrix: Float64Array) -> Float64Array: + """ + Solve for the eigenvalues of the given matrix. + + Args: + matrix (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. + + Returns: + Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. + """ + return eigh(matrix)[0] + + def solver(self) -> Dict[str, Float64Array]: + """ + Solve for all states and return a dictionary of results. + + Returns: + Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ + msg = "Subclasses should implement this method." + raise NotImplementedError(msg) + -class d2(object): +class d2(LigandFieldTheory): """ Class representing the d2 configuration in ligand field theory. """ @@ -33,9 +73,7 @@ def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3801.0) -> None B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def A_1_1_states(self) -> Float64Array: """Calculate the A_1_1 states.""" @@ -92,17 +130,6 @@ def T_3_1_states(self) -> Float64Array: return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - return eigh(M)[0] - def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. @@ -132,7 +159,8 @@ def solver(self) -> Dict[str, Float64Array]: "3_A_2": A_3_2, } -class d3(object): + +class d3(LigandFieldTheory): """Class representing the d3 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 918.0, C: float = 4133.0) -> None: @@ -143,9 +171,7 @@ def __init__(self, Dq: float = 0.0, B: float = 918.0, C: float = 4133.0) -> None B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def T_2_2_states(self) -> Float64Array: """Calculate the T_2_2 states.""" @@ -256,17 +282,6 @@ def T_4_1_states(self) -> Float64Array: return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - return eigh(M)[0] - def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. @@ -300,7 +315,7 @@ def solver(self) -> Dict[str, Float64Array]: } -class d4(object): +class d4(LigandFieldTheory): """Class representing the d4 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 965.0, C: float = 4449.0) -> None: @@ -312,9 +327,7 @@ def __init__(self, Dq: float = 0.0, B: float = 965.0, C: float = 4449.0) -> None B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def T_3_1_states(self) -> Float64Array: """Calculate the T_3_1 states.""" @@ -600,17 +613,6 @@ def A_1_2_states(self) -> Float64Array: return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - return eigh(M)[0] - def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. @@ -666,8 +668,9 @@ def solver(self) -> Dict[str, Float64Array]: } -class d5(object): +class d5(LigandFieldTheory): """Class representing the d5 configuration in ligand field theory.""" + def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3850.0) -> None: """ Initializes the d5 configuration with given parameters. @@ -677,14 +680,11 @@ def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3850.0) -> None B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def T_2_2_states(self) -> Float64Array: """Calculate the T_2_2 states.""" - # diagonal elements AA = -20 * self.Dq - 20 * self.B + 10 * self.C @@ -990,18 +990,6 @@ def E_4_states(self) -> Float64Array: return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - - return eigh(M)[0] - def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. @@ -1056,8 +1044,9 @@ def solver(self) -> Dict[str, Float64Array]: } -class d6(object): +class d6(LigandFieldTheory): """Class representing the d6 configuration in ligand field theory.""" + def __init__(self, Dq: float = 0.0, B: float = 1065.0, C: float = 5120.0): """ Initializes the d6 configuration with given parameters. @@ -1067,9 +1056,7 @@ def __init__(self, Dq: float = 0.0, B: float = 1065.0, C: float = 5120.0): B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def T_3_1_states(self) -> Float64Array: """Calculate the T_3_1 states.""" @@ -1370,17 +1357,7 @@ def A_1_2_states(self) -> Float64Array: return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - - return eigh(M)[0] def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. @@ -1389,7 +1366,6 @@ def solver(self) -> Dict[str, Float64Array]: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. """ - GS = np.array([-4 * self.Dq - 21 * self.B]) T_5_2 = np.array([0], dtype=np.float64) @@ -1441,7 +1417,7 @@ def solver(self) -> Dict[str, Float64Array]: } -class d7(object): +class d7(LigandFieldTheory): """Class for d7 configuration.""" def __init__(self, Dq: float = 0.0, B: float = 971.0, C: float = 4499.0): @@ -1452,9 +1428,7 @@ def __init__(self, Dq: float = 0.0, B: float = 971.0, C: float = 4499.0): B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def T_2_2_states(self): """Calculate the T_2_2 states.""" @@ -1573,17 +1547,7 @@ def T_4_1_states(self): return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. - """ - return eigh(M)[0] def solver(self) -> Dict[str, np.ndarray]: """Solve for all states and return a dictionary of results. @@ -1636,7 +1600,7 @@ def solver(self) -> Dict[str, np.ndarray]: } -class d8(object): +class d8(LigandFieldTheory): def __init__(self, Dq: float = 0.0, B: float = 1030.0, C: float = 4850.0): """ Initializes the d8 configuration with given parameters. @@ -1646,9 +1610,7 @@ def __init__(self, Dq: float = 0.0, B: float = 1030.0, C: float = 4850.0): B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). """ - self.Dq = np.float64(Dq) - self.B = np.float64(B) - self.C = np.float64(C) + super().__init__(Dq, B, C) def A_1_1_states(self): """Calculate the A_1_1 states.""" @@ -1711,17 +1673,7 @@ def T_3_1_states(self): return self.eigensolver(states) - def eigensolver(self, M: Float64Array) -> Float64Array: - """Solve for the eigenvalues of the given matrix. - - Args: - M (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. - - Returns: - Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamilton - """ - return eigh(M)[0] def solver(self) -> Dict[str, Float64Array]: """Solve for all states and return a dictionary of results. diff --git a/tanabesugano/tools.py b/tanabesugano/tools.py index b885e29..ee52ca4 100644 --- a/tanabesugano/tools.py +++ b/tanabesugano/tools.py @@ -1,3 +1,4 @@ +from __future__ import annotations from typing import Tuple, Union import numpy as np From 9a29d812c3b37fffc7939df3c3ec3542c2d10a75 Mon Sep 17 00:00:00 2001 From: Anselm Hahn Date: Wed, 23 Oct 2024 06:25:58 +0200 Subject: [PATCH 3/4] feat: add future annotations for improved type hinting --- tanabesugano/__init__.py | 2 + tanabesugano/batch.py | 42 ++++++------- tanabesugano/cmd.py | 62 +++++++++--------- tanabesugano/matrices.py | 107 ++++++++++++++++---------------- tanabesugano/test/test_batch.py | 2 + tanabesugano/test/test_front.py | 4 +- tanabesugano/test/test_num.py | 10 +-- tanabesugano/tools.py | 7 ++- 8 files changed, 127 insertions(+), 109 deletions(-) diff --git a/tanabesugano/__init__.py b/tanabesugano/__init__.py index b04970e..7a69a1d 100644 --- a/tanabesugano/__init__.py +++ b/tanabesugano/__init__.py @@ -1,3 +1,5 @@ """tanabesugano: A Python package for Tanabe-Sugano diagrams.""" +from __future__ import annotations + __version__ = "1.4.4" diff --git a/tanabesugano/batch.py b/tanabesugano/batch.py index 5c3ee44..3b3fcb1 100644 --- a/tanabesugano/batch.py +++ b/tanabesugano/batch.py @@ -1,8 +1,11 @@ +from __future__ import annotations + from typing import List import numpy as np -from tanabesugano import matrices, tools +from tanabesugano import matrices +from tanabesugano import tools class Batch: @@ -22,26 +25,23 @@ def __init__( C = [3600.0, 4000, 10] if len(Dq) != 3: raise KeyError( - "The range of `Dq` is based on the three values: start, stop, steps!" + "The range of `Dq` is based on the three values: start, stop, steps!", ) - else: - self.Dq = np.linspace(Dq[0], Dq[1], int(Dq[2])) # Oh-crystalfield-splitting + self.Dq = np.linspace(Dq[0], Dq[1], int(Dq[2])) # Oh-crystalfield-splitting if len(B) != 3: raise KeyError( - "The range of `B` is based on the three values: start, stop, steps!" + "The range of `B` is based on the three values: start, stop, steps!", ) - else: - self.B = np.linspace( - B[0], B[1], int(B[2]) - ) # Racah-Parameter B in wavenumbers + self.B = np.linspace( + B[0], B[1], int(B[2]), + ) # Racah-Parameter B in wavenumbers if len(C) != 3: raise KeyError( - "The range of `C` is based on the three values: start, stop, steps!" + "The range of `C` is based on the three values: start, stop, steps!", ) - else: - self.C = np.linspace( - C[0], C[1], int(C[2]) - ) # Racah-Parameter C in wavenumbers + self.C = np.linspace( + C[0], C[1], int(C[2]), + ) # Racah-Parameter C in wavenumbers if slater: # Transformin Racah to Slater-Condon @@ -72,7 +72,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 3: # d3 @@ -84,7 +84,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 4: # d4 states = matrices.d4(Dq=_Dq, B=_B, C=_C).solver() @@ -95,7 +95,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 5: # d5 states = matrices.d5(Dq=_Dq, B=_B, C=_C).solver() @@ -106,7 +106,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 6: # d6 states = matrices.d6(Dq=_Dq, B=_B, C=_C).solver() @@ -117,7 +117,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 7: # d7 states = matrices.d7(Dq=_Dq, B=_B, C=_C).solver() @@ -128,7 +128,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) elif self.d_count == 8: # d8 states = matrices.d8(Dq=_Dq, B=_B, C=_C).solver() @@ -139,7 +139,7 @@ def calculation(self) -> None: "B": _B, "C": _C, "states": states, - } + }, ) else: raise ValueError("not a correct value!") diff --git a/tanabesugano/cmd.py b/tanabesugano/cmd.py index 9a027dd..3f1af2f 100644 --- a/tanabesugano/cmd.py +++ b/tanabesugano/cmd.py @@ -1,23 +1,29 @@ #!/usr/bin/env python from __future__ import annotations + import argparse +from pathlib import Path + import matplotlib.pyplot as plt import numpy as np import pandas as pd + from prettytable import PrettyTable -from pathlib import Path + try: import plotly.express as px except ImportError: # pragma: no cover px = None -from tanabesugano import __version__, matrices, tools +from tanabesugano import __version__ +from tanabesugano import matrices +from tanabesugano import tools -class CMDmain(object): +class CMDmain: def __init__( self, Dq: float = 4000.0, @@ -43,6 +49,7 @@ def __init__( Electron count, by default 5 slater : bool, optional Transforming from Racah to Slater-Condon, by default False + """ self.Dq = Dq self.B = B @@ -63,7 +70,7 @@ def __init__( self.result = np.zeros((self._size + 1, nroots)) self.df = pd.DataFrame( - {"Energy": energy, "delta_B": energy / self.B, "10Dq": energy * 10.0} + {"Energy": energy, "delta_B": energy / self.B, "10Dq": energy * 10.0}, ) self.title_TS = ( f"TS-diagram_d{self.d_count}_10Dq_{int(self.Dq * 10.0)}_" @@ -86,7 +93,7 @@ def plot(self) -> None: self.df.drop(["Energy", "delta_B", "10Dq"], axis=1).to_numpy() / self.B, ls="--", ) - self.label_plot("Tanabe-Sugano-Diagram", "$E/B$", "$\Delta/B$") + self.label_plot("Tanabe-Sugano-Diagram", "$E/B$", r"$\Delta/B$") # Figure one for Energy-Correlation-Diagram Dq-Energy versus State-Energy plt.figure(2) @@ -96,7 +103,7 @@ def plot(self) -> None: ls="--", ) self.label_plot( - "DD excitations -Diagram", "$dd-state-energy\,(1/cm)$", "$10Dq\,(1/cm)$" + "DD excitations -Diagram", r"$dd-state-energy\,(1/cm)$", r"$10Dq\,(1/cm)$", ) plt.show() @@ -121,52 +128,51 @@ def savetxt(self) -> None: ).to_csv(Path(f"{self.title_DD}.csv"), index=False) def calculation(self) -> None: - """ - Is filling the self.result with the iTS states of over-iterated energy range + """Is filling the self.result with the iTS states of over-iterated energy range """ result = [] for dq in self.df["Energy"]: if self.d_count == 2: # d2 result.append( self.subsplit_states( - matrices.d2(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d2(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 3: # d3 result.append( self.subsplit_states( - matrices.d3(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d3(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 4: # d4 result.append( self.subsplit_states( - matrices.d4(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d4(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 5: # d5 result.append( self.subsplit_states( - matrices.d5(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d5(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 6: # d6 result.append( self.subsplit_states( - matrices.d6(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d6(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 7: # d7 result.append( self.subsplit_states( - matrices.d7(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d7(Dq=dq, B=self.B, C=self.C).solver(), + ), ) elif self.d_count == 8: # d8 result.append( self.subsplit_states( - matrices.d8(Dq=dq, B=self.B, C=self.C).solver() - ) + matrices.d8(Dq=dq, B=self.B, C=self.C).solver(), + ), ) else: msg = "The number of unpaired electrons should be between 2 and 8." @@ -191,8 +197,7 @@ def subsplit_states(states: dict) -> dict: return rearranged_states def ci_cut(self, dq_ci: float = None) -> None: - """ - Extracting the atomic-termsymbols for a specific dq depending on the oxidation state + """Extracting the atomic-termsymbols for a specific dq depending on the oxidation state """ if self.d_count == 2: # d2 states = matrices.d2(Dq=dq_ci / 10.0, B=self.B, C=self.C).solver() @@ -234,11 +239,12 @@ def ts_print(self, states: dict, dq_ci: float = None) -> None: List of atomic-termsymbols for a specific oxidation state dq_ci : float, optional Specific crystalfield-splitting in Dq, by default None + """ count = 0 cut = np.zeros( self._size + 1, - dtype=[("state", np.unicode_, 7), ("cm", int), ("eV", float)], + dtype=[("state", np.str_, 7), ("cm", int), ("eV", float)], ) for irreducible in states: for energy in states[irreducible]: @@ -281,7 +287,7 @@ def interactive_plot(self) -> None: if px is None: raise ImportError( "Plotly is not installed. Please install plotly " - "with 'pip install tanabesugano[plotly]'!" + "with 'pip install tanabesugano[plotly]'!", ) _col = self.df.drop(["Energy", "delta_B", "10Dq"], axis=1).columns @@ -360,7 +366,7 @@ def cmd_line() -> None: parser = argparse.ArgumentParser(description=description) parser.add_argument( - "-d", type=int, default=6, help="Number of unpaired electrons (default d5)" + "-d", type=int, default=6, help="Number of unpaired electrons (default d5)", ) parser.add_argument( "-Dq", @@ -392,7 +398,7 @@ def cmd_line() -> None: "1.)", ) parser.add_argument( - "-n", type=int, default=500, help="Number of roots (default nroots = 500)" + "-n", type=int, default=500, help="Number of roots (default nroots = 500)", ) parser.add_argument( "-ndisp", diff --git a/tanabesugano/matrices.py b/tanabesugano/matrices.py index 947a7dc..9e8fd9a 100644 --- a/tanabesugano/matrices.py +++ b/tanabesugano/matrices.py @@ -1,12 +1,14 @@ -from __future__ import print_function +from __future__ import annotations + +from typing import Dict +from typing import TypeAlias import numpy as np + from numpy._typing._array_like import NDArray from numpy.linalg import eigh -from typing import Dict, TypeAlias - _sqrt2 = np.sqrt(2.0) _sqrt3 = np.sqrt(3.0) _sqrt6 = np.sqrt(6.0) @@ -24,54 +26,53 @@ class LigandFieldTheory: """Parent class for ligand field theory configurations.""" def __init__(self, Dq: float, B: float, C: float) -> None: - """ - Initializes the configuration with given parameters. + """Initializes the configuration with given parameters. Args: dq (float): Crystal field splitting in wavenumbers (cm-1). b (float): Racah parameter B in wavenumbers (cm-1). c (float): Racah parameter C in wavenumbers (cm-1). + """ self.Dq = np.float64(Dq) self.B = np.float64(B) self.C = np.float64(C) def eigensolver(self, matrix: Float64Array) -> Float64Array: - """ - Solve for the eigenvalues of the given matrix. + """Solve for the eigenvalues of the given matrix. Args: matrix (Float64Array): 2-dimensional square array representing the TS matrix of the ligand field Hamiltonian. Returns: Float64Array: 1-dimensional array of eigenvalues of the diagonalized ligand field Hamiltonian. + """ return eigh(matrix)[0] def solver(self) -> Dict[str, Float64Array]: - """ - Solve for all states and return a dictionary of results. + """Solve for all states and return a dictionary of results. Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ msg = "Subclasses should implement this method." raise NotImplementedError(msg) class d2(LigandFieldTheory): - """ - Class representing the d2 configuration in ligand field theory. + """Class representing the d2 configuration in ligand field theory. """ def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3801.0) -> None: - """ - Initializes the d2 configuration with given parameters. + """Initializes the d2 configuration with given parameters. Args: Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) @@ -90,7 +91,6 @@ def A_1_1_states(self) -> Float64Array: def E_1_states(self) -> Float64Array: """Calculate the E_1 states.""" - # Diagonal elements AA = -8 * self.Dq + self.B + 2 * self.C BB = +12 * self.Dq + 2 * self.C @@ -104,7 +104,6 @@ def E_1_states(self) -> Float64Array: def T_1_2_states(self) -> Float64Array: """Calculate the T_1_2 states.""" - # Diagonal elements AA = -8 * self.Dq + self.B + 2 * self.C BB = +2 * self.Dq + 2 * self.C @@ -118,7 +117,6 @@ def T_1_2_states(self) -> Float64Array: def T_3_1_states(self) -> Float64Array: """Calculate the T_3_1 states.""" - # Diagonal elements AA = -8 * self.Dq - 5 * self.B BB = +2 * self.Dq + 4 * self.B @@ -135,6 +133,7 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states GS = self.T_3_1_states()[0] @@ -170,6 +169,7 @@ def __init__(self, Dq: float = 0.0, B: float = 918.0, C: float = 4133.0) -> None Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) @@ -204,7 +204,7 @@ def T_2_2_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -240,7 +240,7 @@ def T_2_1_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -264,7 +264,7 @@ def E_2_states(self) -> Float64Array: CD = DC = _2sqrt3 * self.B states = np.array( - [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]] + [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]], ) return self.eigensolver(states) @@ -287,6 +287,7 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states GS = np.array([-12 * self.Dq - 15 * self.B]) @@ -319,19 +320,18 @@ class d4(LigandFieldTheory): """Class representing the d4 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 965.0, C: float = 4449.0) -> None: - """ - Initializes the d4 configuration with given parameters. + """Initializes the d4 configuration with given parameters. Args: Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) def T_3_1_states(self) -> Float64Array: """Calculate the T_3_1 states.""" - # Diagonal elements AA = -16 * self.Dq - 15 * self.B + 5 * self.C BB = -6 * self.Dq - 11 * self.B + 4 * self.C @@ -378,7 +378,7 @@ def T_3_1_states(self) -> Float64Array: [EA, EB, EC, ED, EE, EF, EG], [FA, FB, FC, FD, FE, FF, FG], [GA, GB, GC, GD, GE, GF, GG], - ] + ], ) return self.eigensolver(states) @@ -431,7 +431,7 @@ def T_1_2_states(self) -> Float64Array: [EA, EB, EC, ED, EE, EF, EG], [FA, FB, FC, FD, FE, FF, FG], [GA, GB, GC, GD, GE, GF, GG], - ] + ], ) return self.eigensolver(states) @@ -467,7 +467,7 @@ def A_1_1_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -503,7 +503,7 @@ def E_1_1_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -539,14 +539,13 @@ def T_3_2_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) def T_1_1_states(self) -> Float64Array: """Calculate the T_1_1 states.""" - # Diagonal elements AA = -6 * self.Dq - 3 * self.B + 6 * self.C BB = -6 * self.Dq - 3 * self.B + 8 * self.C @@ -564,7 +563,7 @@ def T_1_1_states(self) -> Float64Array: CD = DC = -_sqrt6 * self.B states = np.array( - [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]] + [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]], ) return self.eigensolver(states) @@ -601,7 +600,6 @@ def A_3_2_states(self) -> Float64Array: def A_1_2_states(self) -> Float64Array: """Calculate the A_1_2 states.""" - # Diagonal elements AA = -6 * self.Dq - 12 * self.B + 6 * self.C BB = +4 * self.Dq - 3 * self.B + 6 * self.C @@ -618,6 +616,7 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states GS = np.array([-6 * self.Dq - 21 * self.B]) @@ -672,19 +671,18 @@ class d5(LigandFieldTheory): """Class representing the d5 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 860.0, C: float = 3850.0) -> None: - """ - Initializes the d5 configuration with given parameters. + """Initializes the d5 configuration with given parameters. Args: Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) def T_2_2_states(self) -> Float64Array: """Calculate the T_2_2 states.""" - # diagonal elements AA = -20 * self.Dq - 20 * self.B + 10 * self.C @@ -766,7 +764,7 @@ def T_2_2_states(self) -> Float64Array: [HA, HB, HC, HD, HE, HF, HG, HH, HI, HJ], [IA, IB, IC, ID, IE, IF, IG, IH, II, IJ], [JA, JB, JC, JD, JE, JF, JG, JH, JI, JJ], - ] + ], ) return self.eigensolver(states) @@ -831,7 +829,7 @@ def T_2_1_states(self) -> Float64Array: [FA, FB, FC, FD, FE, FF, FG, FH], [GA, GB, GC, GD, GE, GF, GG, GH], [HA, HB, HC, HD, HE, HF, HG, HH], - ] + ], ) return self.eigensolver(states) @@ -886,7 +884,7 @@ def E_2_states(self) -> Float64Array: [EA, EB, EC, ED, EE, EF, EG], [FA, FB, FC, FD, FE, FF, FG], [GA, GB, GC, GD, GE, GF, GG], - ] + ], ) return self.eigensolver(states) @@ -912,7 +910,7 @@ def A_2_1_states(self) -> Float64Array: CD = DC = 0.0 states = np.array( - [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]] + [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]], ) return self.eigensolver(states) @@ -995,12 +993,13 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states GS = -35 * self.B A_6_1 = np.array( - [0.0], dtype=float + [0.0], dtype=float, ) # Starting value is -35. * B, but has to set to zero per definition E_4 = self.E_4_states() - GS A_4_1 = np.array([-25 * self.B + 5 * self.C]) - GS @@ -1048,13 +1047,13 @@ class d6(LigandFieldTheory): """Class representing the d6 configuration in ligand field theory.""" def __init__(self, Dq: float = 0.0, B: float = 1065.0, C: float = 5120.0): - """ - Initializes the d6 configuration with given parameters. + """Initializes the d6 configuration with given parameters. Args: Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) @@ -1108,7 +1107,7 @@ def T_3_1_states(self) -> Float64Array: [EA, EB, EC, ED, EE, EF, EG], [FA, FB, FC, FD, FE, FF, FG], [GA, GB, GC, GD, GE, GF, GG], - ] + ], ) return self.eigensolver(states) @@ -1163,7 +1162,7 @@ def T_1_2_states(self) -> Float64Array: [EA, EB, EC, ED, EE, EF, EG], [FA, FB, FC, FD, FE, FF, FG], [GA, GB, GC, GD, GE, GF, GG], - ] + ], ) return self.eigensolver(states) @@ -1201,7 +1200,7 @@ def A_1_1_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -1239,7 +1238,7 @@ def E_1_1_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -1277,7 +1276,7 @@ def T_3_2_states(self) -> Float64Array: [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -1303,7 +1302,7 @@ def T_1_1_states(self) -> Float64Array: CD = DC = -_sqrt6 * self.B states = np.array( - [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]] + [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]], ) return self.eigensolver(states) @@ -1364,8 +1363,8 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. - """ + """ GS = np.array([-4 * self.Dq - 21 * self.B]) T_5_2 = np.array([0], dtype=np.float64) @@ -1427,6 +1426,7 @@ def __init__(self, Dq: float = 0.0, B: float = 971.0, C: float = 4499.0): Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) @@ -1463,7 +1463,7 @@ def T_2_2_states(self): [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -1501,7 +1501,7 @@ def T_2_1_states(self): [CA, CB, CC, CD, CE], [DA, DB, DC, DD, DE], [EA, EB, EC, ED, EE], - ] + ], ) return self.eigensolver(states) @@ -1527,7 +1527,7 @@ def E_2_states(self): CD = DC = _2sqrt3 * self.B states = np.array( - [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]] + [[AA, AB, AC, AD], [BA, BB, BC, BD], [CA, CB, CC, CD], [DA, DB, DC, DD]], ) return self.eigensolver(states) @@ -1554,6 +1554,7 @@ def solver(self) -> Dict[str, np.ndarray]: Returns: Dict[str, np.ndarray]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states @@ -1602,13 +1603,13 @@ def solver(self) -> Dict[str, np.ndarray]: class d8(LigandFieldTheory): def __init__(self, Dq: float = 0.0, B: float = 1030.0, C: float = 4850.0): - """ - Initializes the d8 configuration with given parameters. + """Initializes the d8 configuration with given parameters. Args: Dq (float): Crystal field splitting in wavenumbers (cm-1). B (float): Racah parameter B in wavenumbers (cm-1). C (float): Racah parameter C in wavenumbers (cm-1). + """ super().__init__(Dq, B, C) @@ -1659,7 +1660,6 @@ def T_1_2_states(self): def T_3_1_states(self): """Calculate the T_3_1 states.""" - # - diagonal elements AA = +8 * self.Dq - 5 * self.B @@ -1680,6 +1680,7 @@ def solver(self) -> Dict[str, Float64Array]: Returns: Dict[str, Float64Array]: Dictionary with atomic term symbols as keys and eigenvalues as values. + """ # Ligand field independent states diff --git a/tanabesugano/test/test_batch.py b/tanabesugano/test/test_batch.py index 51375ff..9463848 100644 --- a/tanabesugano/test/test_batch.py +++ b/tanabesugano/test/test_batch.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from tanabesugano.batch import Batch diff --git a/tanabesugano/test/test_front.py b/tanabesugano/test/test_front.py index ddf0935..3698143 100644 --- a/tanabesugano/test/test_front.py +++ b/tanabesugano/test/test_front.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from tanabesugano import cmd as frontapp @@ -5,7 +7,7 @@ def test_frontapp(): return frontapp.CMDmain( - Dq=4000.0, B=400.0, C=3600.0, nroots=100, d_count=5 + Dq=4000.0, B=400.0, C=3600.0, nroots=100, d_count=5, ).calculation() diff --git a/tanabesugano/test/test_num.py b/tanabesugano/test/test_num.py index 3efbd04..994aebf 100644 --- a/tanabesugano/test/test_num.py +++ b/tanabesugano/test/test_num.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np from tanabesugano import matrices @@ -8,16 +10,16 @@ def state_check(x): if x == 3: states = matrices.d3(Dq=i).solver() return len(states) - elif x == 4: + if x == 4: states = matrices.d4(Dq=i).solver() return len(states) - elif x == 5: + if x == 5: states = matrices.d5(Dq=i).solver() return len(states) - elif x == 6: + if x == 6: states = matrices.d6(Dq=i).solver() return len(states) - elif x == 7: + if x == 7: states = matrices.d7(Dq=i).solver() return len(states) diff --git a/tanabesugano/tools.py b/tanabesugano/tools.py index ee52ca4..f62c1a9 100644 --- a/tanabesugano/tools.py +++ b/tanabesugano/tools.py @@ -1,11 +1,13 @@ from __future__ import annotations -from typing import Tuple, Union + +from typing import Tuple +from typing import Union import numpy as np def racah( - F2: Union[float, np.array], F4: Union[float, np.array] + F2: Union[float, np.array], F4: Union[float, np.array], ) -> Union[Tuple[float, float], Tuple[np.array, np.array]]: """Transform the Slater-Condon-Parameter to Racah-Parameter. @@ -18,6 +20,7 @@ def racah( Returns: Union[Tuple[float, float], Tuple[np.array, np.array]]: Return the racah parameters. + """ eVcm = 8065.54 B = eVcm * (F2 / 49.0 - 5 / 441.0 * F4) From 31424cf90ec69dcc96933d580a634212349534a1 Mon Sep 17 00:00:00 2001 From: Anselm Hahn Date: Wed, 23 Oct 2024 06:35:20 +0200 Subject: [PATCH 4/4] refactor: adjust TypeAlias definition for Float64Array --- tanabesugano/matrices.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tanabesugano/matrices.py b/tanabesugano/matrices.py index 9e8fd9a..406801c 100644 --- a/tanabesugano/matrices.py +++ b/tanabesugano/matrices.py @@ -1,7 +1,7 @@ from __future__ import annotations from typing import Dict -from typing import TypeAlias +# from typing import TypeAlias import numpy as np @@ -19,7 +19,8 @@ _3sqrt3 = _sqrt3 * 3.0 _3sqrt6 = _sqrt6 * 3.0 -Float64Array: TypeAlias = NDArray[np.float64] +# Float64Array: TypeAlias = NDArray[np.float64] +Float64Array = NDArray[np.float64] class LigandFieldTheory: