Guest User

Untitled

a guest
Mar 6th, 2021
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.78 KB | None | 0 0
  1.  
  2. import os
  3. import math
  4. import std/strutils
  5.  
  6. type Dual* = tuple[val: float, dot: float]
  7.  
  8. func d_dual*(x: float): Dual =
  9. (x, 0.0)
  10.  
  11. func d_var*(x: float): 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: float): Dual =
  18. (x.val + y, x.dot)
  19.  
  20. func `+`*(x: float, 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: float): Dual =
  27. (x.val - y, x.dot)
  28.  
  29. func `-`*(x: float, 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: float): Dual =
  36. (x.val * y, x.dot * y)
  37.  
  38. func `*`*(x: float, 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: float): Dual =
  45. (x.val / y, x.dot / y)
  46.  
  47. func `/`*(x: float, 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
  57. Parameters* = object
  58. m: float
  59. gm: float
  60. q_r: float
  61. p_r: float
  62. q_phi: float
  63. p_phi: float
  64. h0: float
  65.  
  66. func h(p: Parameters, qr: Dual, pr: Dual, pth: Dual): Dual = # the Hamiltonian
  67. (pr * pr + pth * pth / (qr * qr)) / (2.0 * p.m) - p.gm / qr
  68.  
  69. proc update_q(p: var Parameters, c: float) = # coordinate updates, dq/dt = dH / dp
  70. let qr = c * h(p, d_dual(p.q_r), d_var(p.p_r), d_dual(p.p_phi)).dot
  71. let qphi = c * h(p, d_dual(p.q_r), d_dual(p.p_r), d_var(p.p_phi)).dot
  72. p.q_r = p.qr + qr
  73. p.q_phi = p.qphi + qphi
  74.  
  75. proc update_p(p: var Parameters, d: float) = # momentum updates, dp/dt = - dH / dq
  76. p.pr = p.pr - d * h(p, d_var(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).dot
  77.  
  78. proc plot(p: Parameters, t: float) =
  79. var diff = h(p, d_dual(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).val - p.h0
  80. var e = if diff > 0.0 : diff else: - diff
  81. echo p.q_r * sin(p.q_phi), " ", p.q_r * cos(p.q_phi), " ", 0.0, " ", t, " ", 10.0 * log10(if e >= 1e-36 : e else: 1e-36)
  82.  
  83. type
  84. Coefficients = seq[float]
  85. ArgumentError = object of ValueError
  86.  
  87. proc symplectic[T](p: var T, cd: Coefficients, uq, up)
  88. for i in countup(0, cd.len - 1):
  89. if (i mod 2) == 0: uq(p, cd[i]) else: up(p, cd[i])
  90. for i in countdown(cd.len - 2, 0):
  91. if (i mod 2) == 0: uq(p, cd[i]) else: up(p, cd[i])
  92.  
  93. proc solve*[T](args: seq[string], p: var T, uq, up, output: proc(p: var T, _: float))
  94. let
  95. order: int64 = parseInt(args[1])
  96. h: float = parseFloat(args[2])
  97. steps: int64 = parseInt(args[3])
  98. z1: float = 1.0 / (4.0 - pow(4.0, (1.0 / 3.0)))
  99. y1: float = 1.0 / (4.0 - pow(4.0, (1.0 / 5.0)))
  100. x1: float = 1.0 / (4.0 - pow(4.0, (1.0 / 7.0)))
  101. z0: float = 1.0 - 4.0 * z1
  102. y0: float = 1.0 - 4.0 * y1
  103. x0: float = 1.0 - 4.0 * y1
  104. cd: Coefficients = case order
  105. of 2: # Stormer-Verlet
  106. @[0.5 * h, h]
  107. of 4: # m4r35n357_4
  108. @[0.5 * h * z1, h * z1, h * z1, h * z1, 0.5 * h * (z1 + z0), h * z0]
  109. of 6: # m4r35n357_6
  110. @[0.5 * h * z1 * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, 0.5 * h * (z1 + z0) * y1, h * z0 * y1, 0.5 * h * (z0 + z1) * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, 0.5 * h * (z1 + z0) * y1, h * z0 * y1, 0.5 * h * (z0 + z1) * y1, h * z1 * y1, h * z1 * y1, h * z1 * y1, 0.5 * h * z1 * (y1 + y0), h * z1 * y0, h * z1 * y0, h * z1 * y0, 0.5 * h * (z1 + z0) * y0, h * z0 * y0]
  111. of 8: # m4r35n357_8
  112. @[0.5 * h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * z1 * (y1 + y0) * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, 0.5 * h * (z1 + z0) * y0 * x1, h * z0 * y0 * x1, 0.5 * h * (z0 + z1) * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, 0.5 * h * z1 * (y1 + y0) * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * z1 * (y1 + y0) * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, 0.5 * h * (z1 + z0) * y0 * x1, h * z0 * y0 * x1, 0.5 * h * (z0 + z1) * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, h * z1 * y0 * x1, 0.5 * h * z1 * (y1 + y0) * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * (z1 + z0) * y1 * x1, h * z0 * y1 * x1, 0.5 * h * (z0 + z1) * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, h * z1 * y1 * x1, 0.5 * h * z1 * y1 * (x1 + x0), h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, 0.5 * h * (z1 + z0) * y1 * x0, h * z0 * y1 * x0, 0.5 * h * (z0 + z1) * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, 0.5 * h * (z1 + z0) * y1 * x0, h * z0 * y1 * x0, 0.5 * h * (z0 + z1) * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, h * z1 * y1 * x0, 0.5 * h * z1 * (y1 + y0) * x0, h * z1 * y0 * x0, h * z1 * y0 * x0, h * z1 * y0 * x0, 0.5 * h * (z1 + z0) * y0 * x0, h * z0 * y0 * x0]
  113. else:
  114. echo "invalid order value ", order, ", should be 2, 4, 6, or 8"
  115. raise newException(ArgumentError, "Invalid integrator")
  116. p.h0 = h(p, d_dual(p.q_r), d_dual(p.p_r), d_dual(p.p_phi)).val
  117. for step in 1..steps:
  118. symplectic(p, cd, uq, up)
  119. output(p, step.float * h)
  120.  
  121. # ./h_newton 6 2 1 10000 1 12 .6
  122. let
  123. args: seq[string] = commandLineParams()
  124. mass = parseFloat(args[4])
  125. r0 = parseFloat(args[5])
  126. lfac = parseFloat(args[6])
  127. var p = Parameters(m: mass, gm: mass, q_r: r0, p_r: 0.0, q_phi: 0.0, p_phi: lfac * sqrt(r0), h0: 0.0)
  128. solve(args, p, update_q, update_p, plot)
  129.  
Add Comment
Please, Sign In to add comment