Skip to content

Commit

Permalink
WIP new semiclassical
Browse files Browse the repository at this point in the history
  • Loading branch information
vatai committed Mar 14, 2024
1 parent f1ec24d commit ce449a4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 38 deletions.
44 changes: 14 additions & 30 deletions radicalpy/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,50 +577,34 @@ def effective_hyperfine(self) -> float:
return np.sqrt((4 / 3) * sum((hfcs_np**2 * spns_np) * (spns_np + 1)))

@property ############ TODO(calc only once)
def semiclassical_tau2(self) -> float:
"""Calculate the :math:`\\tau^2` coefficient.
def semiclassical_std(self) -> float:
r"""The standard deviation for the semiclassical HFCs.
:math:`\\tau^2` is used in
`Molecule.semiclassical_random_hfc`.
Calculate the standard deviation :math:`\sigma` where
.. math::
\\tau_i^{-2} = \\frac{1}{6} \\sum_k a_k^2 I_k (I_k + 1)
\sigma = \sqrt{\frac{2}{\tau^2}}
where :math:`a_k`, :math:`I_k` are the hyperfine coupling and
and
.. math::
\tau_i^{-2} = \frac{1}{6} \sum_k a_k^2 I_k (I_k + 1)
where :math:`a_k` is the hyperfine coupling and :math:`I_k`
the spin quantum number of each nucleus, respectively.
Examples:
>>> m = Molecule.fromdb("flavin_anion", nuclei=["N14"])
>>> m.semiclassical_tau
>>> m.semiclassical_std
0.0010410773656027476
"""
tmp = sum(
n.spin_quantum_number * (n.spin_quantum_number + 1) * n.hfc.isotropic**2
for n in self.nuclei
)
return 6 / tmp

def semiclassical_random_hfc(self, I_max: float, fI_max: float) -> float:
tau = self.semiclassical_tau
I_r = self.hfc_rng.uniform(0, I_max)
fI_r = self.hfc_rng.uniform(0, fI_max)
f = (
I_r**2
* ((tau**2 / (4 * np.pi)) ** 1.5)
* np.exp(-1 / 4 * I_r**2 * tau**2)
)
return I_r if fI_r < f else 0

def semiclassical_random_rotations(self) -> Tuple[float, float, float]:
while True:
theta_r = self.ang_rng.uniform(0, np.pi)
s_r = self.ang_rng.uniform()
if s_r < np.sin(theta_r):
theta = theta_r
break

phi = self.ang_rng.uniform(0, 2 * np.pi)
return np.sin(theta) * np.cos(phi), np.sin(theta) * np.sin(phi), np.cos(theta)
tau2 = 6.0 / tmp
return np.sqrt(2 / tau2)


class Triplet(Molecule):
Expand Down
16 changes: 8 additions & 8 deletions radicalpy/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1214,20 +1214,20 @@ def semiclassical_gen(
B: float,
I_max: list[float],
fI_max: list[float],
) -> Iterator[NDArray[float]]:
) -> Iterator[NDArray[np.float_]]:
num_particles = len(self.radicals)
spinops = [
[self.spin_operator(i, ax) for ax in "xyz"]
for i in range(len(self.radicals))
[self.spin_operator(ri, ax) for ax in "xyz"] for ri in range(num_particles)
]
for i in range(num_samples):
result = complex(0)
for ri, m in enumerate(self.molecules):
h = m.semiclassical_random_hfc(I_max[ri], fI_max[ri])
std = m.semiclassical_std
Is = np.random.normal(0, std, size=3)
gamma = m.radical.gamma_mT
rots = m.semiclassical_random_rotations()
for ai, rot in enumerate(rots):
spinop = spinops[ri][ai]
result += gamma * spinop * rot * h
for ax in range(3):
spinop = spinops[ri][ax]
result += gamma * spinop * Is[ax]
result += gamma * B * spinop
yield result

Expand Down

0 comments on commit ce449a4

Please sign in to comment.