(*by Nasser M. Abbasi, version: 8/8/2012*)
Manipulate[
gTick;
Module[{g1, wasHit = False, r0 = 0.2(*bob radius, fixed*),
L0 = R0/2.0(*relaxed length of the spring*)},
If[setIC,
setIC = False;
If[initialBobX > R0, initialBobX = R0];
simulationTime = 0;
list@setIC[{initialBobX, initialBobSpeed, initialTheta,
initialThetaDot, 2 m0 initialBobSpeed initialThetaDot}];
isRelaxedSpring =
If[Abs[initialBobX - R0/2] <= $MachineEpsilon, True, False]
];
If[runningState == "RUNNING" || runningState == "STEP",
wasHit = solver@step[m0, R0, L0, k, M0, delT, wallType];
(*this logic below so that we do not animate a hit on the edge \
unless last time it was no hit*)
If[wasHit,
If[wasHitLastTime == True,
wasHit = False,
wasHitLastTime = True
]
,
wasHitLastTime = False
];
simulationTime = Mod[simulationTime + delT, 1000];
If[runningState == "STEP", runningState = "STOP", gTick += del]
];
(*all done, display the animation on the screen*)
g1 = display@
makeDisplay[simulationTime, plotType, m0, M0, R0, r0, wasHit, k,
showPlots, showCounters, showCoriolisForce, trace];
FinishDynamic[];
g1
],
(*---------- control layout ------------*)
Grid[{
{Grid[{{
Button[
Text[Style["run", 12]], {If[
Not[plotType == "velocity/acceleration"],
runningState = "RUNNING"]; gTick += del},
ImageSize -> {55, 35}],
Button[
Text[Style["stop", 12]], {If[
Not[plotType == "velocity/acceleration"],
runningState = "STOP"]; gTick += del}, ImageSize -> {55, 35}]
},
{
Button[
Text[Style["step", 12]], {If[
Not[plotType == "velocity/acceleration"],
runningState = "STEP"]; gTick += del},
ImageSize -> {55, 35}],
Button[
Text[Style["reset",
12]],(*bring simulation back to initial conditions*)
\
{
setIC = True;
runningState = "STOP";
gTick += del
}, ImageSize -> {55, 35}]
}}, Spacings -> {0.5, .2}
]},
{Text@Style["simulation parameters", 12]},
{Grid[
{
{"simulation speed",
Manipulator[Dynamic[delT, {delT = #} &], {0.01, 5, 0.01},
ImageSize -> Tiny, ContinuousAction -> False],
Text@Style[Dynamic@padIt2[delT, {3, 2}], 11]
},
{"disk mass",
Manipulator[Dynamic[M0,
{M0 = #;
setIC = True;
gTick += del
} &], {1, 500, 1}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[M0, 3], 11]
},
{"disk radius",
Manipulator[Dynamic[R0,
{R0 = #;
setIC = True;
gTick += del
} &], {1, 4, 0.1}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[R0, {2, 1}], 11]
},
{"bob mass",
Manipulator[Dynamic[m0,
{m0 = #;
setIC = True;
gTick += del
} &], {0, 99, 0.1}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[m0, {3, 1}], 11]
},
{"spring stiffness",
Manipulator[Dynamic[k,
{k = #;
setIC = True;
gTick += del
} &], {0.1, 9, .1}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[k, {2, 1}], 11]
},
{Grid[{{"disk edge",
RadioButtonBar[Dynamic[wallType,
{wallType = #;
setIC = True;
gTick += del
} &], {"elastic" -> "elastic",
"inelastic" -> "inelastic"}]
}}], SpanFromLeft
}
}, Spacings -> {.6, .5}, Alignment -> Left, Frame -> True,
FrameStyle -> Directive[Thickness[.005], Gray]
]
},
{Text@Style["initial conditions", 12]},
{Grid[{
{"angular velocity",
Manipulator[Dynamic[initialThetaDot,
{initialThetaDot = #;
setIC = True;
gTick += del
} &], {-0.1, 0.1, .01}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt1[initialThetaDot, {2, 2}], 11]
},
{"angle (degree)",
Manipulator[Dynamic[initialTheta,
{initialTheta = #;
setIC = True;
gTick += del
} &], {0, 2 Pi, 2 Pi/100.}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[initialTheta*180.0/Pi, {4, 1}], 11]
},
{"bob position",
Manipulator[Dynamic[initialBobX,
{initialBobX = #;
setIC = True;
gTick += del
} &], {0, 4, 0.1}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt2[initialBobX, {2, 1}], 11]
},
{
Grid[{{
Row[{"relax", Spacer[2],
Checkbox[Dynamic[isRelaxedSpring,
{isRelaxedSpring = #;
initialBobX = R0/2;
setIC = True;
gTick += del
} &]]}],
Row[{"trace", Spacer[2],
Checkbox[Dynamic[trace,
{trace = #;
If[#, list@clearTrace[]];
gTick += del
} &]]}],
Row[{"show coriolis force", Spacer[2],
Checkbox[Dynamic[showCoriolisForce,
{showCoriolisForce = #;
gTick += del
} &]]}]
}}, Spacings -> {0.4, 0}], SpanFromLeft
},
{"bob speed",
Manipulator[Dynamic[initialBobSpeed,
{initialBobSpeed = #;
setIC = True;
gTick += del
} &], {-0.1, 0.1, 0.01}, ImageSize -> Tiny,
ContinuousAction -> False],
Text@Style[Dynamic@padIt1[initialBobSpeed, {2, 2}], 11]
}
}, Spacings -> {.6, .3}, Alignment -> Left, Frame -> True,
FrameStyle -> Directive[Thickness[.005], Gray]
]
},
{Grid[{
{Text@Style["plot type", 12], Text@Style["test case", 12]},
{
PopupMenu[Dynamic[plotType, {plotType = #;
If[plotType == "velocity/acceleration",
{
If[runningState == "RUNNING",
runningState = "SUSPEND_RUNNING"
]
},
{
If[runningState == "SUSPEND_RUNNING",
runningState = "RUNNING"]
}
]; gTick += del} &],
{
"disk angular velocity" ->
Text@Style["disk angular velocity", 12],
"disk angle" -> Text@Style["disk angle", 12],
"bob position" -> Text@Style["bob position", 12],
"bob velocity" -> Text@Style["bob velocity", 12],
"Coriolis force" -> Text@Style["Coriolis force", 12]
}, ImageSize -> All, ContinuousAction -> False,
Enabled -> Dynamic[showPlots]]
,
PopupMenu[Dynamic[testCase, {testCase = #;
runningState = "STOP";
Which[testCase == 1,
(
isRelaxedSpring = False; delT = 1; m0 = 40; k = 1;
R0 = 3.9;
initialThetaDot = 0.09; initialTheta = 206 Degree;
initialBobX = 0.5; initialBobSpeed = 0; M0 = 10;
trace = True;
setIC = True;
runningState = "STOP";
plotType = "bob position"
),
testCase == 2,
(
isRelaxedSpring = False; delT = 5; m0 = 16; k = 3; R0 = 2;
initialThetaDot = 0.01; initialTheta = 45 Degree;
initialBobX = 1.4; initialBobSpeed = 0; M0 = 100;
trace = True;
setIC = True;
runningState = "STOP";
plotType = "disk angular velocity"
),
testCase == 3,
(
isRelaxedSpring = True; delT = 5; m0 = 50; k = 0.5;
M0 = 100; R0 = 3; trace = False;
initialThetaDot = 0; initialTheta = 270 Degree;
initialBobX = 1.5; initialBobSpeed = 0.1;
setIC = True;
runningState = "STOP";
plotType = "disk angular velocity"
)
];
gTick += del} &],
{
1 -> Text@Style["1", 12], 2 -> Text@Style["2", 12],
3 -> Text@Style["3", 12]
}, ImageSize -> All, ContinuousAction -> False]
},
{Grid[{
{
Row[{"show plot ", Spacer[4],
Checkbox[
Dynamic[showPlots, {showPlots = #; gTick += del} &]]}],
Spacer[12],
Row[{"show counters ", Spacer[4],
Checkbox[
Dynamic[
showCounters, {showCounters = #; gTick += del} &]]}],
SpanFromLeft
}
}
], SpanFromLeft
},
{Grid[{
{"plot x-scale",
Manipulator[Dynamic[xScale,
{xScale = #;
list@setSize[xScale];
setIC = True;
gTick += del
} &], {10, 1000, 1}, ImageSize -> Tiny,
ContinuousAction -> False, Enabled -> Dynamic[showPlots]],
Text@Style[Dynamic@padIt2[xScale, 4], 11]
}
}], SpanFromLeft
}
}, Frame -> True,
FrameStyle -> Directive[Thickness[.005], Gray]
]
}
}, Spacings -> {0, {2 -> 1, 4 -> 1, 6 -> 0.5, 8 -> 0}},
Alignment -> Center, Frame -> None],
(*----control variables--*)
{{m0, 40}, None},
{{M0, 10}, None},
{{R0, 3.9}, None},
{{delT, 1}, None},
{{k, 1}, None},
{{initialThetaDot, 0.09}, None},
{{initialTheta, 45 Degree}, None},
{{initialBobX, 1.5}, None},
{{initialBobSpeed, 0}, None},
{{isRelaxedSpring, False}, None},
{{plotType, "bob position"}, None},
{{testCase, 1}, None},
{{wallType, "elastic"}, None},
{{showPlots, False}, None},
{{showCounters, True}, None},
{{xScale, 400}, None},
{{showCoriolisForce, False}, None},
{{trace, True}, None},
{{setIC, False}, None},
(*----- refresh control ---*)
{{gTick, 0}, ControlType -> None},
{{del, $MachineEpsilon}, None},
(*----- state variables for sim---*)
{{runningState, "STOP"},
None},(*"RUNNING","STEP","SUSPEND","STOP"*)
{{simulationTime, 0},
None},
{{wasHitLastTime, False}, None},
TrackedSymbols :> {gTick},
ControlPlacement -> Left,
SynchronousUpdating -> False,
SynchronousInitialization -> True,
ContinuousAction -> False,
Alignment -> Center,
ImageMargins -> 0,
FrameMargins -> 0,
Paneled -> True,
Frame -> False,
Initialization :>
{
(*definitions used for parameter checking*)
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] &);
(* This list object is used to store and the manage the time \
series generated during running of the simulation so that display \
object can use it to make plots and the animation *)
listClass[$size_?integer(*maximum size of the list*)] :=
Module[{size, lists, self},
(*lists are in this order x,v,\[Theta],\[Omega],force,
trace*)
self@getSize[] := size;
self@setSize[n_] := ( size = n;
lists = Table[{0, Table[0, {n}]}, {6}] );
self@
add[{x_?numeric,(*bob position*)
v_?numeric,(*bob speed*)
\[Theta]_?
numeric,(*disk angle*)
\[Omega]_?
numeric,(*disk angular speed*)
force_?numeric(*
coriolis force*)}
] := Module[{},
MapThread[Function[{e, idx},
lists[[idx, 1]]++;
If[lists[[idx, 1]] > size, lists[[idx, 1]] = 1];
lists[[ idx, 2, lists[[idx, 1]] ]] = e
],
{{x, v, \[Theta], \[Omega],
force, {x*Cos[\[Theta]], x*Sin[\[Theta]]}},
Range[1, Length[lists]]}
]
];
self@
setIC[{x_?numeric,
v_?numeric, \[Theta]_?numeric, \[Omega]_?numeric,
force_?numeric}] := (
list@clear[];
list@add[{x, v, \[Theta], \[Omega], force}]
);
self@getCurrent[] :=
lists[[ #, 2, lists[[#, 1]] ]] & /@ Range[1, Length[lists]];
self@clear[] := (lists[[#, 1]] = 0) & /@
Range[1, Length[lists]];
self@clearTrace[] := lists[[6, 1]] = 0;
self@getPositionList[] :=
Module[{len = lists[[1, 1]]}, lists[[ 1, 2, 1 ;; len]] ] ;
self@getSpeedList[] :=
Module[{len = lists[[2, 1]]}, lists[[ 2, 2, 1 ;; len]] ] ;
self@getThetaList[] :=
Module[{len = lists[[3, 1]]}, lists[[ 3, 2, 1 ;; len]] ] ;
self@getOmegaList[] :=
Module[{len = lists[[4, 1]]}, lists[[ 4, 2, 1 ;; len]] ] ;
self@getCoriolisForceList[] :=
Module[{len = lists[[5, 1]]}, lists[[ 5, 2, 1 ;; len]] ] ;
self@getTraceData[] :=
Module[{len = lists[[6, 1]]}, lists[[ 6, 2, 1 ;; len]] ] ;
(*--- constructor---*)
self@setSize[$size];
self
];
(*-----------------------------------------------------------*)
solverClass[] :=
Module[{self},
(* uses NDSolve to integrate equations of motion for given time \
step*)
self@step[m0_?numericPositive,(*bob mass*)
R0_?numericStrictPositive,(*disk radius*)
L0_?numericStrictPositive,(*relaxed spring length,
measured from the origin*)
k_?numericStrictPositive,(*spring k*)
M0_?numericStrictPositive,(*disk mass*)
delT_?numericStrictPositive,(*time length to integrate over \
for NDSolve*)
wallType_String(*
wall type is either elastic or inelastic*)
] :=
Module[{ic, eq1, eq2, t, x, \[Theta], maxDistance = R0,
minDistance = 0, currentSolution, currentX, currentV,
current\[Theta], currentOmega,
wasHit =
False, $currentX, $currentV, $current\[Theta], \
$currentOmega, $force, trace},
{$currentX, $currentV, $current\[Theta], $currentOmega, $force,
trace} = list@getCurrent[];
currentX = $currentX;
currentV = $currentV;
If[ Abs[m0] <= $MachineEpsilon,
currentSolution =
First@NDSolve[{\[Theta]''[t] == 0, \[Theta][0] ==
Mod[$current\[Theta], 2 Pi], \[Theta]'[
0] == $currentOmega}, {\[Theta], \[Theta]'}, {t, 0,
delT}, MaxSteps -> Infinity];
current\[Theta] = (\[Theta] /. currentSolution)[delT];
currentOmega = (\[Theta]' /. currentSolution)[delT]
,
eq1 = (x^\[Prime]\[Prime])[t] == (-k (x[t] - L0))/m0 +
x[t] \[Theta]'[t]^2;
eq2 = \[Theta]''[t] == (-4 m0 x[t] x'[t] \[Theta]'[t])/(
M0 R0^2 + 2 m0 x[t]^2);
ic = {x[0] == $currentX,
x'[0] == $currentV, \[Theta][0] ==
Mod[$current\[Theta], 2 Pi], \[Theta]'[0] == $currentOmega};
currentSolution =
First@Quiet@
NDSolve[
Flatten@{eq1, eq2, ic}, {x, x', \[Theta], \[Theta]'}, {t,
0, delT}, MaxSteps -> Infinity];
currentX = (x /. currentSolution)[delT];
currentV = (x' /. currentSolution)[delT];
current\[Theta] = (\[Theta] /. currentSolution)[delT];
currentOmega = (\[Theta]' /. currentSolution)[delT];
(*
if bob hits the edge of the disk or the base of the spring,
fix speed and reset things*)
If[currentX > maxDistance || currentX < minDistance,
currentV = 0;
If[wallType == "elastic",
If[currentX > maxDistance, wasHit = True];
currentV = -$currentV
];
currentX = $currentX;
current\[Theta] = $current\[Theta];
currentOmega = $currentOmega
]
];
(*save current solution in the list object so that display can \
use it*)
list@add[{currentX, currentV, current\[Theta], currentOmega,
2 m0 currentOmega currentV}];
wasHit
];
self
];
(*--------- displayClass ---------------------------------------*)
displayClass[] :=
Module[{makeCounters, makeDiskDiagram, makePlot, self},
(*--------- private ---------------------------------------*)
makeCounters[simulationTime_?numericPositive,
m0_?numericPositive,
M0_?numericStrictPositive,
R0_?numericStrictPositive,
k_?numericStrictPositive] :=
Module[{h1, h2, currentMomentOfInertia, x,
v, \[Theta], \[Omega], currentCoriolisForce, PE, KE, trace},
{x, v, \[Theta], \[Omega], currentCoriolisForce, trace} =
list@getCurrent[];
currentMomentOfInertia = M0/2*R0^2 + m0*x^2;
PE = 0.5*k*(x - R0/2)^2;
KE = 1/4 M0 R0^2 \[Omega]^2 + 1/2 m0 (v^2 + x^2 \[Omega]^2);
h1 = Text@Style[Grid[{
{Text["disk \[Theta]"],
Text["disk \[Omega]"],
Text["bob position"],
Text["bob velocity"],
Text[Style["\[CapitalIota]", Italic]],
Text["energy"]
},
{Text["(degree)"],
Text["(rad/sec)"],
Text["(meter)"],
Text["(meter/sec)"],
Text["(kg \!\(\*SuperscriptBox[\(meter\), \(2\)]\))"],
Text[Row[{"(", Style["J", Italic], ")"}]]
},
{ padIt2[180./Pi*\[Theta], {5, 2}],
padIt2[\[Omega], {7, 6}],
padIt2[x, {3, 2}],
padIt1[v, {6, 3}],
padIt2[currentMomentOfInertia, {5, 2}],
padIt2[PE + KE, {4, 3}]
}
},
Frame -> {All,
None, { {{1, 2}, {1, 6}} -> True , {{3, 3}, {1, 6}} ->
True}},
FrameStyle -> Gray,
Spacings -> 1,
ItemSize -> {{All, 2 ;; -1} -> 5},
Alignment -> Center], 12];
h2 = Text@Style[Grid[{
{Text["time (sec)"],
Text["\[CapitalIota]\[InvisibleSpace] \[InvisibleSpace]\
\[Omega] (joule second)"],
Text@Row[{"Coriolis force (", Style["N", Italic], ")"}],
Text@Row[{"P.E. (", Style["J", Italic], ")"}],
Text@Row[{"K.E. (", Style["J", Italic], ")"}]
},
{ padIt2[simulationTime, {5, 2}],
padIt2[currentMomentOfInertia*\[Omega], {6, 4}],
padIt1[currentCoriolisForce, {5, 4}],
padIt2[PE, {5, 4}],
padIt2[KE, {5, 4}]
}},
Frame -> All,
FrameStyle -> Gray,
Spacings -> 1,
ItemSize -> {{All, 2 ;; -1} -> 6},
Alignment -> Center], 12];
Grid[{{h1}, {h2}}, Spacings -> {0, .1}]
];
(*---------------private----------------------------------*)
makeDiskDiagram[m0_?numericPositive,
R0_?numericStrictPositive,
r_?numericStrictPositive,
wasHit_?bool,
{w_?numericStrictPositive, h_?numericStrictPositive},
showCoriolisForce_?bool,
trace_?bool] :=
Module[{x, y, splash, xx, v, \[Theta], \[Omega], force,
traceData, currentTrace},
{xx, v, \[Theta], \[Omega], force, currentTrace} =
list@getCurrent[];
force = force/(4*1.25) + 0.25*Sign[force];
x = xx*Cos[\[Theta]];
y = xx*Sin[\[Theta]];
traceData = list@getTraceData[];
splash = If[wasHit, {
{ Dotted, Red,
Rotate[Line[{{R0, 0}, {1.2 R0, 0}}], \[Theta], {0, 0}]},
{Dotted, Red,
Rotate[Line[{{R0, 0}, {1.2 R0, .2 R0}}], \[Theta], {0, 0}]},
{Dotted, Red,
Rotate[Line[{{R0, 0}, {1.2 R0, .1 R0}}], \[Theta], {0, 0}]},
{Dotted, Red,
Rotate[Line[{{R0, 0}, {1.2 R0, -.2 R0}}], \[Theta], {0,
0}]},
{Dotted, Red,
Rotate[Line[{{R0, 0}, {1.2 R0, -.1 R0}}], \[Theta], {0, 0}]}
},
Sequence @@ {}
];
Graphics[{
{EdgeForm[{Thick, Blue}], FaceForm@RGBColor[.75, .97, .97],
Disk[{0, 0}, R0 ]},
If[showCoriolisForce && Abs[force] > $MachineEpsilon,
{Dotted, Black,
Rotate[Arrow[{{xx,
Sign[force]*
r}, {xx, (force + Sign[force]*r)}}], \[Theta], {0,
0}]}, Sequence @@ {}
],
If[trace, {Dotted, Darker@Red, Line[traceData]},
Sequence @@ {}],
If[m0 <= $MachineEpsilon,
Sequence @@ {}, { Red, Disk[{x, y}, r]}],
{Black,
Line@makeSpring[0,
0, (xx - r) Cos[\[Theta]], (xx - r) Sin[\[Theta]], 0.8*r]},
(*relaxed position indicator*)
{Dashed, Gray,
Rotate[Line[{{R0/2, -r}, {R0/2, -2 r}}], \[Theta], {0,
0}]},
{Dashed, Gray,
Rotate[Line[{{R0/2, r}, {R0/2, 2 r}}], \[Theta], {0, 0}]},
(*
inertial frames*)
{Gray, Dashed,
Rotate[Line[{{-R0, 0}, {0, 0}}], \[Theta], {0, 0}]},
{Gray, Dashed,
Rotate[Line[{{0, -R0}, {0, R0}}], \[Theta], {0, 0}]},
splash
},
ImageSize -> {w, h},
ImagePadding -> {{10, 10}, {10, 10}},
PlotRange -> {{-R0 - r, R0 + r}, {-R0 - r, R0 + r}},
ImageMargins -> 1,
AspectRatio -> 1
]
];
(*-------------------- private -----------------------------*)
makePlot[plotType_String,
R0_?numericStrictPositive] :=
Module[{plotTitle, data, n = list@getSize[]},
Which[plotType == "disk angular velocity",
data = list@getOmegaList[];
If[Length[data] == 0, data = {0}];
plotTitle = {{Text@Style["\[Omega] (rad/sec)", 12],
None}, {Text@Style["time"],
Text@Style["disk angular velocity vs. time", 12]}};
plotRange = {{1, n}, All}
,
plotType == "disk angle",
data = 180.0/Pi*list@getThetaList[];
If[Length[data] == 0, data = {0}];
plotTitle = {{Text@Style["\[Theta] (deg)", 12],
None}, {Text@Style["time"],
Text@Style["disk angle vs. time", 12]}};
plotRange = {{1, n}, {0, 360}}
,
plotType == "bob position",
data = list@getPositionList[];
If[Length[data] == 0, data = {0}];
plotTitle = {{Text@
Style[Row[{"position (", Style["m", Italic], ")"}], 12],
None}, {Text@Style["time"],
Text@Style["bob position vs. time", 12]}};
plotRange = {{1, n}, {0, R0}}
,
plotType == "bob velocity",
data = list@getSpeedList[];
If[Length[data] == 0, data = {0}];
plotTitle = {{Text@
Style[Row[{"velocity (", Style["m/s", Italic], ")"}], 12],
None}, {Text@Style["time"],
Text@Style["bob velocity vs. time", 12]}};
plotRange = {{1, n}, All}
,
plotType == "Coriolis force",
data = list@getCoriolisForceList[];
If[Length[data] == 0, data = {0}];
plotTitle = {{Text@
Style[Row[{"Coriolis force (", Style["N", Italic], ")"}],
12], None}, {Text@Style["time"],
Text@Style["Coriolis force vs. time", 12]}};
plotRange = {{1, n}, All}
];
ListPlot[ data,
PlotRange -> plotRange,
AxesOrigin -> {0, 0},
Joined -> True,
Frame -> True,
GridLines -> Automatic,
ImageSize -> {330, 160},
ImagePadding -> {{60, 10}, {30, 25}},
ImageMargins -> {{2, 1}, {1, 1}},
Axes -> False,
FrameLabel -> plotTitle,
PlotStyle -> Red,
AspectRatio -> 0.27]
];
(*------- public ----------------------------------*)
self@makeDisplay[simulationTime_?numericPositive,
plotType_String,
m0_?numericPositive,
M0_?numericStrictPositive,
R0_?numericStrictPositive,
r0_?numericStrictPositive,
wasHit_?bool,
k_?numericStrictPositive,
showPlots_?bool,
showCounters_?bool,
showCoriolisForce_?bool,
trace_?bool] :=
If[showPlots,
If[showCounters,
Grid[{
{makeCounters[simulationTime, m0, M0, R0, k]},
{makePlot[plotType, R0]},
{makeDiskDiagram[m0, R0, r0,
wasHit, {1.4 ContentSizeW, 0.515 ContentSizeH},
showCoriolisForce, trace]}
}, Spacings -> 0]
,
Grid[{
{makePlot[plotType, R0]},
{makeDiskDiagram[m0, R0, r0,
wasHit, {1.4 ContentSizeW, 0.787 ContentSizeH},
showCoriolisForce, trace]}
}, Spacings -> 0]
],
If[showCounters,
Grid[{
{makeCounters[simulationTime, m0, M0, R0, k]},
{makeDiskDiagram[m0, R0, r0,
wasHit, {1.4 ContentSizeW, 0.93 ContentSizeH},
showCoriolisForce, trace]}
}, Spacings -> 0]
,
Grid[{
{makeDiskDiagram[m0, R0, r0,
wasHit, {1.4 ContentSizeW, 1.2 ContentSizeH},
showCoriolisForce, trace]}
}, Spacings -> 0]
]
];
self
];
(*--------------------------------------------*)
(*
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];
(*This function is called to make spring,
based on code by Arpad Kosa from WRI demo*)(*at Wolfram web site \
modified by me.This returns a Line which is the spring*)
(*szel,
larger number means bigger spring width*)
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}}
];
(*--- constant parameters size and width of display ---*)
ContentSizeW = 260;
ContentSizeH = 405;
(* objects used by the simulation.
These must be here in the initialization section *)
list = listClass[400];
list@add[{1.5, 0.0, Pi/4, 0.09, 0.0}];
solver = solverClass[];
display = displayClass[];
}
]