Line data Source code
1 : # SPDX-FileCopyrightText: 2025 PairInteraction Developers 2 : # SPDX-License-Identifier: LGPL-3.0-or-later 3 1 : from __future__ import annotations 4 : 5 1 : from typing import TYPE_CHECKING, overload 6 : 7 1 : from pairinteraction.perturbative.effective_system_pair import EffectiveSystemPair, EffectiveSystemPairReal 8 1 : from pairinteraction.units import QuantityScalar 9 : 10 : if TYPE_CHECKING: 11 : from pairinteraction.ket import KetAtom 12 : from pairinteraction.units import PintFloat 13 : 14 : 15 1 : class C6(EffectiveSystemPair): 16 : """Class for calculating the C6 coefficient for a two-atom state ``|ket1, ket2>``. 17 : 18 : Given two `KetAtom` objects ket1 and ket2, 19 : this class computes the C6 coefficient for the pair state ``|ket1, ket2>``. 20 : This class also allows to set magnetic and electric fields similar to the `SystemAtom` class, 21 : as well as the angle between the two atoms like in the `SystemPair` class. 22 : 23 : Note, that ket1 and ket2 must be either the same state or states of different species. 24 : If you want to calculate the C6 coefficient for two different states of the same species, 25 : we recommend using the `EffectiveSystemPair` class with the ket_tuples subspace [(ket1, ket2), (ket2, ket1)]. 26 : 27 : 28 : 29 : Examples: 30 : >>> import pairinteraction as pi 31 : >>> ket = pi.KetAtom("Rb", n=60, l=0, j=0.5, m=0.5) 32 : >>> c6_obj = pi.C6(ket, ket) 33 : >>> c6 = c6_obj.get(unit="planck_constant * GHz * micrometer^6") 34 : >>> print(f"{c6:.1f}") 35 : -138.9 36 : 37 : """ 38 : 39 1 : def __init__(self, ket1: KetAtom, ket2: KetAtom) -> None: 40 1 : if ket1.species == ket2.species and ket1 != ket2: 41 0 : raise ValueError( 42 : "If you want to calculate 2nd order perturbations of two different states a and b " 43 : "(of the same species), " 44 : "please use the EffectiveSystemPair([(a,b), (b,a)]) class." 45 : ) 46 : 47 1 : super().__init__([(ket1, ket2)]) 48 1 : self.set_perturbation_order(2) 49 : 50 : # Set some default distance. The exact value does not matter for the C6 value, 51 : # but too small distances result in warnings about the basisvec admixtures 52 1 : self.set_distance(100, unit="micrometer") 53 : 54 : @overload 55 : def get(self, unit: None = None) -> PintFloat: ... 56 : 57 : @overload 58 : def get(self, unit: str) -> float: ... 59 : 60 1 : def get(self, unit: str | None = None) -> float | PintFloat: 61 : r"""Get the C6 coefficient of the interaction between the specified ket1 and ket2. 62 : 63 : The C6 coefficient is defined such that the van der Waals interaction potential is given by 64 : :math:`V(r) = -C_6/r^6`. 65 : Note, the entry in the effective Hamiltonian matrix (see :meth:`get_effective_hamiltonian`) 66 : has the opposite sign as the C6 coefficient. 67 : 68 : Args: 69 : unit: The unit in which to return the C6 coefficient. 70 : If None, returns a pint object. 71 : 72 : """ 73 1 : h_eff_pint = self.get_effective_hamiltonian(return_order=2) 74 1 : distance = self.system_pair.get_distance() 75 1 : c6_pint = -h_eff_pint[0, 0] * distance**6 # type: ignore [index] # pint does not know it can be indexed 76 1 : return QuantityScalar.convert_pint_to_user(c6_pint, "c6", unit) 77 : 78 : 79 1 : class C6Real(C6, EffectiveSystemPairReal): 80 1 : pass