SunnySuite / Sunny.jl

Spin dynamics and generalization to SU(N) coherent states
Other
86 stars 19 forks source link

Pulses and operator average values #141

Closed ilijanikolov closed 1 year ago

ilijanikolov commented 1 year ago

I was wondering if there are any notebooks\examples of how to access the time domain average values of operators, for example <Ix(t)> of the system. In addition, is there any way to apply pulses (time-dependent Hamiltonian) or QM rotations (instantaneous pulse approximation) This is motivated by applications to NMR.

Thanks.

ddahlbom commented 1 year ago

Thanks for the suggestion. At the moment, we don't have any examples like that, but certainly this kind of thing can (and has) been done. You'll just have to put it together yourself at the moment. I'll give a brief outline of how this could be done below, but first:

Performing simulations with time-varying parameters or intermittent perturbations

Currently, the only part of the Hamiltonian which is easy to make time-dependent (in a non-hacky way) is the external field. This can be done with set_external_field!(sys, B) or, if you only want to change the field for certain sites, set_external_field_at!(sys, B, site). These functions may be called at any point between integration steps.

For example, suppose you have some time series stored in a vector pulse_series. This vector is nsteps long and each element of pulse_series is itself a 3-vector specifying the external field. Then you could modulate the field dynamically with the following loop.

for i in 1:nsteps
    step!(sys, integrator)

    set_external_field!(sys, pulse_series[i])

    # Record the trajectory of some observable or accumulate some average value
end

Similarly, you could apply an arbitrary perturbation to the spin state (e.g., random rotations) in the same way.

for i in 1:nsteps
    step!(sys, integrator)

    if mod1(i, interval) == 1   # Only do this every `interval` steps
        for site in eachsite(sys)
            perturb_spin!(sys, site)   # You would have to write `perturb_spin!` function
        end
    end

    # Record the trajectory of some observable or accumulate some average value
end

To change or record a spin, you would have to act on the state of your System. If you are in dipole mode (regular Landau-Lifshitz), the spins are stored in sys.dipoles. This is a 4-dimensional array, three lattice indices and a final atom index. Each entry of this array is a real 3-vector, storing sx, sy and sz in the global frame.

If you are in SU(N) mode, you can access dipole information in the same way, if you're only interested in dipoles. If you want to access the "generalized spins" (SU(N) coherent states), these are stored in sys.coherents, which is a similarly shaped array. Each entry of this array is a complex N-vector. You can use these to take the expectation value of an arbitrary observable.

Lazersmoke commented 1 year ago

Just to add this, here's a working example on how to build a customized time-integrator using Sunny's time-integrator as a base (based on David's design above), by way of integrating with the excellent DynamicalSystems.jl package.

Output should look something like this:

image

kbarros commented 1 year ago

@ilijanikolov is a time-dependent field sufficient for you, or did you have in mind more general perturbations to the hamiltonian?

ilijanikolov commented 1 year ago

This look good! Thanks so much!