Giter Club home page Giter Club logo

nonlinearnormalform.jl's Introduction

NonlinearNormalForm

Stable Dev Build Status

Overview

This package is still in an early development stage

This package provides routines for calculating parameter-dependent normal forms of nonlinear Hamiltonian (and nearly Hamiltonian) maps expressed as truncated power series in the variables, using Lie algebraic methods. Basically, given some map, it computes the canonical transformation of the variables to coordinates where the nonlinear motion lies on circles in phase space. This allows calculation of invariants of the motion, and when leaving one resonance in the map, a single-resonance normal form. This package may be of particular interest to those in accelerator physics, electron microscopy, and astronomy.

For simplicity, we define an operator using the Poisson bracket as $$:f:g \triangleq \lbrace f, q \rbrace \ , $$

where $:f:$ can act on scalar functions, or element-wise on vector functions. With this definition, Hamilton's equations can then be expressed as

$$ \frac{d}{dt} \vec{z} = :-H:\ \vec{z} \ .$$

This has the solution (for some time $t$)

$$ \vec{z}_f = \exp{\left(:h:\right)}\vec{z}_0 = \vec{\zeta}_{t_0\rightarrow t_0+t}(\vec{z}_0) \ , \ \ \ \ \ \ \ h=-\int_{t_0}^t H \ dt$$

The transfer map $\vec{\zeta}_{t_0\rightarrow t_0+t}$ acts on phase space variables; it is finite dimension (= number of phase space variables) but, expressed as a power series in small phase space variables, may be infinite in order. It is more useful to instead work with the Lie representation of the map $\mathcal{M}_{\vec{\zeta}}=\exp{\left(:h:\right)}$, which acts on functions of the phase space variables instead of the phase space variables themselves, e.g.

$$\mathcal{M}_{\vec{\zeta}}f=f\circ\vec{\zeta} \ .$$

$\mathcal{M}_{\vec{\zeta}}$ is a Koopman operator. This replaces the nonlinear problem of a finite dimension (describing how the phase space variables transform to infinite order in the phase space variables), to a linear problem of infinite dimension (describing how each monomial coefficient in the Hamiltonian map transforms). The number of monomial coefficients is simply truncated at some order, chosen by the user.

Because the problem is now linear, the transformation of the monomial coefficients could be expressed using a (truncated) matrix, however this is notoriously slow and inconvenient to work with. This package implements the full Lie algebraic formulation using Lie operators.

While using the time-integral of the Hamiltonian as a generator of the time evolution (canonical transformation) in this way is useful, it is not always practical. In a particle tracking code for example, the motion may not always be exactly symplectic, e.g. when there is some small dissipation due to synchrotron radiation emission. In this case, a Hamiltonian cannot be obtained from an integrator, however the force field $\vec{F}$ on the particle is of course known from the integrator. Using the operator isomorphism $\vec{F}\cdot\vec{\nabla} \triangleq \ :h: $.

Setup

To use this package, in the Julia REPL run:

import Pkg; Pkg.add(path="https://github.com/bmad-sim/NonlinearNormalForm.jl")

Basic Usage

This package imports and reexports GTPSA.jl, a library for computing real and complex truncated power series to arbitrary orders in the variables and parameters. Before using NonlinearNormalForm.jl, you should have some familiarity with GTPSA.jl.

nonlinearnormalform.jl's People

Contributors

mattsignorelli avatar dependabot[bot] avatar

Stargazers

 avatar

Watchers

David Sagan avatar  avatar

nonlinearnormalform.jl's Issues

to-do

In GTPSA:

  • Move layer 2 implementations of "map" methods out of GTPSA and into this package? (Yes but then "parameters" in GTPSA.jl are meaningless, which might be okay, would have to move into this package, so unsure)
  • Allow changing Descriptors when number variables/parameters also changes? no for now
  • Documentation cleanup (fixing "Syntax" parts of gjh, etc)
  • Make TPSs callable for nicer evaluation syntax and also composition

Both:

  • SizedVectors required (not isbits) and confirmed is slower in tracking than regular vectors. Consider use of MVector/SVector for map fields. This is faster for small array sizes but concatenation current requires one to include all parameters in vector so may be slower for large number of parameters. Would need to Modify all lower level functions in GTPSA to also accept MVector or SVector (dense)

