LupoLab / Luna.jl

Nonlinear optical pulse propagator
MIT License
66 stars 27 forks source link

Free propogation using Luna #323

Open eliso02 opened 1 year ago

eliso02 commented 1 year ago

Hi

I'm trying to understand how to use Luna for free propagation with some addons and would appriciate your help. These are the specific things I'm interested in understanding how my beam would look:

  1. I have a focusing mirror
  2. after a short distance I have 1mm thin window and than Gas with some pressure for about 10m.
  3. Another thin fused silica window.
  4. Than collimating mirror
  5. chirp mirrors

What I need to understand is how my beam will look like and the SPM. (including option with larger power than Pcritical / self focusing option for plasma / blue shift)

Would aprriciate your help in understanding how to use Luna for it.

Thanks

chrisbrahms commented 1 year ago

Hi!

Apologies for the slow response.

Luna can definitely do this, but there is currently no super-simple interface for this sort of thing like there is for capillary propagation. A good starting point is the example radial.jl in the low-level interface.

Do you want/need to model the nonlinear propagation in the windows as well as in the gas? If not, then the simplest way of getting the simulation you want is:

  1. Define your field (with Fields.GaussGaussField) via the nominal focal spot size and focal plane with some linear back-propagation to where you want to start the nonlinear propagation simulation.
  2. Add the spectral phase of the first window using Fields.prop_material!.
  3. Run the nonlinear propagation similar to the example linked to above.
  4. Add the spectral phase of the window and chirped mirrors (and if you like, the spatial phase function of the collimating mirror)

This approach ignores a few subtleties of your system (e.g. spherical aberration/astigmatism from your focusing mirror) but would be the quickest to implement.

If you also need to implement the nonlinear propagation inside the windows, you would need to run three nonlinear simulations in sequence, using the result of the first as the input for the second etc. Only the chirped mirrors would be modeled purely linearly in this approach.

Hope this helps to get you started, but happy to help more if needed (I have a bit more time now so should be able to answer quicker than 3 weeks!)

eliso02 commented 1 year ago

Hi Chris

I got lost with the code there because there are no comments in that example. About the back propagation, why do we need it? I mean, we don't know what we will get and want to simpulate it. Regarding the window, I assume we can leave the non linear propagation (inside the window) at the moment but do add the phases (GDD and so on for fused silica).

Is that possible to ask you maybe to write a small sample code according to my description that I can play with and adjust, and than ask more questions?

chrisbrahms commented 1 year ago

I've quickly made up a commented example which does most of what you want. it's still a bit messy but hopefully will get you started. you will have to play around with the parameters.

about the back-propagation: you'll see this in the example, but what I mean is that to simulate a focusing mirror, the easiest thing is to create a Gaussian focus and then linearly back-propagate to the focusing mirror, rather than adding the focusing spatial phase manually. this is what Fields.GausGaussField with a propz argument can do. You could also do it differently (define a field without a propz argument and multiply by the correct spatial phase).

https://gist.github.com/chrisbrahms/e706fa9a9759c4ad4f83082c5fee35dc

highflyer737 commented 1 year ago

How would I add "the focusing spatial phase manually"? Say I wanted to propagate through a multipass system? What would the best approach be?

Thanks

chrisbrahms commented 1 year ago

Instead of defining a GaussGaussField with a nominal focus size and the propz keyword argument set, you'd use the far-field (collimated) beam size without propz. Without anything else done to it, this would then behave like a collimated laser beam, simply diverging due to diffraction (or self-focusing if the critical power is exceeded). To make it focus as with an optic, you multiply by the correct phase factor, like this:

# assume q is the QDHT as in the example
Eωk, transform, FT = Luna.setup(...) # create input field
Eωr = q \ Eωk # inverse QDHT: Eωk is E(ω, k) so Eωr is E(ω, r)

# calculate kz(ω, k_perp)
kzsq = (grid.ω/PhysData.c).^2 .- reshape(q.k.^2, (1, length(q.k)))
kzsq[kzsq .< 0] .= 0
kz = sqrt.(kzsq)

# phase imparted by reflection off of a parabolic mirror at normal incidence
# f is the focal length of the mirror
# q.r is the radial coordinate in the simulation
φr_foc = -kz .* reshape(q.r.^2/2f, (1, length(q.r))) 

#multiply by phase factor
Eωr_foc = Eωr .* exp.(-1im .* φr_foc)

# transform back to E(ω, k)
Eωk_foc = q*Eωr_foc

# run your simulation with the new field as the input
Luna.run(Eωk_foc, grid, ...)

Note that the phase is a function of radial position and frequency. Here I've used the phase transfer function of an ideal focusing optic (parabolic mirror) without any dispersion, but you could replace that with a spherical mirror just as easily.

To simulate a multipass system, you would then take the output of this simulation, apply a similar (or identical) phase factor to re-focus the beam, and feed that into a subsequent simulation--repeat for the number of passes. Note that this ignores radially asymmetric effects of course (e.g. off-axis reflection from a focusing mirror like in pulse compression MPCs).

highflyer737 commented 1 year ago

Thanks!

I assume the asymmetric case could also be handled with an appropriate (x, y)-based grid and phase function?

chrisbrahms commented 1 year ago

I assume the asymmetric case could also be handled with an appropriate (x, y)-based grid and phase function?

Yes, exactly the same way

highflyer737 commented 1 year ago

Thanks Chris! I've been playing around with various scenarios and it works really well.

to simulate a focusing mirror, the easiest thing is to create a Gaussian focus and then linearly back-propagate to the focusing mirror, ...

This definitely seems like the easier way to go. It works for me as in your example, but is failing for me at Luna.setup(...) on an (x, y) grid. Is this because there's currently no method defined for prop! with a FreeGrid?

ERROR: MethodError: no method matching prop!(::Array{ComplexF64, 3}, ::Float64, ::Luna.Grid.RealGrid, ::Luna.Grid.FreeGrid)

Closest candidates are:
  prop!(::Any, ::Any, ::Any, ::Hankel.QDHT)
...

Thanks

chrisbrahms commented 1 year ago

Whoops, you are totally correct: https://github.com/LupoLab/Luna.jl/blob/3988898e44a1d0c5c2d1423d697ec34e9b1784c9/src/Fields.jl#L395

I'll try and add it quickly now

highflyer737 commented 1 year ago

Thanks--it works great!