3
$\begingroup$

I have a series of variables that will plot the number of straight segments along a curve, thanks to the help from here on one of my previous questions.

I can create a working Manipulate command from the code in Mathematica by varying nSeg and then visually show the number of segments increasing as the slider is raised, similar to the picture below.

The number of segments (nSeg) can affect the number of x co-ordinates that I have, so if nSeg = 4 then I will have nSeg+1 x co-ordinates in total.

Cable Arches

The difficulty I have is that because I am using subscripted variables for my x co-ordinates, if I try to reset them using the code below or through using Remove[] I invoke dynamic content in my Mathematica file and I'm unable to export as a CDF file that I can embed into a website, although I can get it to execute as a CDF if the user specifically selects to allow dynamic content.

clearSubscript[x_Symbol] := (First /@ Select[DownValues[Subscript],
  MatchQ[First[#],
    Verbatim[HoldPattern][Subscript[x, _]]] &]) /. 
HoldPattern :> Unset;
clearSubscript[x];

I've been hunting around for ways to remove subscripted variables for a few days now, and whilst I've found a few different ways of doing it, I've not managed to work out how this can be done in a way that doesn't invoke Dynamic Content in Mathematica, and without doing this I'm struggling to create a CDF that can be embedded into a webpage.

Any suggestions or help, gratefully received...

EDIT: Removing all subscripts I still get a similar problem when trying to clear variables, edited to include simplified sample code below which I can't make into CDF file for embedding into a web page due to the Dynamic Content which I think is being invoked by the Clear command.

 Manipulate[
 nSeg;
 f[x_] = (50 x)/41 - x^2/3362;
 upVal = 4100;
 chordL = Table[Sqrt[(x[i + 1] - x[i])^2 + (f[x[i + 1]] - f[x[i]])^2], {i, 1, nSeg}];
 combEqs = # == d & /@ chordL;
 Clear[vars, x];
 vars = Append[{x[#], #, x[1] + 10^-6, upVal - 10^-6} & /@ Range[2, nSeg], {d, 1}];
 x[1] = 0;
 x[nSeg + 1] = upVal;
 sol = {FindRoot[combEqs, vars]},
 {nSeg, 3, 8, 1}
 ]

Question updated to reflect the intention is to enable the Manipulate to recreate the graphical images above of the cable-chain arches, whilst I have no problems sharing the full code, I think it would be unfair to throw it all in here, but essentially there is a Plot function that plots the curves once the co-ordinates are calculated via the FindRoot, and the various solutions from the Findroot are also used to plot the links as straight lines. Combined with the proposed Dynamic and TrackedSymbols functions added, the code is something along the lines of:

Dynamic[
Manipulate[nSeg;
f[x_] = (50 x)/41 - x^2/3362;
upVal = 4100;
chordL = Table[Sqrt[(x[i + 1] - x[i])^2 + (f[x[i + 1]] - f[x[i]])^2], {i, 1, nSeg}];
combEqs = # == d & /@ chordL;
vars = Append[{x[#], #, x[1] + 10^-6, upVal - 10^-6} & /@ Range[2, nSeg], {d, 1}];
combEqs = combEqs /. {x[1] -> 0, x[nSeg + 1] -> upVal};
vars = vars /. {x[1] -> 0, x[nSeg + 1] -> upVal};
sol = {FindRoot[combEqs, vars]};
Show[Plot[f[x], {x, 0, 4100}],
Graphics[{Black, Thick,Line[Table[{{x[i], f[x[i]]}, {x[i + 1], f[x[i + 1]]}}, {i, 1, nSeg}] /. sol[[1]]]}],
Graphics[{Black, Dashed,Line[Table[{{x[i], f[x[i]]}, {x[i + 2], f[x[i + 2]]}}, {i, 1, nSeg - 1}] /. sol[[1]]]}],
Graphics[{Red, PointSize[Large],Point[Table[{x[i], f[x[i]]}, {i, 1, nSeg + 1}] /. sol[[1]]]}],
AspectRatio -> Automatic,
Axes -> False],
{nSeg, 3, 8, 1},
TrackedSymbols :> {nSeg}]]
$\endgroup$
2
  • $\begingroup$ I presume you have read this. If that doesn't work, I recommend replacing your subscripted variables with x[5] type DownValues. $\endgroup$
    – Mr.Wizard
    Aug 17, 2012 at 16:21
  • $\begingroup$ Thanks for the link, I've already been through that thread and the problem seems to be clearing variables within the Manipulate command. I've been through and simplified my code removing the subscripts and I still get the same problem unfortunately so perhaps it's not just limited to subscripted variables but clearing variables generally... $\endgroup$ Aug 17, 2012 at 17:01

2 Answers 2

3
$\begingroup$

Here is a version which uses Mr.Wizards way to avoid the need to explicitly set any downvalues of x and uses a Dynamic wrapper around the body of the Manipulate to avoid unnecessary updates which seem to be triggered by FindRoot (and maybe also Plot) otherwise.

Manipulate[
 Dynamic[
  nSeg;
  f[x_] = (50 x)/41 - x^2/3362;
  upVal = 4100;
  chordL = 
   Table[Sqrt[(x[i + 1] - x[i])^2 + (f[x[i + 1]] - f[x[i]])^2], {i, 1,
      nSeg}];
  combEqs = # == d & /@ chordL;
  vars = Append[{x[#], #, x[1] + 10^-6, upVal - 10^-6} & /@ 
     Range[2, nSeg], {d, 1}];
  combEqs = combEqs /. {x[1] -> 0, x[nSeg + 1] -> upVal};
  vars = vars /. {x[1] -> 0, x[nSeg + 1] -> upVal};
  sol = {FindRoot[combEqs, vars]};
  Plot[f[x], {x, 0, 4100}, PlotLabel -> Column @@ sol],
  TrackedSymbols :> {nSeg}
  ]
 , {nSeg, 3, 8, 1}]

Note that I have removed the Show which was unnecessary here and added a PlotLabel so you can see that the FindRoot is actually run for the given value of nSeg. As Ajasja mentioned, the Dynamic wrapper is not necessary, as Manipulate will understand the TrackedSymbols option directly, so the following will work as well:

Manipulate[
 nSeg;
 f[x_] = (50 x)/41 - x^2/3362;
 upVal = 4100;
 chordL = 
  Table[Sqrt[(x[i + 1] - x[i])^2 + (f[x[i + 1]] - f[x[i]])^2], {i, 1, 
    nSeg}];
 combEqs = # == d & /@ chordL;
 vars = Append[{x[#], #, x[1] + 10^-6, upVal - 10^-6} & /@ 
    Range[2, nSeg], {d, 1}];
 combEqs = combEqs /. {x[1] -> 0, x[nSeg + 1] -> upVal};
 vars = vars /. {x[1] -> 0, x[nSeg + 1] -> upVal};
 sol = {FindRoot[combEqs, vars]};
 Plot[f[x], {x, 0, 4100}, PlotLabel -> Column @@ sol],
 {nSeg, 3, 8, 1},
 TrackedSymbols :> {nSeg}
 ]
$\endgroup$
3
  • $\begingroup$ That's really useful, I think I'm going to have to go and read up a lot more on the use of Dynamic if I'm to make the most of the Manipulate routines. How complex would it be to add the Show command back in to introduce a straight line which connects through the solutions of the FindRoot? I've tried to do this myself by prefixing the Plot line with Show[ and then add a Graphics line to cycle through the points before TrackedSymbols, but it gives errors so I'm assuming my syntax must be off, or it needs special treatment with the Dynamic wrapper? $\endgroup$ Aug 17, 2012 at 22:47
  • 1
    $\begingroup$ I don't think you need a separate Dynamic blocks, since Manipulate accepts the TrackedSymbols Option as well. $\endgroup$
    – Ajasja
    Aug 20, 2012 at 12:25
  • $\begingroup$ @Ajasja: good point, I'll add it to the answer... $\endgroup$ Aug 21, 2012 at 13:04
2
$\begingroup$

I am not familiar with the requirements of .CDF export but if Clear is the problem perhaps you can use a variation that does not require it. Here with ReplaceAll:

Manipulate[nSeg;
 f[x_] = (50 x)/41 - x^2/3362;
 upVal = 4100;
 chordL = Table[Sqrt[(x[i + 1] - x[i])^2 + (f[x[i + 1]] - f[x[i]])^2], {i, 1, nSeg}];
 combEqs = # == d & /@ chordL;
 vars = Append[{x[#], #, x[1] + 10^-6, upVal - 10^-6} & /@ Range[2, nSeg], {d, 1}];
 combEqs = combEqs /. {x[1] -> 0, x[nSeg + 1] -> upVal};
 vars = vars /. {x[1] -> 0, x[nSeg + 1] -> upVal};
 sol = {FindRoot[combEqs, vars]},
 {nSeg, 3, 8, 1}
]
$\endgroup$
5
  • $\begingroup$ That's an interesting way of getting round the Clear function, and it works well for the symbolic aspect, but if you were to add a Plot function near the end so that it was to draw the graph of the curve, as you increment the nSeg value the graphing element crashes, where if you Remove or Clear the x variable this doesn't happen, but I can't understand why. I added this line just above the nSeg call for the manipulate. Show[Plot[f[x], {x, x[1], x[nSeg + 1]}]], $\endgroup$ Aug 17, 2012 at 21:18
  • $\begingroup$ @Mr.Wizard: have you noticed that this Manipulate will keep on updating? Or is that only happening to me? I suspect it is because FindRoot "effectively uses Block to localize variables" and that's why the Manipulate sees all the internal changes of (the downvalues of) x within FindRoot and keeps updating. I found Block-like scoping a major source of problems in any dynamic code which I think WRI should address. A workaround for this particular case is a wrapper Dynamic[...,TrackedSymbols:>{nSeg}] around the whole Manipulate body... $\endgroup$ Aug 17, 2012 at 21:19
  • $\begingroup$ @ASBOAllstar: your Plot can't work as Mr.Wizards code does never set any of the x[i], and that's by purpose. You need to replace those plot limits with their values, e.g. with something like: Plot[f[x], Evaluate@{x, x[1] /. sol, upVal}] (note that Plot has attribute HoldAll so you'll need some effort to make the limits evaluate). $\endgroup$ Aug 17, 2012 at 21:26
  • $\begingroup$ @AlbertRetey thanks for the comment, even with fixed variables or having the variables defined the graph crashes as soon as the nSeg slider is incremented, which is strange as nothing for the plot range of f[x] is updated. $\endgroup$ Aug 17, 2012 at 21:29
  • $\begingroup$ @ASBOAllstar: sorry, I forgot that you will additionally need the Dynamic wrapper I mentioned to suppress the neverending evaluation. Can you show what you are running? Maybe you want to edit your question and add the line that crashes... $\endgroup$ Aug 17, 2012 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.