Advertisement
Guest User

Untitled

a guest
Mar 4th, 2021
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.54 KB | None | 0 0
  1.  
  2. import os
  3. import math
  4. import std/strutils
  5.  
  6. type Dual* = tuple[val: float64, dot: float64]
  7.  
  8. func d_dual*(x: float64): Dual =
  9. (x, 0.0)
  10.  
  11. func d_var*(x: float64): Dual =
  12. (x, 1.0)
  13.  
  14. func `+`*(x, y: Dual): Dual =
  15. (x.val + y.val, x.dot + y.dot)
  16.  
  17. func `+`*(x: Dual, y: float64): Dual =
  18. (x.val + y, x.dot)
  19.  
  20. func `+`*(x: float64, y: Dual): Dual =
  21. (x + y.val, y.dot)
  22.  
  23. func `-`*(x, y: Dual): Dual =
  24. (x.val - y.val, x.dot - y.dot)
  25.  
  26. func `-`*(x: Dual, y: float64): Dual =
  27. (x.val - y, x.dot)
  28.  
  29. func `-`*(x: float64, y: Dual): Dual =
  30. (x - y.val, - y.dot)
  31.  
  32. func `*`*(x, y: Dual): Dual =
  33. (x.val * y.val, y.val * y.dot + x.dot * y.val)
  34.  
  35. func `*`*(x: Dual, y: float64): Dual =
  36. (x.val * y, x.dot * y)
  37.  
  38. func `*`*(x: float64, y: Dual): Dual =
  39. (x * y.val, x * y.dot)
  40.  
  41. func `/`*(x, y: Dual): Dual =
  42. (x.val / y.val, (x.dot * y.val - x.val * y.dot) / (y.val * y.val))
  43.  
  44. func `/`*(x: Dual, y: float64): Dual =
  45. (x.val / y, x.dot / y)
  46.  
  47. func `/`*(x: float64, y: Dual): Dual =
  48. (x / y.val, - y.dot * x / (y.val * y.val))
  49.  
  50. func sin*(x: Dual): Dual =
  51. (sin(x.val), x.dot * cos(x.val))
  52.  
  53. func cos*(x: Dual): Dual =
  54. (cos(x.val), x.dot * - sin(x.val))
  55.  
  56. type Parameters = tuple[m: float64, gm: float64, q_r: float64, p_r: float64, q_phi: float64, p_phi: float64, h0: float64]
  57.  
  58. func h(p: Parameters, qr: Dual, pr: Dual, pth: Dual): Dual = # the Hamiltonian
  59. (pr * pr + pth * pth / (qr * qr)) / (2.0 * p.m) - p.gm / qr
  60.  
  61. proc update_q(p: var Parameters, c: float64) = # dq/dt = dH / dp
  62. let qr = c * h(p, d_dual(p.q_r), d_var(p.p_r), d_dual(p.p_phi)).dot
  63. let qphi = c * h(p, d_dual(p.q_r), d_dual(p.p_r), d_var(p.p_phi)).dot
  64. p.q_r = p.qr + qr
  65. p.q_phi = p.qphi + qphi
  66.  
  67. proc update_p(p: var Parameters, d: float64) = # dp/dt = - dH / dq
  68. p.pr = p.pr - d * h(p, d_var(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).dot
  69.  
  70. proc plot(p: Parameters, t: float64) =
  71. let x = p.q_r * sin(p.q_phi)
  72. let y = p.q_r * cos(p.q_phi)
  73. 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
  74.  
  75. proc euler_cromer*(p: var Parameters, h: float64,
  76. uq: proc(p: var Parameters, h: float64),
  77. up: proc(p: var Parameters, h: float64)) =
  78. uq(p, h)
  79. up(p, h)
  80.  
  81. proc stormer_verlet*(p: var Parameters, h: float64,
  82. uq: proc(p: var Parameters, h: float64),
  83. up: proc(p: var Parameters, h: float64)) =
  84. uq(p, h * 0.5)
  85. up(p, h)
  86. uq(p, h * 0.5)
  87.  
  88. proc solve*(p: var Parameters,
  89. uq: proc(p: var Parameters, h: float64),
  90. up: proc(p: var Parameters, h: float64),
  91. output: proc(p: Parameters, h: float64)) =
  92. let
  93. args: seq[string] = commandLineParams()
  94. order: int64 = parseInt(args[1])
  95. h: float64 = parseFloat(args[2])
  96. steps: int64 = parseInt(args[3])
  97. var
  98. integrator: proc(p: var Parameters, h: float64, uq: proc(p: var Parameters, h: float64), up: proc(p: var Parameters, h: float64))
  99. case order
  100. of 1:
  101. integrator = euler_cromer
  102. of 2:
  103. integrator = stormer_verlet
  104. else:
  105. echo "invalid integrator ", order, " should be 1 or 2"
  106. p.h0 = h(p, d_dual(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).val
  107. for step in 1..steps:
  108. integrator(p, h, uq, up)
  109. output(p, step.float * h)
  110.  
  111. # ./h_newton 6 2 1 10000 1 12 .6
  112. let
  113. args: seq[string] = commandLineParams()
  114. mass = parseFloat(args[4])
  115. r0 = parseFloat(args[5])
  116. lfac = parseFloat(args[6])
  117. var p: Parameters = (mass, mass, r0, 0.0, 0.0, lfac * sqrt(r0), 0.0)
  118. solve(p, update_q, update_p, plot)
  119.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement