示例#1
0
    def test_rotation_dipolar(self):
        theta = np.pi / 3

        # Build two-atom system
        system_one_tmp = pi.SystemOne(self.system_one)
        system_one_tmp.setBfield([0, 0, 1])
        system_one_tmp.diagonalize()
        system_two = pi.SystemTwo(system_one_tmp, system_one_tmp, self.cache)
        system_two.restrictEnergy(self.state_two.getEnergy() - 2, self.state_two.getEnergy() + 2)
        system_two.setConservedParityUnderPermutation(pi.ODD)
        system_two.setDistance(6)
        system_two.setAngle(theta)
        system_two.diagonalize()
        eigenvalues1 = system_two.getHamiltonian().diagonal()
        overlaps1 = system_two.getOverlap(self.state_two)

        system_one_tmp = pi.SystemOne(self.system_one)
        system_one_tmp.setBfield([0, 0, 1], 0, theta, 0)
        system_one_tmp.diagonalize()
        system_two = pi.SystemTwo(system_one_tmp, system_one_tmp, self.cache)
        system_two.restrictEnergy(self.state_two.getEnergy() - 2, self.state_two.getEnergy() + 2)
        system_two.setConservedParityUnderPermutation(pi.ODD)
        system_two.setDistance(6)
        system_two.diagonalize()
        eigenvalues2 = system_two.getHamiltonian().diagonal()
        overlaps2 = system_two.getOverlap(self.state_two, 0, theta, 0)

        system_two.rotate(0, -theta, 0)
        overlaps3 = system_two.getOverlap(self.state_two)

        # Check that everything is the same
        np.testing.assert_allclose(eigenvalues1, eigenvalues2, rtol=1e-6)
        np.testing.assert_allclose(overlaps1, overlaps2, rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(overlaps1, overlaps3, rtol=1e-4, atol=1e-6)
示例#2
0
    def test_diagonalization_full(self):

        # Setup states
        state_one = pi.StateOne("Cs", 60, 0, 0.5, 0.5)

        # Build one-atom system
        system_one = pi.SystemOne(state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(state_one.getEnergy() - 30, state_one.getEnergy() + 30)
        system_one.restrictN(state_one.getN() - 1, state_one.getN() + 1)
        system_one.restrictL(state_one.getL() - 1, state_one.getL() + 1)
        system_one.setEfield([1, 0, 0])
        system_one.setBfield([5, 50, 0])

        # Diagonalize using the standard approach
        system_one_standard = pi.SystemOne(system_one)
        system_one_standard.diagonalize()
        evecs_standard = system_one_standard.getBasisvectors()

        # Diagonalize using FEAST
        system_one.diagonalize(-1e12, 1e12)
        evecs_feast = system_one.getBasisvectors()

        # Check results
        overlap = np.abs(np.dot(evecs_standard.conj().T, evecs_feast))**2
        np.testing.assert_allclose(overlap.diagonal(), np.ones_like(overlap.diagonal()), rtol=1e-12)
        self.assertAlmostEqual(np.sum(overlap), system_one.getNumBasisvectors(), places=6)
示例#3
0
    def setUp(self):
        # Set up rotation angles
        self.alpha = 2.67
        self.beta = 1.32
        self.gamma = 0.83

        # Get geometric interpretation of the rotation angles

        # The coordinate system is rotated by R_z(alpha)*R_y(beta)*R_z(gamma) where e.g. R_z is the elementary rotation
        # R_z(alpha) = [[cos(alpha), -sin(alpha), 0], [sin(alpha), cos(alpha), 0], [0,0,1]]. In the following, we calculate
        # the coordinate representations of the rotated z-axis and y-axis in the unrotated system.

        s, c = np.sin(self.gamma), np.cos(self.gamma)
        self.rotator = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
        s, c = np.sin(self.beta), np.cos(self.beta)
        self.rotator = np.dot(np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]), self.rotator)
        s, c = np.sin(self.alpha), np.cos(self.alpha)
        self.rotator = np.dot(np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]]), self.rotator)
        self.to_z_axis = np.dot(self.rotator, [0, 0, 1])
        self.to_y_axis = np.dot(self.rotator, [0, 1, 0])

        # Set up cache
        self.cache = pi.MatrixElementCache()

        # Setup states
        self.state_one = pi.StateOne("Rb", 61, 2, 1.5, 1.5)
        self.state_two = pi.StateTwo(self.state_one, self.state_one)

        # Build one-atom system
        self.system_one = pi.SystemOne(self.state_one.getSpecies(), self.cache)
        self.system_one.restrictEnergy(self.state_one.getEnergy() - 30, self.state_one.getEnergy() + 30)
        self.system_one.restrictN(self.state_one.getN() - 1, self.state_one.getN() + 1)
        self.system_one.restrictL(self.state_one.getL() - 1, self.state_one.getL() + 1)