In NonlinearNormalForm

  • cleaned Probe ctor cleanup (all kwarg? but need number vars. MVectors + numvars in type. do not require v)
  • Probe for both types of trackingHow to deal with Probes? Should I overload indexing for probe struct to automatically set scalar part?
  • Map ctor cleanup
  • Map operators: \circ, ^, +, -
  • (Bi)quaternion implementation
  • Add ref column to map output
  • Probe cannot just take a phase space ray... need to fix this. Etiennes way is to set x0 with scalar part of TPSA map and keep scalar part in map

TPSAMap negative powers bug

For some reason, when writing (something)^(negative_number), Julia does not just call ^(something, negative_number). Instead it calls inv(something)^(-1*negative_number). This definition does not agree with FPP. For example, for a TPSAMap m, inv(m)^3 != inv(m^3). In fact inv(m)^3 is very problematic, whereas inv(m^3) is not.

This is only a problem for TPSAMaps

fix `outx_low` inv_work_low temporary

Because of of the bug in GTPSA, the output map length must be nn and not nv. Therefore this temporary is unnecessarily big.

After the bug is fixed the affected functions inv!, prep_comp_inv_work_low and prep_inv_work_low should be corrected. Also instead of allocating a new array for the quaternion if nv<4 instead of reusing m1x_low or whatever it was, instead just make m1x_low big enough to reuse quaternion part

rand(DAMap, spin=true) throws error.

julia> d = Descriptor(2,2)  # 2 variables, 2nd order
GTPSA Descriptor
-----------------------
Maximum order:     2
# Variables:       2

julia> m = rand(DAMap, spin=true) # Rand symplectic map including spin
ERROR: MethodError: no method matching rand(::Type{DAMap}; spin::Bool)

Closest candidates are:
  rand(::Type{X}, ::Integer, ::Integer...) where X got unsupported keyword argument "spin"
   @ Random /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Random/src/Random.jl:294
  rand(::Type{X}, ::Tuple{Vararg{Int64, N}} where N) where X got unsupported keyword argument "spin"
   @ Random /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Random/src/Random.jl:291
  rand(::Type{X}) where X got unsupported keyword argument "spin"
   @ Random /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Random/src/Random.jl:261
  ...

Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

`@fast` macro

At the time of this issue, the function gofix looks like

function gofix(xy::DAMap, order=1)
  desc = getdesc(xy)
  nv = numvars(desc)

  # 1: v = map-identity in harmonic planes, identity in spin
  v = zero(xy)
  for i=1:nv
    @inbounds v.x[i] =  xy.x[i] - mono(i,use=desc)
  end
  v.Q.q[1] = 1

  # 2: map is cut to order 2 or above
  cut!(v,v,order+1)

  # 3: map is inverted at least to order 1:
  inv!(v,v)

  # 4: a map x is created with dimension nv
  # x is zero except for the parameters and delta if coasting
  x = zero(v) # default identity in parameters
  x.Q.q[1] = 1 # identity in spin
  compose!(v,v,x)

  # 5: add back in identity
  for i=1:nv
    @inbounds v.x[i] += mono(i,use=desc)
  end

  return v
end

This is pretty fast (could be made faster by proper use of work temporaries accessible by user of inv and compose) , however this is not the easiest to read. gofix could instead be written as

function gofix(xy::DAMap, order=1)
  m = cut(xy, order+1)
  return (m-I)^-1zero(m)+I
end

This is much easier to understand and read, however much slower. For the best of both worlds, a macro must be implemented to convert the above easy-to-read function to its faster less-easy-to-read function. The approach could be the same as that taken for @FastGTPSA in GTPSA.jl

rand(DAMap, spin=true) does not give higher order spin terms.

julia> d = Descriptor(2,2);
julia> m = rand(DAMap, spin=true) # Rand symplectic map including spin
DAMap{Float64, TPS, Quaternion{TPS}, Nothing}:
Reference Orbit Vector{Float64}:
1:   0.0
2:   0.0

Orbital Ray Vector{TPS}:
  Out  Coefficient                Order   Exponent
----------------------------------------------------
   1:   8.1101993966198205e-01      1      1   0
   1:  -1.6248124638669312e-01      1      0   1
   1:  -2.4366333428567447e-01      2      2   0
   1:  -1.4374421426166708e+00      2      1   1
   1:  -1.2069500706559679e+00      2      0   2
----------------------------------------------------
   2:   2.0066006241921230e-01      1      1   0
   2:   1.1928146962222499e+00      1      0   1
   2:   1.1918359785245087e+00      2      2   0
   2:  -1.1645682660555752e-01      2      1   1
   2:   7.7011103482282994e-01      2      0   2

Quaternion{TPS}:
  Out  Coefficient                Order   Exponent
----------------------------------------------------
  q0:   1.0745368850792125e-01      0      0   0
