fork(1) download
  1. #define RUNGE_KUTTA_4_INTEGRATION
  2.  
  3. using System;
  4.  
  5. namespace ConsoleApplication {
  6.  
  7. #region Runge Kutta 4 Integrator
  8.  
  9. /// <summary>Integrates position and velocity using the Runge Kutta 4 method</summary>
  10. public struct RungeKutta4 {
  11.  
  12. #region struct State
  13.  
  14. /// <summary>Stores the current state of the system</summary>
  15. private struct State {
  16.  
  17. /// <summary>Position of the object</summary>
  18. public float Position;
  19. /// <summary>Velocity the object is moving at</summary>
  20. public float Velocity;
  21.  
  22. }
  23.  
  24. #endregion // struct State
  25.  
  26. #region struct Derivative
  27.  
  28. /// <summary>Stores the derivative state of the system</summary>
  29. private struct Derivative {
  30.  
  31. /// <summary>Velocity of the object</summary>
  32. public float Velocity;
  33. /// <summary>Acceleration the object's velocity is increasing at</summary>
  34. public float Acceleration;
  35.  
  36. }
  37.  
  38. #endregion // struct Derivative
  39.  
  40. /// <summary>Performs one Runge Kutta 4 simulation step</summary>
  41. /// <param name="velocity">Velocity of the object</param>
  42. /// <param name="acceleration">Acceleration of the object at (t + dt)</param>
  43. /// <param name="deltaTime">Amount of time that will be simulated</param>
  44. /// <returns>The translation of the object after the specified delta time</returns>
  45. public float Step(ref float velocity, float acceleration, float deltaTime) {
  46. var state = new State();
  47. state.Position = 0.0f;
  48. state.Velocity = velocity;
  49.  
  50. this.acceleration = acceleration;
  51. integrate(ref state, deltaTime);
  52.  
  53. velocity = state.Velocity;
  54. return state.Position;
  55. }
  56.  
  57. /// <summary>Integrates the state over the specified delta time</summary>
  58. /// <param name="state">State that will be integrated</param>
  59. /// <param name="deltaTime">Amount of time that has passed</param>
  60. private void integrate(ref State state, float deltaTime) {
  61. Derivative a, b, c, d;
  62.  
  63. a = evaluate(state, 0.0f, new Derivative());
  64. b = evaluate(state, deltaTime * 0.5f, a);
  65. c = evaluate(state, deltaTime * 0.5f, b);
  66. d = evaluate(state, deltaTime, c);
  67.  
  68. float velocity = (
  69. 1.0f / 6.0f * (a.Velocity + 2.0f * (b.Velocity + c.Velocity) + d.Velocity)
  70. );
  71. float acceleration = (
  72. 1.0f / 6.0f * (a.Acceleration + 2.0f * (b.Acceleration + c.Acceleration) + d.Acceleration)
  73. );
  74.  
  75. state.Position += velocity * deltaTime;
  76. state.Velocity += acceleration * deltaTime;
  77. }
  78.  
  79. /// <summary>Linearly integrates a single state over the specified time</summary>
  80. /// <param name="initial">State at the beginning of the simulation</param>
  81. /// <param name="deltaTime">Amount of time that should be simulated</param>
  82. /// <param name="derivative">Derivative describing how the state changes</param>
  83. /// <returns>The state after the specified amount of time has passed</returns>
  84. private Derivative evaluate(State initial, float deltaTime, Derivative derivative) {
  85. State state;
  86. state.Position = initial.Position + derivative.Velocity * deltaTime;
  87. state.Velocity = initial.Velocity + derivative.Acceleration * deltaTime;
  88.  
  89. Derivative output;
  90. output.Velocity = state.Velocity;
  91. output.Acceleration = this.acceleration;
  92.  
  93. return output;
  94. }
  95.  
  96. /// <summary>Acceleration (constant over each step)</summary>
  97. private float acceleration;
  98.  
  99. }
  100.  
  101. #endregion // Runge Kutta 4 Integrator
  102.  
  103. internal class Program {
  104.  
  105. static void Test() {
  106. float delta = 1f/120f;
  107. float height = .001f;
  108. float impulse = 6.264f;
  109. float gravity = -9.81f;
  110. float mass = 80f;
  111. float velocity = 0;
  112.  
  113. float peakHeight = 0;
  114. while (height > 0)
  115. {
  116. #if RUNGE_KUTTA_4_INTEGRATION
  117.  
  118. float acceleration = gravity/mass;
  119. float impulses = impulse/mass;
  120. impulse = 0;
  121. acceleration += impulses/delta;
  122.  
  123. var rk4 = new RungeKutta4();
  124. height += rk4.Step(ref velocity, acceleration * mass, delta);
  125.  
  126. #else // EULER_INTEGRATION
  127.  
  128. float acceleration = gravity/mass;
  129. float impulses = impulse/mass;
  130. impulse = 0;
  131. acceleration += impulses/delta;
  132. velocity += (acceleration*mass)*delta/2f;
  133.  
  134. height += velocity*delta;
  135.  
  136. velocity += (acceleration*mass)*delta/2f;
  137.  
  138. #endif
  139.  
  140. if (height > peakHeight)
  141. peakHeight = height;
  142.  
  143. }
  144.  
  145. Console.WriteLine("PeakHeight: " + peakHeight);
  146. }
  147.  
  148. public static void Main(string[] args) {
  149. Test();
  150. }
  151. }
  152. }
Success #stdin #stdout 0s 131648KB
stdin
Standard input is empty
stdout
PeakHeight: 1.974736