(* by Nasser M. Abbasi, version:  July 26,2013 *)

Manipulate[
 tick;
 Module[{sol, t, \[Theta]1sol, \[Theta]2sol, v1sol, v2sol, eq1, eq2, 
   ic, \[Theta]1, \[Theta]2, result},
  
  If[state == "running" || state == "step" || state == "initial",
   eq1 = 3/2 r^2 m1 \[Theta]1''[t] + 
      r^2 ((k1 + k2) \[Theta]1[t] - k2 \[Theta]2[t]) == 0;
   eq2 = 3/2 r^2 m2 \[Theta]2''[t] + 
      r^2 (-k2 \[Theta]1[t] + (k2 + k3) \[Theta]2[t]) == 0;
   ic = {\[Theta]1[0] == \[Theta]1current, \[Theta]2[
       0] == \[Theta]2current, \[Theta]1'[0] == 
      v1current, \[Theta]2'[0] == v2current};
   sol = First@
     NDSolve[{eq1, eq2, 
       ic}, {\[Theta]1[t], \[Theta]2[t], \[Theta]1'[t], \[Theta]2'[
        t]}, {t, 0, stepSize}]
   ];
  
  If[state == "running" || state == "step",
   \[Theta]1current = \[Theta]1[t] /. sol /. t -> stepSize;
   \[Theta]2current = \[Theta]2[t] /. sol /. t -> stepSize;
   v1current = \[Theta]1'[t] /. sol /. t -> stepSize;
   v2current = \[Theta]2'[t] /. sol /. t -> stepSize;
   x1 = springRelaxedL + r \[Theta]1[t] /. sol /. t -> 0;
   x2 = x1 + springRelaxedL + r \[Theta]2[t] /. sol /. t -> 0;
   currentTime = currentTime + stepSize;
   If[state == "running",
    tick += del
    ];
   ];
  
  Text@drawSystem[currentTime, r, x1, 
    x2, \[Theta]1current, \[Theta]2current, v1current, v2current, m1, 
    m2, k1, k2, k3, showGrid]
  ],
 
 Text@Grid[{
    {
     Grid[{
       {
        Button[Text[Style["run", 11]], state = "running"; tick += del,
          ImageSize -> {50, 35}],
        Button[Text[Style["pause", 11]], state = "paused"; 
         tick += del, ImageSize -> {50, 35}]
        },
       {Button[Text[Style["step", 11]], state = "step"; tick += del, 
         ImageSize -> {50, 35}],
        Button[Text[Style["reset", 11]], state = "initial";
         tick = 0; \[Theta]10 = 0; \[Theta]1current = 0; \[Theta]20 = 
          0; \[Theta]2current = 0; v1current = 40.0*(2 Pi)/60; 
         v10 = 40.0;
         v2current = 0; v20 = 0; currentTime = 0; k1 = 100; k2 = 200; 
         k3 = 300; m1 = 6; m2 = 1; x1 = springRelaxedL; 
         x2 = 2 springRelaxedL; tick += del,
         ImageSize -> {50, 35}
         ]
        }
       }, Spacings -> {0.4, .2}, Alignment -> Center
      ]
     },
    {
     Grid[{
       {
        "step size", 
        Manipulator[
         Dynamic[stepSize, {stepSize = #} &], {0.001, 0.02, 0.001}, 
         ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[stepSize, {4, 3}]], "sec"
        },
       {Row[{Subscript["\[Theta]", 1]', "(0)"}], 
        Manipulator[
         Dynamic[v10, {v10 = #; v1current = v10*2 Pi/60} &], {0, 
          50, .1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[v10, {2, 1}]], "rpm"
        },
       {Row[{Subscript["\[Theta]", 2]', "(0)"}], 
        Manipulator[
         Dynamic[v20 , {v20 = #; v2current = v20*2 Pi/60} &], {0, 
          50, .1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[v20, {2, 1}]], "rpm"
        },
       {Text@TraditionalForm@Style[Subscript[k, 1], 11], 
        Manipulator[Dynamic[k1 , {k1 = #; tick += del} &],
         {100, 500, 1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[k1, 3]], "N/m"
        },
       {TraditionalForm@Style[Subscript[k, 2], 11], 
        Manipulator[Dynamic[k2 , {k2 = #; tick += del} &],
         {100, 500, 1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[k2, 3]], "N/m"
        },
       {TraditionalForm@Style[Subscript[k, 3], 11], 
        Manipulator[Dynamic[k3 , {k3 = #; tick += del} &],
         {100, 500, 1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[k3, 3]], "N/m"
        },
       {TraditionalForm@Style[Subscript[m, 1], 11], 
        Manipulator[Dynamic[m1 , {m1 = #; tick += del} &],
         {.1, 10, .1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[m1, {3, 1}]], "kg"
        },
       {TraditionalForm@Style[Subscript[m, 2], 11], 
        Manipulator[Dynamic[m2 , {m2 = #; tick += del} &],
         {.1, 10, .1}, ImageSize -> Tiny, ContinuousAction -> True], 
        Dynamic[padIt2[m2, {3, 1}]], "kg"
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Alignment -> Center, Spacings -> {.4, .1}
      ]
     }
    }],
 
 Row[{"show grid", Spacer[4], 
   Checkbox[Dynamic[showGrid, {showGrid = #; tick += del} &]]}],
 
 {{showGrid, True}, None},
 {{springRelaxedL, 2}, None},
 {{x1, 2}, None},(*keep same as springRelaxedL*)
 {{x2, 4}, None},(*keep same as 2*springRelaxedL*)
 {{r, .5}, None},
 {{state, "initial"}, None},
 {{stepSize, 0.015}, None},
 {{m1, 6}, None},
 {{m2, 1}, None},
 {{k1, 100}, None},
 {{k3, 300}, None},
 {{k2, 200}, None},
 {{\[Theta]10, 0}, None}, (*initial radial position m1*)
 {{\[Theta]20, 0}, None}, (*initial radial position m2*)
 {{v10, 40}, None}, (*initial angular position RPM, m2*)
 {{v20, 0}, None}, (*initial angula position RPM, m2*)
 
 {{\[Theta]1current, 0}, None}, (*current radial position m1*)
 {{\[Theta]2current, 0}, None}, (*current radial position m2*)
 {{v1current, 40 (2 Pi/60)}, 
  None}, (*current angular position, rad/sec m2*)
 {{v2current, 0 (2 Pi/60)}, 
  None}, (*current angula position rad/sec m2*)
 
 {{currentTime, 0}, None}, (*simulation time*)
 {{del, $MachineEpsilon}, None},
 {{tick, 0}, None},
 
 ControlPlacement -> Left,
 SynchronousUpdating -> False,
 SynchronousInitialization -> False,
 ContinuousAction -> False,
 Alignment -> Center,
 ImageMargins -> 0,
 FrameMargins -> 0,
 Paneled -> True,
 Frame -> False,
 AutorunSequencing -> {1},
 
 TrackedSymbols :> {tick},
 Initialization :>
  {
   integerStrictPositive = (IntegerQ[#] && # > 0 &);
   integerPositive = (IntegerQ[#] && # >= 0 &);
   numericStrictPositive = (Element[#, Reals] && # > 0 &);
   numericPositive = (Element[#, Reals] && # >= 0 &);
   numericStrictNegative = (Element[#, Reals] && # < 0 &);
   numericNegative = (Element[#, Reals] && # <= 0 &);
   bool = (Element[#, Booleans] &);
   numeric = (Element[#, Reals] &);
   integer = (Element[#, Integers] &);
   
   (*--------------------------------------------*)
   (* helper function for formatting             *)
   (*--------------------------------------------*)
   padIt1[v_?numeric, f_List] := 
    AccountingForm[Chop[v] , f, NumberSigns -> {"-", "+"}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True];
   (*--------------------------------------------*)
   (* helper function for formatting             *)
   (*--------------------------------------------*)
   padIt2[v_?numeric, f_List] := 
    AccountingForm[Chop[v] , f, NumberSigns -> {"", ""}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True];
   padIt2[v_?numeric, f_Integer] := 
    AccountingForm[Chop[v] , f, NumberSigns -> {"", ""}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True];
   
   (*--------------------------------------------*)
   getKE[m1_, m2_, v1_, v2_] := 
    Module[{i1 = 1/2 m1 r^2, i2 = 1/2 m2 r^2}, 
     1/2 i1 (v1)^2 + 1/2 m1 (r v1)^2 + 1/2 i2 (v2)^2 + 
      1/2 m2 (r v2)^2];
   getPE[\[Theta]1_, \[Theta]2_, k1_, k2_, k3_] := 
    1/2 k1 (r \[Theta]1)^2 + 1/2 k2 (r \[Theta]2 - r \[Theta]1)^2 + 
     1/2 k3 (r \[Theta]2)^2;
   (*--------------------------------------------*)
   drawSystem[currentTime_,
     r_(*radius of sphere*),
     x1_(*distance of center of 1st cylinder from left wall*),
     x2_(*distance of center of 2nd cylinder from left wall*),
     \[Theta]1sol_(*angle of rotation of first cyliner*),
     \[Theta]2sol_(*angle of rotation of second cyliner*),
     v1sol_(*anglular velocity of first cyliner*),
     v2sol_(*anglular velocity of first cyliner*),
     m1_, m2_, k1_, k2_, k3_, showGrid_] := Module[{ke, pe, h1},
     ke = getKE[m1, m2, v1sol, v2sol];
     pe = getPE[\[Theta]1sol, \[Theta]2sol, k1, k2, k3];
     
     h1 = Text@Style[Grid[{
          {"time (sec)",
           "P.E. (J)",
           "K.E. (J)",
           "energy (J)",
           Row[{Subscript["\[Theta]", 1]', " (rpm)"}],
           Row[{Subscript["\[Theta]", 2]', " (rpm)"}]
           },
          {padIt2[currentTime, {6, 2}],
           padIt2[pe, {6, 3}],
           padIt2[ke, {6, 3}],
           padIt2[ke + pe, {6, 3}],
           padIt2[v1sol*60/(2 Pi), {6, 3}],
           padIt2[v2sol*60/(2 Pi), {6, 3}]}
          },
         Frame -> All,
         FrameStyle -> Directive[Thickness[.001], Gray],
         Spacings -> {1, 1.2},
         Alignment -> Center]
        , 12];
     
     Grid[{
       {
        h1
        },
       {
        Graphics[{
          {AbsoluteThickness[k1/250], 
           Line@makeSpring[0, r, x1 - r, r, r/2]},
          {EdgeForm[Black], Opacity[m1/10], Red, Disk[{x1, r}, r]},
          {Black, 
           Line[{{x1, r}, {x1 + r Sin[\[Theta]1sol], 
              r + r Cos[\[Theta]1sol]}}]},
          {AbsoluteThickness[k2/250], 
           Line@makeSpring[x1 + r, r, x2 - r, r, r/2]},
          {EdgeForm[Black], Opacity[m2/10], Red, Disk[{x2, r}, r]},
          {Black, 
           Line[{{x2, r}, {x2 + r Sin[\[Theta]2sol], 
              r + r Cos[\[Theta]2sol]}}]},
          {AbsoluteThickness[k3/250], 
           Line@makeSpring[x2 + r, r, 3 springRelaxedL, r, r/2]}
          },
         PlotRange -> {{0, 3 springRelaxedL}, {-0.5 r, 3 r}},
         ImageSize -> 400,
         Axes -> True,
         Frame -> True,
         AxesOrigin -> {0, 0},
         AspectRatio -> Automatic,
         GridLines -> 
          If[showGrid, {Range[0, 3 springRelaxedL, .5], Automatic}, 
           None],
         GridLinesStyle -> LightGray
         ]
        }
       }, Alignment -> Center, Spacings -> {.1, .2}
      ]
     ];
   (*--------------------------------------------*)
   makeSpring[xFirst_?numeric, yFirst_?numeric, xEnd_?numeric, 
     yEnd_?numeric, szel_?numeric] := 
    Module[{hx, veghossz, hossz, hy, dh, tbl},
     hx = xEnd - xFirst;
     If[Abs[hx] <= $MachineEpsilon, hx = 10^-6];
     hy = yEnd - yFirst;
     If[Abs[hy] <= $MachineEpsilon, hy = 10^-6];
     
     veghossz = 0.03;
     hossz = Sqrt[hx^2 + hy^2];
     dh = (hossz - 2*veghossz)/20;
     tbl = 
      Table[If[
        OddQ[i], {xFirst + hx*(i*dh + veghossz)/hossz + hy*szel/hossz,
          yFirst + hy*(i*dh + veghossz)/hossz - 
          hx*szel/hossz}, {xFirst + hx*(i*dh + veghossz)/hossz - 
          hy*szel/hossz, 
         yFirst + hy*(i*dh + veghossz)/hossz + hx*szel/hossz}], {i, 2,
         18}];
     {{xFirst, yFirst}}~
      Join~{{xFirst + hx*(dh + veghossz)/hossz, 
        yFirst + hy*(dh + veghossz)/hossz}}~Join~tbl~
      Join~{{xFirst + hx*(19*dh + veghossz)/hossz, 
        yFirst + hy*(19*dh + veghossz)/hossz}}~Join~{{xEnd, yEnd}}
     ];
   
   }
 ]