static void MakeSpinOrbital() { // First, we assign an orbital index, say `5`. Note that we use 0-indexing, // so this is the 6th orbital. var orbitalIdx = 5; // Second, we assign a spin index, say `Spin.u` for spin up or `Spin.d` for spin down. var spin = Spin.d; // The spin-orbital (5, ↓) is then var spinOrbital0 = new SpinOrbital(orbitalIdx, spin); // A tuple `(int, Spin)` is also implicitly recognized as a spin-orbital. (int, Spin)tuple = (orbitalIdx, spin); // We explicitly specify the type of `spinOrbital1` to demonstrate // the implicit cast to `SpinOrbital`. SpinOrbital spinOrbital1 = tuple; Assert.True(spinOrbital1 == spinOrbital0); }
static void LadderOperator() { // Let us use the spin orbital created in the previous snippet. var spinOrbitalInteger = new SpinOrbital(5, Spin.d).ToInt(); // We specify either a creation or annihilation operator using // the enumerable type `RaisingLowering.u` or `RaisingLowering.d` // respectively; var creationEnum = RaisingLowering.u; // The type representing a creation operator is then initialized // as follows. Here, we index these operators with integers. // Hence we initialize the generic ladder operator with an // integer index type. var ladderOperator0 = new LadderOperator <int>(creationEnum, spinOrbitalInteger); // An alternate constructor for a LadderOperator instead uses // a tuple. var ladderOperator1 = new LadderOperator <int>((creationEnum, spinOrbitalInteger)); Assert.Equal(ladderOperator0, ladderOperator1); }
static void SpinOrbitalToInt() { // Let us use the spin orbital created in the previous snippet. var spinOrbital = new SpinOrbital(5, Spin.d); // Let us set the total number of orbitals to be say, `7`. var nOrbitals = 7; // This converts a spin-orbital index to a unique integer, in this case `12`, // using the formula `g(j,σ)`. var integerIndexHalfUp = spinOrbital.ToInt(IndexConvention.HalfUp, nOrbitals); // This converts a spin-orbital index to a unique integer, in this case `11`, // using the formula `h(j,σ)`. var integerIndexUpDown = spinOrbital.ToInt(IndexConvention.UpDown); // The default conversion uses the formula `h(j,σ)`, in this case `11`. var integerIndexDefault = spinOrbital.ToInt(); Assert.Equal(11, integerIndexDefault); Assert.Equal(12, integerIndexHalfUp); }
static void CreateHubbardHamiltonianTest() { ////////////////////////////////////////////////////////////////////////// // Introduction ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // In this example, we will create a representation of a // 1D Hubbard Hamiltonian using the quantum chemistry library. // This representation allows one to easily simulate Hamiltonian // time-evolution and obtain the cost of simulation. // The 1D Hubbard model has `n` sites. Let `i` be the site index, // `s` = 1,0 be the spin index, where 0 is up and 1 is down, `t` be the // hopping coefficient, `u` the repulsion coefficient, and aᵢₛ the fermionic // annihilation operator on the fermion indexed by `(i,s)`. The Hamiltonian // of this model is // // H ≔ - t/2 Σᵢ (a†ᵢₛ aᵢ₊₁ₛ + a†ᵢ₊₁ₛ aᵢₛ) + u Σᵢ a†ᵢ₀ a†ᵢ₁ aᵢ₁ aᵢ₀ // // Note that we use closed boundary conditions. // Contents: // - Spin-orbital representation // - Hamiltonian term representation // - Hamiltonian representation // - Building the Hubbard Hamiltonian // - Building the Hubbard Hamiltonian through orbital integrals // - Jordan–Wigner representation #region Spin-orbital representation // In the vocabulary of chemistry, the site index is also called the // orbital index. Thus a complete description of a fermion index is // as spin-orbital. Let us build an example. // First, we assign an orbital index, say `5`. var orbitalIdx = 5; // Second, we assign a spin index. In addition to // assigning them up and down integer indices, a good memonic is to // label then with a `Spin` enumeration type, say `u` for up and `d` // for down. var spin = Spin.d; // A spin-orbital index is then var spinOrbital0 = new SpinOrbital(orbitalIdx, spin); // We may also map the composite spin-orbital index into a single integer `x` // using the default formula `x = 2 * orbitalIdx + spin`; var spinOrbital0Int = spinOrbital0.ToInt(); // Other indexing schemes are possible. For example, we may use the formula // `x = orbitalIdx + nOrbitals * spin` var spinOrbital0HalfUpInt = spinOrbital0.ToInt(IndexConvention.HalfUp, 6); // Let us print these spin-orbitals to verify they contain the // expected information. Console.WriteLine($"Spin-orbital representation:"); Console.WriteLine($"spinOrbital0: (Orbital, Spin) index: ({spinOrbital0.Orbital},{spinOrbital0.Spin})."); Console.WriteLine($"spinOrbital0Int: (2 * Orbital + Spin) index: ({spinOrbital0Int})."); Console.WriteLine($"spinOrbital0HalfUpInt: (Orbital + nOrbitals * Spin) index: ({spinOrbital0HalfUpInt})."); Console.WriteLine($""); #endregion #region Hamiltonian term representation // Each term in the Hamiltonian is then labelled by an ordered sequence of // spin-orbtal indices, and a coefficient. By default, normal-ordering is // assumed, meaning that all creation operators are left of all annihilation // operators. By default, the number of creation and annihilation operators // are also assumed to be equal as chemistry Hamiltonian often conserve // particle number. // Let us represent the Hermitian fermion term 0.5 (a†ᵢₛ aᵢ₊₁ₛ + a†ᵢ₊₁ₛ aᵢₛ), where `i` is 5 and `s` // is spin up. As mentioned, we require a coefficient var coefficient = 0.5; // We also require a sequence of spin-orbital indices. var spinOrbitalIndices = new[] { (5, Spin.u), (6, Spin.u) };