----------------------------------------------------
  q1:   6.9840876842554311e-01      0      0   0
----------------------------------------------------
  q2:   6.9444018451635481e-01      0      0   0
----------------------------------------------------
  q3:   1.3576349708684621e-01      0      0   0

how to account for non-oscillating plane

FPP accounts for longitudinal drift (RF off) with a special setting ndpt which treats the longitudinal as a parameter but must also satisfy poisson bracket (unlike the rest of the parameters which are just knobs). My current thinking is for NonlinearNormalForm to extend the Descriptor constructors to allow for this

Error installing NF package

What I see is:

julia> import Pkg; Pkg.add(path="https://github.com/bmad-sim/NonlinearNormalForm.jl")
Cloning git-repo https://github.com/bmad-sim/NonlinearNormalForm.jl
Updating git-repo https://github.com/bmad-sim/NonlinearNormalForm.jl
Updating registry at ~/.julia/registries/General.toml
Resolving package versions...
ERROR: Unsatisfiable requirements detected for package GTPSA_jll [a4739e29]:
GTPSA_jll [a4739e29] log:
├─possible versions are: 1.0.0-1.3.0 or uninstalled
└─restricted to versions 1.3.1-1 by GTPSA [b27dd330] — no versions left
└─GTPSA [b27dd330] log:
├─possible versions are: 0.6.1 or uninstalled
├─restricted to versions 0.5.2-0.5 by NonlinearNormalForm [05e19671] — no versions left
│ └─NonlinearNormalForm [05e19671] log:
│ ├─possible versions are: 1.0.0 or uninstalled
│ └─NonlinearNormalForm [05e19671] is fixed to version 1.0.0-DEV
└─GTPSA [b27dd330] is fixed to version 0.6.1
Stacktrace:
[1] check_constraints(graph::Pkg.Resolve.Graph)
@ Pkg.Resolve /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Resolve/graphtype.jl:998
[2] Pkg.Resolve.Graph(compat::Dict{…}, compat_weak::Dict{…}, uuid_to_name::Dict{…}, reqs::Dict{…}, fixed::Dict{…}, verbose::Bool, julia_version::VersionNumber)
@ Pkg.Resolve /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Resolve/graphtype.jl:345
[3] deps_graph(env::Pkg.Types.EnvCache, registries::Vector{…}, uuid_to_name::Dict{…}, reqs::Dict{…}, fixed::Dict{…}, julia_version::VersionNumber, installed_only::Bool)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:586
[4] resolve_versions!(env::Pkg.Types.EnvCache, registries::Vector{…}, pkgs::Vector{…}, julia_version::VersionNumber, installed_only::Bool)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:406
[5] targeted_resolve(env::Pkg.Types.EnvCache, registries::Vector{…}, pkgs::Vector{…}, preserve::Pkg.Types.PreserveLevel, julia_version::VersionNumber)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:1360
[6] tiered_resolve(env::Pkg.Types.EnvCache, registries::Vector{…}, pkgs::Vector{…}, julia_version::VersionNumber, try_all_installed::Bool)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:1349
[7] _resolve(io::Base.TTY, env::Pkg.Types.EnvCache, registries::Vector{…}, pkgs::Vector{…}, preserve::Pkg.Types.PreserveLevel, julia_version::VersionNumber)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:1370
[8] add(ctx::Pkg.Types.Context, pkgs::Vector{…}, new_git::Set{…}; preserve::Pkg.Types.PreserveLevel, platform::Base.BinaryPlatforms.Platform)
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:1387
[9] add
@ Pkg.Operations /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/Operations.jl:1376 [inlined]
[10] add(ctx::Pkg.Types.Context, pkgs::Vector{…}; preserve::Pkg.Types.PreserveLevel, platform::Base.BinaryPlatforms.Platform, kwargs::@kwargs{…})
@ Pkg.API /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/API.jl:278
[11] add(pkgs::Vector{Pkg.Types.PackageSpec}; io::Base.TTY, kwargs::@kwargs{})
@ Pkg.API /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/API.jl:159
[12] add(pkgs::Vector{Pkg.Types.PackageSpec})
@ Pkg.API /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Pkg/src/API.jl:148
[13] add(; name::Nothing, uuid::Nothing, version::Nothing, url::Nothing, rev::Nothing, path::String, mode::Pkg.Types.PackageMode, subdir::Nothing, kwargs::@kwargs{})
@ Pkg.API ./boot.jl:0
[14] top-level scope
@ REPL[1]:1
Some type information was truncated. Use show(err) to see complete types.

julia>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.