Skip to content

Commit 56c92dd

Browse files
wip
1 parent 4fc0933 commit 56c92dd

8 files changed

Lines changed: 248 additions & 65 deletions

File tree

src/rydstate/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from rydstate import angular, basis, radial, rydberg, species
2-
from rydstate.basis import BasisMQDT, BasisSQDT
2+
from rydstate.basis import BasisMQDT, BasisSQDT, BasisSQDTMultiChannels
33
from rydstate.rydberg import (
44
RydbergStateMQDT,
55
RydbergStateSQDT,
@@ -13,6 +13,7 @@
1313
__all__ = [
1414
"BasisMQDT",
1515
"BasisSQDT",
16+
"BasisSQDTMultiChannels",
1617
"RydbergStateMQDT",
1718
"RydbergStateSQDT",
1819
"RydbergStateSQDTAlkali",

src/rydstate/basis/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from rydstate.basis.basis_base import BasisBase
22
from rydstate.basis.basis_mqdt import BasisMQDT
3-
from rydstate.basis.basis_sqdt import BasisSQDT
3+
from rydstate.basis.basis_sqdt import BasisSQDT, BasisSQDTMultiChannels
44

5-
__all__ = ["BasisBase", "BasisMQDT", "BasisSQDT"]
5+
__all__ = ["BasisBase", "BasisMQDT", "BasisSQDT", "BasisSQDTMultiChannels"]

src/rydstate/basis/basis_base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def filter_states(
6060
elif qn_min <= qn_value <= qn_max:
6161
new_states.append(state)
6262
self.states = new_states
63-
elif qn in ["n", "nu"]:
63+
elif qn in ["n", "nu", "nui"]:
6464
self.states = [state for state in self.states if qn_min <= getattr(state, qn) <= qn_max]
6565
else:
6666
raise ValueError(f"Unknown quantum number {qn}")
@@ -81,14 +81,14 @@ def sort_states(self, *qns: str) -> Self:
8181
def calc_exp_qn(self, qn: str) -> NDArray:
8282
if is_angular_momentum_quantum_number(qn):
8383
return np.array([state.angular.calc_exp_qn(qn) for state in self.states])
84-
if qn in ["n", "nu"]:
84+
if qn in ["n", "nu", "nui"]:
8585
return np.array([getattr(state, qn) for state in self.states])
8686
raise ValueError(f"Unknown quantum number {qn}")
8787

8888
def calc_std_qn(self, qn: str) -> NDArray:
8989
if is_angular_momentum_quantum_number(qn):
9090
return np.array([state.angular.calc_std_qn(qn) for state in self.states])
91-
if qn in ["n", "nu"]:
91+
if qn in ["n", "nu", "nui"]:
9292
return np.zeros(len(self.states))
9393
raise ValueError(f"Unknown quantum number {qn}")
9494

src/rydstate/basis/basis_mqdt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def get_mqdt_states_from_fmodel(
130130
sqdt_states: list[RydbergStateSQDT[AngularKetFJ[Any]]] = []
131131
for nui, angular_ket in zip(nuis, model.outer_channels, strict=True):
132132
sqdt_species = model.species_name.replace("_mqdt", "")
133-
sqdt_states.append(RydbergStateSQDT.from_angular_ket(sqdt_species, angular_ket, nu=float(nui)))
133+
sqdt_states.append(RydbergStateSQDT.from_angular_ket(sqdt_species, angular_ket, nui=float(nui)))
134134

135135
states.append(RydbergStateMQDT(coefficients, sqdt_states, nu=nu))
136136

src/rydstate/basis/basis_sqdt.py

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@
77

88
from rydstate.angular import NotSet
99
from rydstate.angular.angular_ket import AngularKetBase, AngularKetFJ, AngularKetJJ, AngularKetLS
10-
from rydstate.angular.utils import is_not_set
10+
from rydstate.angular.utils import (
11+
InvalidQuantumNumbersError,
12+
Unknown,
13+
get_possible_quantum_number_values,
14+
is_not_set,
15+
is_unknown,
16+
try_trivial_spin_addition,
17+
)
1118
from rydstate.basis.basis_base import BasisBase
1219
from rydstate.rydberg import (
1320
RydbergStateSQDT,
1421
)
1522
from rydstate.species import SpeciesObjectSQDT
23+
from rydstate.species.mqdt.species_object_mqdt import SpeciesObjectMQDT
1624

1725
if TYPE_CHECKING:
1826
from rydstate.angular.utils import AllKnown, CouplingScheme
@@ -131,10 +139,22 @@ def _add_states_jj(self, n: int, l_r: int, m_range: tuple[float, float] | None |
131139
state = RydbergStateSQDT.from_angular_ket(self.species, angular_ket, n=n)
132140
self.states.append(state) # type: ignore [arg-type]
133141

134-
def _add_states_fj(self, n: int, l_r: int, m_range: tuple[float, float] | None | NotSet = NotSet) -> None:
142+
def _add_states_fj(
143+
self,
144+
n: int,
145+
l_r: int,
146+
m_range: tuple[float, float] | None | NotSet = NotSet,
147+
l_c: int | Unknown = 0,
148+
j_c: float | Unknown = Unknown,
149+
f_c: float | Unknown = Unknown,
150+
f_tot: float | Unknown = Unknown,
151+
allow_unknown: bool = False,
152+
) -> None:
135153
i_c = self.species.i_c_number
136154
s_r = 0.5
137-
s_c = j_c = 0 if self.species.number_valence_electrons == 1 else 0.5
155+
s_c = 0 if self.species.number_valence_electrons == 1 else 0.5
156+
j_c = try_trivial_spin_addition(l_c, s_c, j_c)
157+
f_c = try_trivial_spin_addition(j_c, i_c, f_c)
138158
s_tot_list = np.arange(s_r - s_c, s_r + s_c + 1)
139159

140160
allowed = [self.species.is_allowed_shell(n, l_r, s) for s in s_tot_list]
@@ -147,13 +167,28 @@ def _add_states_fj(self, n: int, l_r: int, m_range: tuple[float, float] | None |
147167
)
148168
return
149169

150-
for j_r in np.arange(abs(l_r - s_r), l_r + s_r + 1):
151-
for f_c in np.arange(abs(j_c - i_c), j_c + i_c + 1):
152-
for f_tot in np.arange(abs(f_c - j_r), f_c + j_r + 1):
153-
for m in self._get_m_range(m_range, f_tot):
154-
angular_ket = AngularKetFJ(l_r=l_r, j_r=j_r, f_c=f_c, f_tot=f_tot, m=m, species=self.species)
170+
for j_r in get_possible_quantum_number_values(l_r, s_r, Unknown):
171+
for _f_c in get_possible_quantum_number_values(j_c, i_c, f_c):
172+
for _f_tot in get_possible_quantum_number_values(_f_c, j_r, f_tot):
173+
if is_unknown(_f_tot):
174+
raise ValueError(
175+
"Cannot determine f_tot for FJ coupling. Please provide more specific MQDT parameters."
176+
)
177+
for m in self._get_m_range(m_range, _f_tot):
178+
try:
179+
angular_ket = AngularKetFJ( # type: ignore [call-overload]
180+
l_r=l_r,
181+
j_r=j_r,
182+
f_c=_f_c,
183+
f_tot=_f_tot,
184+
m=m,
185+
species=self.species,
186+
allow_unknown=allow_unknown,
187+
)
188+
except InvalidQuantumNumbersError:
189+
continue
155190
state = RydbergStateSQDT.from_angular_ket(self.species, angular_ket, n=n)
156-
self.states.append(state) # type: ignore [arg-type]
191+
self.states.append(state)
157192

158193
def _get_m_range(self, m_range: tuple[float, float] | None | NotSet, f_tot: float) -> list[NotSet | float]:
159194
if is_not_set(m_range):
@@ -164,3 +199,57 @@ def _get_m_range(self, m_range: tuple[float, float] | None | NotSet, f_tot: floa
164199
m_min = max(-f_tot, m_range[0])
165200
m_max = min(f_tot, m_range[1])
166201
return [float(_m) for _m in np.arange(m_min, m_max + 1)]
202+
203+
204+
class BasisSQDTMultiChannels(BasisSQDT[AngularKetFJ[Any]]):
205+
species: SpeciesObjectMQDT
206+
207+
def __init__(
208+
self,
209+
species: str | SpeciesObjectMQDT,
210+
n: tuple[int, int],
211+
m: tuple[float, float] | None | NotSet = NotSet,
212+
*,
213+
coupling_scheme: CouplingScheme = "FJ",
214+
) -> None:
215+
self.species = SpeciesObjectMQDT.from_name(species) if isinstance(species, str) else species
216+
217+
self._init_states(n, m, coupling_scheme)
218+
219+
def _init_states(
220+
self, n_range: tuple[int, int], m_range: tuple[float, float] | None | NotSet, coupling_scheme: CouplingScheme
221+
) -> None:
222+
if coupling_scheme != "FJ":
223+
raise NotImplementedError("Only FJ coupling is implemented for multi-channel SQDT basis")
224+
self.coupling_scheme = coupling_scheme
225+
self.states = []
226+
227+
for core_ket in self.species._ionization_threshold_dict: # noqa: SLF001
228+
if core_ket.contains_unknown:
229+
# we will handle these below
230+
continue
231+
logger.info("Generating states for core ket: %s", core_ket)
232+
233+
for n in range(n_range[0], n_range[1] + 1):
234+
for l_r in range(n):
235+
self._add_states_fj(
236+
n, l_r, m_range, l_c=core_ket.l_c, j_c=core_ket.j_c, f_c=core_ket.f_c, allow_unknown=True
237+
)
238+
239+
# add all addition series, which are defined in the mqdt parameters but have dummy core kets
240+
for fmodel in self.species.models:
241+
for angular_ket in fmodel.outer_channels:
242+
if not angular_ket.contains_unknown:
243+
# handled above
244+
continue
245+
for n in range(n_range[0], n_range[1] + 1):
246+
self._add_states_fj(
247+
n,
248+
angular_ket.l_r,
249+
m_range,
250+
l_c=angular_ket.l_c,
251+
j_c=angular_ket.j_c,
252+
f_c=angular_ket.f_c,
253+
f_tot=angular_ket.f_tot,
254+
allow_unknown=True,
255+
)

src/rydstate/generate_database/generate_states_table.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def get_state_data(ids: int, state: RydbergStateSQDT[AngularKetLS[AllKnown]]) ->
7979

8080
return (
8181
ids, # id
82-
state.species.get_ionization_energy("a.u.") + state.get_energy("a.u."), # energy
82+
state.get_energy("a.u."), # energy
8383
parity, # parity = (-1)^l_tot
8484
state.n, # n: quantum number
8585
state.nu, # nu = NStar for sqdt

0 commit comments

Comments
 (0)