Line data Source code
1 : # SPDX-FileCopyrightText: 2024 PairInteraction Developers
2 : # SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 1 : from __future__ import annotations
5 :
6 1 : from typing import TYPE_CHECKING
7 :
8 1 : import numpy as np
9 1 : import pytest
10 1 : from pairinteraction import ureg
11 1 : from pairinteraction.green_tensor import GreenTensorFreeSpace
12 1 : from pairinteraction.green_tensor.green_tensor_cavity import GreenTensorCavity
13 1 : from pairinteraction.green_tensor.green_tensor_surface import GreenTensorSurface
14 :
15 : if TYPE_CHECKING:
16 : from pairinteraction.green_tensor.green_tensor_base import GreenTensorBase
17 : from pairinteraction.units import NDArray
18 :
19 : from .utils import PairinteractionModule
20 :
21 1 : DISTANCE_VECTOR_MUM_LIST = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 3.5]]
22 :
23 :
24 1 : @pytest.mark.parametrize("distance_vector_mum", DISTANCE_VECTOR_MUM_LIST)
25 1 : def test_static_green_tensor(distance_vector_mum: list[float]) -> None:
26 1 : gt_reference = reference_green_tensor_vacuum(distance_vector_mum)
27 :
28 : gt: GreenTensorBase
29 1 : gt = GreenTensorFreeSpace([0, 0, 0], distance_vector_mum, unit="micrometer", static_limit=True)
30 1 : gt_dipole_dipole = gt.get(1, 1, transition_energy=0, scaled=True)
31 1 : np.testing.assert_allclose(gt_dipole_dipole.m, gt_reference)
32 :
33 1 : gt = GreenTensorSurface([0, 0, 0], distance_vector_mum, z=1000, unit="micrometer", static_limit=True)
34 1 : gt_dipole_dipole = gt.get(1, 1, transition_energy=0, scaled=True)
35 1 : np.testing.assert_allclose(gt_dipole_dipole.m, gt_reference, rtol=1e-6, atol=1e-16)
36 :
37 1 : gt = GreenTensorCavity([0, 0, 0], distance_vector_mum, z1=-1000, z2=1000, unit="micrometer", static_limit=True)
38 1 : gt_dipole_dipole = gt.get(1, 1, transition_energy=0, scaled=True)
39 1 : np.testing.assert_allclose(gt_dipole_dipole.m, gt_reference, rtol=1e-6, atol=1e-16)
40 :
41 :
42 1 : @pytest.mark.parametrize("distance_vector_mum", DISTANCE_VECTOR_MUM_LIST)
43 1 : def test_static_green_tensor_pair_potential(pi_module: PairinteractionModule, distance_vector_mum: list[float]) -> None:
44 1 : ket = pi_module.KetAtom("Rb", n=60, l=0, m=0.5)
45 1 : basis = pi_module.BasisAtom("Rb", n=(ket.n - 2, ket.n + 2), l=(0, 2))
46 1 : system = pi_module.SystemAtom(basis)
47 1 : system.set_magnetic_field([0, 0, 1], "gauss")
48 1 : system.set_electric_field([0, 0, 1], "V/cm")
49 1 : system.diagonalize()
50 :
51 1 : pair_energy_ghz = 2 * system.get_corresponding_energy(ket, unit="GHz")
52 1 : energy_range_ghz = (pair_energy_ghz - 3, pair_energy_ghz + 3)
53 1 : basis_pair = pi_module.BasisPair([system, system], energy=energy_range_ghz, energy_unit="GHz")
54 :
55 1 : system_pair_vacuum = pi_module.SystemPair(basis_pair)
56 1 : system_pair_vacuum.set_distance_vector(distance_vector_mum, unit="micrometer")
57 1 : system_pair_vacuum.set_interaction_order(3)
58 :
59 1 : gt = GreenTensorFreeSpace([0, 0, 0], distance_vector_mum, unit="micrometer", interaction_order=3, static_limit=True)
60 1 : gt.set_relative_permittivity(1.0)
61 1 : system_pair_free_space = pi_module.SystemPair(basis_pair).set_green_tensor(gt)
62 :
63 1 : pi_module.diagonalize([system_pair_free_space, system_pair_vacuum], sort_by_energy=True)
64 1 : np.testing.assert_allclose(
65 : system_pair_vacuum.get_eigenenergies("GHz") - pair_energy_ghz,
66 : system_pair_free_space.get_eigenenergies("GHz") - pair_energy_ghz,
67 : )
68 :
69 :
70 1 : @pytest.mark.parametrize("distance_vector_mum", DISTANCE_VECTOR_MUM_LIST)
71 1 : def test_vacuum_green_tensor(pi_module: PairinteractionModule, distance_vector_mum: list[float]) -> None:
72 1 : ket1 = pi_module.KetAtom("Rb", n=60, l=0, j=0.5, m=0.5)
73 1 : ket2 = pi_module.KetAtom("Rb", n=60, l=1, j=0.5, m=0.5)
74 :
75 1 : basis = pi_module.BasisAtom("Rb", n=(0, 0), additional_kets=[ket1, ket2])
76 1 : system = pi_module.SystemAtom(basis)
77 1 : pair_energy = ket1.get_energy("GHz") + ket2.get_energy("GHz")
78 1 : basis_pair = pi_module.BasisPair((system, system), energy=(pair_energy - 0.1, pair_energy + 0.1), energy_unit="GHz")
79 :
80 1 : dd = ket1.get_matrix_element(ket2, "electric_dipole", q=0)
81 1 : gt_reference = reference_green_tensor_vacuum(distance_vector_mum)
82 1 : reference = dd * gt_reference[2, 2] * dd
83 :
84 : # test internal vacuum green tensor
85 1 : system_pair = pi_module.SystemPair(basis_pair)
86 1 : system_pair.set_distance_vector(distance_vector_mum, "micrometer")
87 1 : hamiltonian = system_pair.get_hamiltonian("hartree").toarray()
88 1 : np.testing.assert_allclose(hamiltonian[1, 0], reference)
89 :
90 : # test custom free space vacuum green tensor
91 1 : system_pair = pi_module.SystemPair(basis_pair)
92 1 : gt = GreenTensorFreeSpace([0, 0, 0], distance_vector_mum, unit="micrometer", static_limit=True)
93 1 : system_pair.set_green_tensor(gt)
94 1 : hamiltonian = system_pair.get_hamiltonian("hartree").toarray()
95 1 : np.testing.assert_allclose(hamiltonian[1, 0], reference)
96 :
97 :
98 1 : def reference_green_tensor_vacuum(distance_vector_mum: list[float]) -> NDArray:
99 1 : distance_mum = np.linalg.norm(distance_vector_mum)
100 1 : distance_au = ureg.Quantity(distance_mum, "micrometer").to_base_units().m
101 1 : gt: NDArray = (
102 : np.eye(3) - 3 * np.outer(distance_vector_mum, distance_vector_mum) / distance_mum**2
103 : ) / distance_au**3
104 1 : return gt
|