StationQ / Liquid

The Language-Integrated Quantum Operations (LIQUi|>) Simulator
http://StationQ.github.io/Liquid
Other
437 stars 97 forks source link

Electron spin in time-dependent magnetic field? #23

Closed Babber closed 8 years ago

Babber commented 8 years ago

Dear LIQUi|> Team, I am interested in a specific problem, and I am not sure if I could use LIQUi|> for this. I would like to simulate the evolution of the spin state of an electron in a time-dependent magnetic field B(t). The Hamiltonian is simply: H(t) = 1/2 * \mu_B * g_e * \sigma . B(t), where \sigma is a vector of the Pauli matrices. Is there a way to do this with LIQUi|>? In case, this is not yet available, do you plan to extend the code in this direction? Many thanks for any help.

alan-geller commented 8 years ago

You can do this using the Spin and SpinTerm classes.

Does your magnetic field change directions over time, or just change strength? The one is much simpler than the other, but both can be done.

Babber commented 8 years ago

Unfortunately also the direction is changing. In the scalar product in the Hamiltonian, B(t) is a 3D vector, and in the most general case, all three components can chage in time independently.

I was trying to figure out how to define a new Hamiltonian and integrate the Scrödinger eq., but I could not find enough info in the user guide and the documentation. Some example with a related problem would be very useful.

alan-geller commented 8 years ago

Chapter 8 in the users manual covers simulating spin glasses, possibly in an external magnetic field, so it's in the right area. Your situation is a little different; let me try to walk through what you'd need to do.

You can think of your system as a spin glass with only one spin, so no spin-spin terms, but with a varying magnetic field. This means that you have to use the "bottom level" Spin' constructor, passing it a list ofSpinTerms'. It also means that you'll need to discretize the time variation of your magnetic field.

First, you'll need to define operations for the three Pauli rotations you need. The `HamiltonianGates' module defines the one you need for Z, so you can import that module and just define the operations for X and Y:

open Microsoft.Research.Liquid.HamiltonianGates

// ZR is defined in this module

let XR (theta:float) (qs:Qubits) = Rpauli (2.0*theta) X qs
let YR (theta:float) (qs:Qubits) = Rpauli (2.0*theta) Y qs

You would have three SpinTerms, one for each Pauli matrix. Set the X one to schedule 0, the Y one to schedule 1, and the Z one to schedule 2. The operation should be one of XR, YR, and ZR, and the amplitude should be the rotation scaling factor for a unit magnetic field. Remember that you have to incorporate the length of the time step into the scaling factor, along with the electrodynamic factors.

The number of spins for the `Spin' constructor would be 1. You can probably leave the optional run mode parameter off; it will default to a first-order Trotter.

If you want to start in a state other than Z=+1, you can manipulate the Ket' property of theSpin' object to prepare whatever initial state you want.

Set the time' property of yourSpin' object to 0, to start at the beginning, before each run.

You would use the `Spin.Run' method to execute the simulation. Set dt to the last time step in your simulation; that is. For the schedule, you would pass in a list of arrays that specifies the strength of the magnetic field at different times. You can provide a schedule entry for every time step:

let sched = [0..dt] |> List.map (fun t -> (t, [| BX(t) ; BY(t) ; BZ(t) |])

Or, you can provide field strengths at specific timesteps, and the simulation will linearly interpolate between them:

let sched = [ (0, [| BX(0) ; BY(0) ; BZ(0) |]);
              (n, [| BX(n) ; BY(n) ; BZ(n) |]);
              (m, [| BX(m) ; BY(m) ; BZ(m) |]);
              ... ]

After the simulation finishes, you can access the qubit directly to get its current state.