示例#4
0
    def test_basisvectors(self):

        one_atom_basisvectors_indices = [[0, 0], [0, 1], [1, 0], [1, 1]]

        # Setup states
        state_one = pi.StateOne("Cs", 60, 0, 0.5, 0.5)

        # One-atom system
        system_one = pi.SystemOne(state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(state_one.getEnergy() - 30, state_one.getEnergy() + 30)
        system_one.restrictN(state_one.getN() - 1, state_one.getN() + 1)
        system_one.restrictL(state_one.getL() - 1, state_one.getL() + 1)
        system_one.setEfield([5, 0, 0])
        system_one.diagonalize()
        basisvectors_one = system_one.getBasisvectors().toarray()
        assert basisvectors_one.shape[0] == basisvectors_one.shape[1]

        # Two-atom system
        system_two = pi.SystemTwo(system_one, system_one, self.cache)
        system_two.setMinimalNorm(0)
        system_two.setOneAtomBasisvectors(one_atom_basisvectors_indices)
        basisvectors_two = system_two.getBasisvectors().toarray()
        assert basisvectors_two.shape[0] == (basisvectors_one.shape[0])**2
        assert basisvectors_two.shape[1] == len(one_atom_basisvectors_indices)

        # Check results
        for n, [a, b] in enumerate(one_atom_basisvectors_indices):
            np.testing.assert_allclose(
                np.outer(basisvectors_one[:, a], basisvectors_one[:, b]).ravel(), basisvectors_two[:, n])
示例#5
0
    def test_permutation(self):
        #######################################################
        ### Check permutation symmetry of two atom systems ####
        #######################################################

        # Remark: calling restrictEnergy() would cause a small
        # deviation # TODO figure out exact reason (in case of
        # symmetrized basis states, the atom-atom interaction would
        # add energy to the diagonal)

        # Define states
        state_one = pi.StateOne("Rb", 61, 1, 0.5, 0.5)
        state_two = pi.StateTwo(state_one, state_one)

        # Build one atom system
        system_one = pi.SystemOne(state_one.element, self.path_cache)
        system_one.restrictEnergy(state_one.energy-20, state_one.energy+20)
        system_one.restrictN(state_one.n-1, state_one.n+1)
        system_one.restrictL(state_one.l-1, state_one.l+1)
        system_one.restrictJ(state_one.j-1, state_one.j+1)
        system_one.setBfield([100, 200, 300])
        system_one.setEfield([1, 2, 3])

        # Build two atom system
        system_two = pi.SystemTwo(system_one, system_one, self.path_cache)
        #system_two.restrictEnergy(state_two.energy-2, state_two.energy+2) # TODO
        system_two.setDistance(1)
        system_two.setOrder(3)

        # Diagonalize blockwise
        system_two_even = pi.SystemTwo(system_two)
        system_two_even.setConservedParityUnderPermutation(pi.EVEN)
        system_two_even.diagonalize()

        system_two_odd = pi.SystemTwo(system_two)
        system_two_odd.setConservedParityUnderPermutation(pi.ODD)
        system_two_odd.diagonalize()

        system_two_combined = system_two_even
        system_two_combined.add(system_two_odd)

        # Diagonalize altogether
        system_two.setConservedParityUnderPermutation(pi.NA)
        system_two.diagonalize()

        # Compare results
        w1 = np.sort(system_two_combined.diagonal)
        w2 = np.sort(system_two.diagonal)

        maxdiff = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff = np.max(maxdiff)
        print("Two-atom system with permutation symmetry, relative maximum deviation: ", maxdiff)
        self.assertAlmostEqual(maxdiff, 0, places=9)
示例#6
0
    def test_rotation_hamiltonian(self):

        # Hamiltonian (in canonical basis) and overlaps after rotating the system with/without atom-field interactions
        system_one_tmp = pi.SystemOne(self.system_one)
        system_one_tmp.setEfield([0.2, 0, 0.3])
        system_one_tmp.setBfield([0, 1, 0])
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma)
        hamiltonian1 = system_one_tmp.getHamiltonian().todense()
        system_one_tmp.diagonalize()
        overlaps1 = system_one_tmp.getOverlap(pi.StateOne("Rb", 61, 2, 1.5, 1.5))

        system_one_tmp = pi.SystemOne(self.system_one)
        # is of no importance for the overlaps, but for the hamiltonians
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma)
        system_one_tmp.setEfield(np.dot(self.rotator.T, [0.2, 0, 0.3]))
        system_one_tmp.setBfield(np.dot(self.rotator.T, [0, 1, 0]))
        hamiltonian2 = system_one_tmp.getHamiltonian().todense()
        system_one_tmp.diagonalize()
        overlaps2 = system_one_tmp.getOverlap(pi.StateOne("Rb", 61, 2, 1.5, 1.5))

        system_one_tmp = pi.SystemOne(self.system_one)
        # is of no importance for the overlaps, but for the hamiltonians
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma)
        system_one_tmp.setEfield([0.2, 0, 0.3], self.alpha, self.beta, self.gamma)
        system_one_tmp.setBfield([0, 1, 0], self.alpha, self.beta, self.gamma)
        hamiltonian3 = system_one_tmp.getHamiltonian().todense()
        system_one_tmp.diagonalize()
        overlaps3 = system_one_tmp.getOverlap(pi.StateOne("Rb", 61, 2, 1.5, 1.5))

        system_one_tmp = pi.SystemOne(self.system_one)
        system_one_tmp.setEfield([0.2, 0, 0.3])
        system_one_tmp.setBfield([0, 1, 0])
        system_one_tmp.diagonalize()
        overlaps4 = system_one_tmp.getOverlap(pi.StateOne("Rb", 61, 2, 1.5, 1.5), -self.gamma, -self.beta, -self.alpha)

        # Check that everything is the same
        np.testing.assert_allclose(overlaps1, overlaps2, rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(overlaps1, overlaps3, rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(overlaps1, overlaps4, rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(hamiltonian1, hamiltonian2, rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(hamiltonian1, hamiltonian3, rtol=1e-4, atol=1e-6)
示例#7
0
    def test_rotation_derotate(self):
        # Add interaction to the Hamiltonian and diagonalize it
        system_one_interacting = pi.SystemOne(self.system_one)
        system_one_interacting.setEfield([0, 0, 0.1])
        system_one_interacting.setBfield([0, 1, 0])
        system_one_interacting.diagonalize()

        # Original eigen pairs
        eigenvectors1 = system_one_interacting.getBasisvectors()
        eigenvalues1 = system_one_interacting.getHamiltonian().diagonal()

        # Eigen pairs after rotating and derotating
        system_one_tmp = pi.SystemOne(system_one_interacting)
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma)
        system_one_tmp.rotate(-self.gamma, -self.beta, -self.alpha)
        eigenvectors2 = system_one_tmp.getBasisvectors()
        eigenvalues2 = system_one_tmp.getHamiltonian().diagonal()

        # Check that everything is the same
        np.testing.assert_allclose(eigenvalues1, eigenvalues2, rtol=1e-6)
        np.testing.assert_allclose(eigenvectors1.A, eigenvectors2.A, rtol=1e-6)
示例#8
0
    def test_rotation_phase(self):
        angle = 0.84

        # Phase due to rotation
        phases1 = self.system_one.getBasisvectors().todense()

        system_one_tmp = pi.SystemOne(self.system_one)
        system_one_tmp.rotate(angle, 0, 0)
        phases2 = system_one_tmp.getBasisvectors().todense()

        # Check diagonality
        np.testing.assert_allclose(phases1, np.diag(np.diag(phases1)), rtol=1e-4, atol=1e-6)
        np.testing.assert_allclose(phases2, np.diag(np.diag(phases2)), rtol=1e-4, atol=1e-6)

        # Check absolute value
        np.testing.assert_allclose(np.abs(phases1), np.abs(phases2), rtol=1e-4, atol=1e-6)

        # Check phases
        array_M = (np.angle(np.diag(phases2)) - np.angle(np.diag(phases1))) / angle
        for state, M in zip(system_one_tmp.getStates(), array_M):
            self.assertAlmostEqual(state.getM(), M)
示例#9
0
    def test_exception(self):

        one_atom_basisvectors_indices = [[0, 0], [0, 0]]

        # Setup states
        state_one = pi.StateOne("Cs", 60, 0, 0.5, 0.5)

        # One-atom system
        system_one = pi.SystemOne(state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(state_one.getEnergy() - 30, state_one.getEnergy() + 30)
        system_one.restrictN(state_one.getN() - 1, state_one.getN() + 1)
        system_one.restrictL(state_one.getL() - 1, state_one.getL() + 1)
        system_one.setEfield([5, 0, 0])
        system_one.diagonalize()
        basisvectors_one = system_one.getBasisvectors().toarray()

        # Two-atom system
        system_two = pi.SystemTwo(system_one, system_one, self.cache)
        system_two.setMinimalNorm(0)
        with self.assertRaises(RuntimeError) as context:
            system_two.setOneAtomBasisvectors(one_atom_basisvectors_indices)
        self.assertTrue('not unique' in str(context.exception))
示例#10
0
    def test_diagonalization_bounded(self):

        # Setup states
        state_one = pi.StateOne("Cs", 60, 0, 0.5, 0.5)

        # Build one-atom system
        system_one = pi.SystemOne(state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(state_one.getEnergy() - 100, state_one.getEnergy() + 100)
        system_one.restrictN(state_one.getN() - 1, state_one.getN() + 1)
        system_one.restrictL(state_one.getL() - 1, state_one.getL() + 1)
        system_one.restrictM(state_one.getM(), state_one.getM())
        system_one.setEfield([0, 0, 1])
        system_one.setBfield([0, 0, 50])

        # Determine energy bounds
        energy_lower_bound = state_one.getEnergy() - 20
        energy_upper_bound = state_one.getEnergy() + 20

        # Diagonalize using FEAST
        system_one.diagonalize(energy_lower_bound, energy_upper_bound, 0.01)

        # Check results
        self.assertEqual(system_one.getNumStates(), 9)
        self.assertEqual(system_one.getNumBasisvectors(), 4)
示例#11
0
    def test_rotation_overlap(self):
        states_to_calculate_overlap_with = [
            pi.StateOne("Rb", 61, 2, pi.ARB, 1.5),
            pi.StateOne("Rb", 60, 2, 1.5, 1.5)
        ]

        # Add interaction to the Hamiltonian and diagonalize it
        system_one_interacting = pi.SystemOne(self.system_one)
        system_one_interacting.setEfield([0, 0, 0.1])
        system_one_interacting.setBfield([0, 1, 0])
        system_one_interacting.diagonalize()

        # Overlap with rotated system
        system_one_tmp = pi.SystemOne(system_one_interacting)
        system_one_tmp.rotate(self.to_z_axis, self.to_y_axis)
        overlap_rotated_system1 = system_one_tmp.getOverlap(states_to_calculate_overlap_with)

        system_one_tmp = pi.SystemOne(system_one_interacting)
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma)
        overlap_rotated_system2 = system_one_tmp.getOverlap(states_to_calculate_overlap_with)

        system_one_tmp = pi.SystemOne(system_one_interacting)
        # gamma can be arbitrary, it just leads to a phase
        system_one_tmp.rotate(self.alpha, self.beta, self.gamma + 0.8342)
        overlap_rotated_system3 = system_one_tmp.getOverlap(states_to_calculate_overlap_with)

        # Overlap with rotated states
        system_one_tmp = pi.SystemOne(system_one_interacting)
        overlap_rotated_states1 = system_one_tmp.getOverlap(
            states_to_calculate_overlap_with, -self.gamma, -self.beta, -self.alpha)

        system_one_tmp = pi.SystemOne(system_one_interacting)
        overlap_rotated_states2 = system_one_tmp.getOverlap(
            states_to_calculate_overlap_with, -self.gamma + 0.8342, -self.beta, -self.alpha)

        # Check that everything is the same
        np.testing.assert_allclose(overlap_rotated_system1, overlap_rotated_system2, rtol=1e-6)
        np.testing.assert_allclose(overlap_rotated_system1, overlap_rotated_system3, rtol=1e-6)
        np.testing.assert_allclose(overlap_rotated_system1, overlap_rotated_states1, rtol=1e-6)
        np.testing.assert_allclose(overlap_rotated_system1, overlap_rotated_states2, rtol=1e-6)
示例#12
0
    def test_combined(self):
        #######################################################
        ### Check combined binary symmetries ##################
        #######################################################

        # Remark: calling restrictEnergy() would cause a small
        # deviation # TODO figure out exact reason (in case of
        # symmetrized basis states, the atom-atom interaction would
        # add energy to the diagonal)

        # Define states
        state_one = pi.StateOne("Rb", 61, 1, 0.5, 0.5)
        state_two = pi.StateTwo(state_one, state_one)

        # Build one atom system
        system_one = pi.SystemOne(state_one.element, self.path_cache)
        system_one.restrictEnergy(state_one.energy-20, state_one.energy+20)
        system_one.restrictN(state_one.n-1, state_one.n+1)
        system_one.restrictL(state_one.l-1, state_one.l+1)
        system_one.restrictJ(state_one.j-1, state_one.j+1)
        system_one.setBfield([0, 100, 0])

        system_one_combined = pi.SystemOne(system_one)
        system_one_combined.setConservedParityUnderReflection(pi.EVEN)
        system_one_combined.diagonalize()
        system_one_inverse = pi.SystemOne(system_one)
        system_one_inverse.setConservedParityUnderReflection(pi.ODD)
        system_one_inverse.diagonalize()
        system_one_combined.add(system_one_inverse)

        system_one.setConservedParityUnderReflection(pi.NA)
        system_one.diagonalize()

        # Build two atom system
        system_two = pi.SystemTwo(system_one, system_one, self.path_cache)
        system_two.setDistance(1)
        system_two.setOrder(3)
        system_two.diagonalize()

        # Note: it is important to use system_one_combined
        system_two_from_combined = pi.SystemTwo(system_one_combined, system_one_combined, self.path_cache)
        system_two_from_combined.setDistance(1)
        system_two_from_combined.setOrder(3)

        system_two_combined = None
        for sym_reflection, sym_inversion, sym_permutation in product([pi.EVEN, pi.ODD], [pi.EVEN, pi.ODD], [pi.EVEN, pi.ODD]):
            system_two_tmp = pi.SystemTwo(system_two_from_combined)
            system_two_tmp.setConservedParityUnderReflection(sym_reflection)
            system_two_tmp.setConservedParityUnderInversion(sym_inversion)
            system_two_tmp.setConservedParityUnderPermutation(sym_permutation)
            system_two_tmp.diagonalize()
            if system_two_combined is None: system_two_combined = system_two_tmp
            else: system_two_combined.add(system_two_tmp)
        system_two_combined.diagonalize()

        # Compare results
        w1 = np.sort(system_two_combined.diagonal)
        w2 = np.sort(system_two.diagonal)

        maxdiff = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff = np.max(maxdiff)
        print("Two-atom system with combined binary symmetries, relative maximum deviation: ", maxdiff)
        self.assertAlmostEqual(maxdiff, 0, places=9)
示例#13
0
    def test_rotation(self):
        #######################################################
        ### Check rotation symmetry of one atom systems #######
        #######################################################

        # Define state
        state_one = pi.StateOne("Rb", 61, 1, 0.5, 0.5)

        # Build one atom system
        system_one = pi.SystemOne(state_one.element, self.path_cache)
        system_one.restrictEnergy(state_one.energy-40, state_one.energy+40)
        system_one.restrictN(state_one.n-1, state_one.n+1)
        system_one.restrictL(state_one.l-1, state_one.l+1)
        system_one.restrictJ(state_one.j-1, state_one.j+1)
        system_one.setBfield([0, 0, 100])
        system_one.setEfield([0, 0, 1])

        momenta_one = np.arange(-(state_one.j+1), (state_one.j+1)+1)

        # Diagonalize blockwise
        system_one_momentum = {}
        for m in momenta_one:
            system_one_momentum[m] = pi.SystemOne(system_one)
            system_one_momentum[m].setConservedMomentaUnderRotation([m])
            system_one_momentum[m].diagonalize()

        system_one_combined = pi.SystemOne(system_one_momentum[momenta_one[0]])
        for m in momenta_one[1:]:
            system_one_combined.add(system_one_momentum[m])

        # Diagonalize altogether
        system_one_alternative = pi.SystemOne(system_one)
        system_one_alternative.setConservedMomentaUnderRotation(momenta_one)
        system_one_alternative.diagonalize()

        system_one.setConservedMomentaUnderRotation([pi.ARB])
        system_one.diagonalize()

        # Compare results
        w1 = np.sort(system_one_combined.diagonal)
        w2 = np.sort(system_one.diagonal)
        w3 = np.sort(system_one_alternative.diagonal)

        maxdiff12 = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff23 = np.abs((w3-w2)/(np.max([w3,w2],axis=0)))
        maxdiff12[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff23[np.abs(w3-w2)<1e-14] = np.abs(w3-w2)[np.abs(w3-w2)<1e-14]
        maxdiff12 = np.max(maxdiff12)
        maxdiff23 = np.max(maxdiff23)
        print("One-atom system with rotation symmetry, relative maximum deviation: ",
              maxdiff12, " (between alternatives: ", maxdiff23,")")
        self.assertAlmostEqual(maxdiff12, 0, places=9)
        self.assertAlmostEqual(maxdiff23, 0, places=9)

        #######################################################
        ### Check rotation symmetry of two atom systems #######
        #######################################################

        # Define state
        state_two = pi.StateTwo(state_one, state_one)

        # Diagonalize blockwise
        system_two_momentum = {}

        for m1 in momenta_one:
            for m2 in momenta_one:
                if m1+m2 in system_two_momentum:
                    tmp = pi.SystemTwo(system_one_momentum[m1], system_one_momentum[m2])
                    tmp.restrictEnergy(state_two.energy-2, state_two.energy+2)
                    system_two_momentum[m1+m2].add(tmp)
                else:
                    system_two_momentum[m1+m2] = pi.SystemTwo(system_one_momentum[m1], system_one_momentum[m2])
                    system_two_momentum[m1+m2].restrictEnergy(state_two.energy-2, state_two.energy+2)

        momenta_two = list(system_two_momentum.keys())

        for m in momenta_two:
            system_two_momentum[m].setDistance(1)
            system_two_momentum[m].setOrder(5)
            system_two_momentum[m].diagonalize()

        system_two_combined = pi.SystemTwo(system_two_momentum[momenta_two[0]])
        for m in momenta_two[1:]:
            system_two_combined.add(system_two_momentum[m])

        # Diagonalize blockwise, alternative
        system_two_momentum_alternative = {}
        for m in momenta_two:
            system_two_momentum_alternative[m] = pi.SystemTwo(system_one, system_one)
            system_two_momentum_alternative[m].restrictEnergy(state_two.energy-2, state_two.energy+2)
            system_two_momentum_alternative[m].setConservedMomentaUnderRotation([int(m)])
            system_two_momentum_alternative[m].setDistance(1)
            system_two_momentum_alternative[m].setOrder(5)
            system_two_momentum_alternative[m].diagonalize()

        system_two_combined_alternative = pi.SystemTwo(system_two_momentum_alternative[momenta_two[0]])
        for m in momenta_two[1:]:
            system_two_combined_alternative.add(system_two_momentum_alternative[m])

        # Diagonalize altogether
        system_two = pi.SystemTwo(system_one, system_one, self.path_cache)
        system_two.restrictEnergy(state_two.energy-2, state_two.energy+2)
        system_two.setDistance(1)
        system_two.setOrder(5)
        system_two.diagonalize()

        # Compare results
        w1 = np.sort(system_two_combined.diagonal)
        w2 = np.sort(system_two.diagonal)
        w3 = np.sort(system_two_combined_alternative.diagonal)

        maxdiff12 = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff23 = np.abs((w3-w2)/(np.max([w3,w2],axis=0)))
        maxdiff12[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff23[np.abs(w3-w2)<1e-14] = np.abs(w3-w2)[np.abs(w3-w2)<1e-14]
        maxdiff12 = np.max(maxdiff12)
        maxdiff23 = np.max(maxdiff23)
        print("Two-atom system with rotation symmetry, relative maximum deviation: ",
              maxdiff12, " (between alternatives: ", maxdiff23,")")
        self.assertAlmostEqual(maxdiff12, 0, places=9)
        self.assertAlmostEqual(maxdiff23, 0, places=9)
示例#14
0
    def test_reflection(self):
        #######################################################
        ### Check reflection symmetry of one atom systems #####
        #######################################################

        # Define state
        state_one = pi.StateOne("Rb", 61, 1, 0.5, 0.5)

        # Build one atom system
        system_one = pi.SystemOne(state_one.element, self.path_cache)
        system_one.restrictEnergy(state_one.energy-20, state_one.energy+20)
        system_one.restrictN(state_one.n-1, state_one.n+1)
        system_one.restrictL(state_one.l-1, state_one.l+1)
        system_one.restrictJ(state_one.j-1, state_one.j+1)
        system_one.setBfield([0, 100, 0])
        system_one.setEfield([1, 0, 2])

        # Diagonalize blockwise
        system_one_even = pi.SystemOne(system_one)
        system_one_even.setConservedParityUnderReflection(pi.EVEN)
        system_one_even.diagonalize()

        system_one_odd = pi.SystemOne(system_one)
        system_one_odd.setConservedParityUnderReflection(pi.ODD)
        system_one_odd.diagonalize()

        system_one_combined = pi.SystemOne(system_one_even)
        system_one_combined.add(system_one_odd)

        # Diagonalize altogether
        system_one.setConservedParityUnderReflection(pi.NA)
        system_one.diagonalize()

        # Compare results
        w1 = np.sort(system_one_combined.diagonal)
        w2 = np.sort(system_one.diagonal)

        maxdiff = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff = np.max(maxdiff)
        print("One-atom system with reflection symmetry, relative maximum deviation: ", maxdiff)
        self.assertAlmostEqual(maxdiff, 0, places=9)

        #######################################################
        ### Check reflection symmetry of two atom systems #####
        #######################################################

        # Remark: calling restrictEnergy() would cause a small deviation

        # Define state
        state_two = pi.StateTwo(state_one, state_one)

        # Diagonalize blockwise
        # Note: it is called odd in order to fit to the notion of the paper
        system_two_odd = pi.SystemTwo(system_one_even, system_one_even, self.path_cache)
        system_two_odd.add(pi.SystemTwo(system_one_odd, system_one_odd, self.path_cache))
        system_two_odd.setDistance(1)
        system_two_odd.setOrder(5)
        system_two_odd.diagonalize()

        system_two_even = pi.SystemTwo(system_one_even, system_one_odd, self.path_cache)
        system_two_even.add(pi.SystemTwo(system_one_odd, system_one_even, self.path_cache))
        system_two_even.setDistance(1)
        system_two_even.setOrder(5)
        system_two_even.diagonalize()

        system_two_combined =  pi.SystemTwo(system_two_even)
        system_two_combined.add(system_two_odd)

        # Diagonalize blockwise alternative
        # Note: it is important to use system_one_combined
        system_two_alternative= pi.SystemTwo(system_one_combined, system_one_combined, self.path_cache)
        system_two_alternative.setDistance(1)
        system_two_alternative.setOrder(5)

        system_two_even_alternative = pi.SystemTwo(system_two_alternative)
        system_two_even_alternative.setConservedParityUnderReflection(pi.EVEN)
        system_two_even_alternative.diagonalize()

        system_two_odd_alternative = pi.SystemTwo(system_two_alternative)
        system_two_odd_alternative.setConservedParityUnderReflection(pi.ODD)
        system_two_odd_alternative.diagonalize()

        # Diagonalize altogether
        system_two = pi.SystemTwo(system_one, system_one, self.path_cache)
        system_two.setDistance(1)
        system_two.setOrder(5)
        system_two.diagonalize()

        # Compare results
        w1 = np.sort(system_two_combined.diagonal)
        w2 = np.sort(system_two.diagonal)
        w3 = np.sort(system_two_even.diagonal)
        w4 = np.sort(system_two_odd.diagonal)
        w5 = np.sort(system_two_even_alternative.diagonal)
        w6 = np.sort(system_two_odd_alternative.diagonal)

        maxdiff12 = np.abs((w1-w2)/(np.max([w1,w2],axis=0)))
        maxdiff35 = np.abs((w3-w5)/(np.max([w3,w5],axis=0)))
        maxdiff46 = np.abs((w4-w6)/(np.max([w4,w6],axis=0)))
        maxdiff12[np.abs(w1-w2)<1e-14] = np.abs(w1-w2)[np.abs(w1-w2)<1e-14]
        maxdiff35[np.abs(w3-w5)<1e-14] = np.abs(w3-w5)[np.abs(w3-w5)<1e-14]
        maxdiff46[np.abs(w4-w6)<1e-14] = np.abs(w4-w6)[np.abs(w4-w6)<1e-14]
        maxdiff12 = np.max(maxdiff12)
        maxdiff35 = np.max(maxdiff35)
        maxdiff46 = np.max(maxdiff46)
        print("Two-atom system with reflection symmetry, relative maximum deviation: ",
              maxdiff12, " (between alternatives: ", maxdiff35,", ", maxdiff46, ")")
        self.assertAlmostEqual(maxdiff12, 0, places=9)
        self.assertAlmostEqual(maxdiff35, 0, places=9)
        self.assertAlmostEqual(maxdiff46, 0, places=9)
示例#15
0
    def test_integration(self):
        # Build one-atom system
        system_one = pi.SystemOne(self.state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(
            self.state_one.getEnergy() - 40, self.state_one.getEnergy() + 40)
        system_one.restrictN(self.state_one.getN() - 1, self.state_one.getN() + 1)
        system_one.restrictL(self.state_one.getL() - 1, self.state_one.getL() + 1)
        system_one.setEfield([0, 0, 0.1])
        system_one.setBfield([0, 0, 1])

        # Check for correct dimensions
        self.assertEqual(system_one.getNumBasisvectors(), 64)
        self.assertEqual(system_one.getNumStates(), 64)

        # Compare current results to the reference data (the results have to be
        # compared before diagonalization as the order of the eigenvectors is not
        # fixed)
        hamiltonian_one = system_one.getHamiltonian()
        basis_one = system_one.getBasisvectors()
        # without pruning, max_diff_hamiltonian might be infinity due to
        # division by zero
        hamiltonian_one.data *= (abs(hamiltonian_one).data > self.tolerance)
        hamiltonian_one.eliminate_zeros()
        basis_one.data *= (abs(basis_one).data > self.tolerance)
        basis_one.eliminate_zeros()

        if self.dump_new_reference_data:
            self.hamiltonian_one = hamiltonian_one.copy()
            self.basis_one = basis_one.copy()
        else:
            with open("integration_test_referencedata.pickle", "rb") as f:
                hamiltonian_one_reference, basis_one_reference, _, _ = pickle.load(
                    f)
                np.testing.assert_allclose(hamiltonian_one.A,
                                           hamiltonian_one_reference.A,
                                           rtol=self.tolerance)
                np.testing.assert_allclose(basis_one.A,
                                           basis_one_reference.A,
                                           rtol=self.tolerance)

        # Diagonalize one-atom system
        system_one.diagonalize()

        # Build one-atom system (for this test, system_one has to be diagonal by
        # itself because diagonalization can lead to different order of
        # eigenvectors)
        system_one = pi.SystemOne(self.state_one.getSpecies(), self.cache)
        system_one.restrictEnergy(
            self.state_one.getEnergy() - 40, self.state_one.getEnergy() + 40)
        system_one.restrictN(self.state_one.getN() - 1, self.state_one.getN() + 1)
        system_one.restrictL(self.state_one.getL() - 1, self.state_one.getL() + 1)

        # Build two-atom system
        system_two = pi.SystemTwo(system_one, system_one, self.cache)
        system_two.restrictEnergy(
            self.state_two.getEnergy() - 2, self.state_two.getEnergy() + 2)
        system_two.setConservedParityUnderPermutation(pi.ODD)
        system_two.setDistance(6)
        system_two.setAngle(0.9)

        # Check for correct dimensions
        self.assertEqual(system_two.getNumBasisvectors(), 239)
        self.assertEqual(system_two.getNumStates(), 468)

        # Compare current results to the reference data (the results have to be
        # compared before diagonalization as the order of the eigenvectors is not
        # fixed)
        hamiltonian_two = system_two.getHamiltonian()
        basis_two = system_two.getBasisvectors()
        # without pruning, max_diff_hamiltonian might be infinity due to
        # division by zero
        hamiltonian_two.data *= (abs(hamiltonian_two).data > self.tolerance)
        hamiltonian_two.eliminate_zeros()
        basis_two.data *= (abs(basis_two).data > self.tolerance)
        basis_two.eliminate_zeros()

        if self.dump_new_reference_data:
            self.hamiltonian_two = hamiltonian_two.copy()
            self.basis_two = basis_two.copy()
        else:
            with open("integration_test_referencedata.pickle", "rb") as f:
                _, _, hamiltonian_two_reference, basis_two_reference = pickle.load(
                    f)
                np.testing.assert_allclose(hamiltonian_two.A,
                                           hamiltonian_two_reference.A,
                                           rtol=self.tolerance)
                np.testing.assert_allclose(basis_two.A,
                                           basis_two_reference.A,
                                           rtol=self.tolerance)

        # Diagonalize two-atom system
        system_two.diagonalize()