Advertisement
Guest User

Untitled

a guest
Mar 4th, 2021
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.54 KB | None | 0 0
  1. import math
  2.  
  3. type Dual* = tuple[val: float64, dot: float64]
  4.  
  5. func d_dual*(x: float64): Dual =
  6. (x, 0.0)
  7.  
  8. func d_var*(x: float64): Dual =
  9. (x, 1.0)
  10.  
  11. func `+`*(x, y: Dual): Dual =
  12. (x.val + y.val, x.dot + y.dot)
  13.  
  14. func `+`*(x: Dual, y: float64): Dual =
  15. (x.val + y, x.dot)
  16.  
  17. func `+`*(x: float64, y: Dual): Dual =
  18. (x + y.val, y.dot)
  19.  
  20. func `-`*(x, y: Dual): Dual =
  21. (x.val - y.val, x.dot - y.dot)
  22.  
  23. func `-`*(x: Dual, y: float64): Dual =
  24. (x.val - y, x.dot)
  25.  
  26. func `-`*(x: float64, y: Dual): Dual =
  27. (x - y.val, - y.dot)
  28.  
  29. func `*`*(x, y: Dual): Dual =
  30. (x.val * y.val, y.val * y.dot + x.dot * y.val)
  31.  
  32. func `*`*(x: Dual, y: float64): Dual =
  33. (x.val * y, x.dot * y)
  34.  
  35. func `*`*(x: float64, y: Dual): Dual =
  36. (x * y.val, x * y.dot)
  37.  
  38. func `/`*(x, y: Dual): Dual =
  39. (x.val / y.val, (x.dot * y.val - x.val * y.dot) / (y.val * y.val))
  40.  
  41. func `/`*(x: Dual, y: float64): Dual =
  42. (x.val / y, x.dot / y)
  43.  
  44. func `/`*(x: float64, y: Dual): Dual =
  45. (x / y.val, - y.dot * x / (y.val * y.val))
  46.  
  47. func sin*(x: Dual): Dual =
  48. (sin(x.val), x.dot * cos(x.val))
  49.  
  50. func cos*(x: Dual): Dual =
  51. (cos(x.val), x.dot * - sin(x.val))
  52.  
  53. type Parameters = tuple[m: float64, gm: float64, q_r: float64, p_r: float64, q_phi: float64, p_phi: float64, h0: float64]
  54.  
  55. func h(p: Parameters, qr: Dual, pr: Dual, pth: Dual): Dual = # the Hamiltonian
  56. (pr * pr + pth * pth / (qr * qr)) / (2.0 * p.m) - p.gm / qr
  57.  
  58. proc update_q(p: var Parameters, c: float64) = # dq/dt = dH / dp
  59. let qr = c * h(p, d_dual(p.q_r), d_var(p.p_r), d_dual(p.p_phi)).dot
  60. let qphi = c * h(p, d_dual(p.q_r), d_dual(p.p_r), d_var(p.p_phi)).dot
  61. p.q_r = p.qr + qr
  62. p.q_phi = p.qphi + qphi
  63.  
  64. proc update_p(p: var Parameters, d: float64) = # dp/dt = - dH / dq
  65. p.pr = p.pr - d * h(p, d_var(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).dot
  66.  
  67. proc plot(p: Parameters, t: float64) =
  68. let x = p.q_r * sin(p.q_phi)
  69. let y = p.q_r * cos(p.q_phi)
  70. echo x, " ", y, " ", 0.0, " ", t, " ", h(p, d_dual(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).val - p.h0
  71.  
  72. proc solve*(p: var Parameters,
  73. uq: proc(p: var Parameters, h: float64),
  74. up: proc(p: var Parameters, h: float64),
  75. output: proc(p: Parameters, h: float64)) =
  76. let
  77. steps: int64 = 10000
  78. h: float64 = 1.0
  79. #let args: seq[string] = parseCmdLine()
  80. p.h0 = h(p, d_dual(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).val
  81. for step in 1..steps:
  82. uq(p, h)
  83. up(p, h)
  84. output(p, step.float * h)
  85.  
  86. var p: Parameters = (1.0, 1.0, 12.0, 0.0, 0.0, 0.6 * sqrt(12.0), 0.0)
  87. solve(p, update_q, update_p, plot)
  88.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement