Anonymous
2012-03-09
I've been comparing the 'plot' command with direct calls to gnuplot. The following lines generate a plot of radial, hoop and max shear stress in a compound cylinder:
operator SIGR; let {SIGR(~r) => E1/(1-nu1)*(c1*(1+nu1)-c2*((1-nu1)/r^2)) when numberp r and r<c, SIGR(~r) => E2/(1-nu2)*(c3*(1+nu2)-c4*((1-nu2)/r^2)) when numberp r and r>c}; operator SIGH; let {SIGH(~r) => E1/(1-nu1)*(c1*(1+nu1)+c2*((1-nu1)/r^2)) when numberp r and r<c, SIGH(~r) => E2/(1-nu2)*(c3*(1+nu2)+c4*((1-nu2)/r^2)) when numberp r and r>c}; operator TAUMAX; let TAUMAX(~r) => (max(SIGR(r),SIGH(r))-min(SIGR(r),SIGH(r)))/2 when numberp r; load_package gnuplot$ plotreset; % reset the plot subsystem; gnuplot(set,key); plot(SIGR(x),SIGH(x),TAUMAX(x),x=(a .. b),title="plot_title",output="plot_2");
c1 through c4 are coefficients from solving a system of eqns; a = inner radius, b = outer radius and c = contact radius.
I have not found a way to show a key (legend) with the plot command. Direct calls to gnuplot produce a key, but I don't understand how to pass my operators in reduce to gnuplot. I consulted the "Gnuplot Interface for REDUCE Version 4" document by Herbert Melenk, but that did not shed any light on this. Is it possible to produce a key usin 'plot' or pass operators directly?
Rainer Schöpf
2012-03-12
I'm afraid that the current implementation of the gnuplot interface doesn't display keys. In fact, it sends the command
unset key
immediately before each plot command. (You can see the commands being sent to gnuplot by saying
on trplot;
before giving the plot command.)
Of course, in principle it should be possible to add a title-spec to each plot, but this means (a) enhancing the code that generates the actual gnuplot commands, and (b) defining an input syntax for the keys.
If we could just omit the
unset key
command, or allow adding arbitray
set key
commands, would that help you?
Anonymous
2012-03-14
There is an indirect way to achieve what I want. The basic idea is to generate a file with the points to plot. The following illustrates this scheme using the same operators (by the way, I found that the operator commands before 'let' statements were not necessary):
let {SIGR(~r) => SIGR1(r) when numberp r and r<c, SIGR(~r) => SIGR2(r) when numberp r and r>c}$ let {SIGH(~r) => SIGH1(r) when numberp r and r<c, SIGH(~r) => SIGH2(r) when numberp r and r>c}$ let {TAUMAX(~r) => (max(SIGR(r),SIGH(r))-min(SIGR(r),SIGH(r)))/2 when numberp r}$ on fort$ on rounded$ out "SIGR"$ s:={"-"," "," "}$ for x:= a step (b-a)/500 until b do write part(s,sign(x)+2),abs(x),", ", part(s,sign(y:=SIGR(x))+2),abs(y)$ shut "SIGR"$ out "SIGH"$ s:={"-"," "," "}$ for x:= a step (b-a)/500 until b do write part(s,sign(x)+2),abs(x),", ", part(s,sign(y:=SIGH(x))+2),abs(y)$ shut "SIGH"$ out "TAUMAX"$ s:={"-"," "," "}$ for x:= a step (b-a)/500 until b do write part(s,sign(x)+2),abs(x),", ", part(s,sign(y:=TAUMAX(x))+2),abs(y)$ shut "TAUMAX"$ off fort$ load_package gnuplot$ plotreset$ gnuplot(plot,"""SIGR""","with lines",",","""SIGH""","with lines",",","""TAUMAX""","with lines"); plotshow$
I then tried to implement the above as a general purpose procedure that would take a list of functions (i.e. operators such as SIGR, SIGH, etc.), etc. as arguments and create the data files:
procedure plotdata(lis)$ begin on fort$ on rounded$ foreach k in lis do$ out part(lis,k)$ s:={"-"," "," "}$ for x:= a step (b-a)/500 until b do write part(s,sign(x)+2),abs(x),", ", part(s,sign(y:=part(lis,k)(x))+2),abs(y)$ shut part(lis,k)$ off fort$ end$
This did not work, and I'm not entirely sure this can be done. Can you help me?
Anonymous
2012-03-15
I finally got the procedure to work. Unfortunately, it's static, i.e. won't handle an arbitrary operation. Is there a way to pass pointers to operators? I imagine it would involve delving deeper into the workings of REDUCE.
load_package assist$ procedure write_data(lis)$ begin on fort$ on rounded$ foreach i in lis do << out i$ s:={"-"," "," "}$ for x:= a step (b-a)/500 until b do write part(s,sign(x)+2),abs(x),", ", part(s,sign((if position(i,lis)=1 then y:=SIGR(x) else if position(i,lis)=2 then y:=SIGH(x) else if position(i,lis)=3 then y:=SIGE(x) else if position(i,lis)=4 then y:=TAUMAX(x) else y:=DISPR(x)))+2),abs(y)$ shut i$ >>$ off fort$ end$
Rainer Schöpf
2012-03-18
You can set the operator of an expression by putting a PART operator on the left had side of an assignment, eg. with
y := {x}; z := (part(y,0) := tan);
z is equivalent to tan(x).
I notice you haven't answered the question in my previous post: would such a change help you?
Rainer
Anonymous
2012-03-19
Not having a key (esp. when plotting more than 1 curve) in my opinion limits the usefulness of the plot , so yes, having at least the default key would be helpful. But for those times when the key isn't necessary (plotting a single curve) or desireable, it would be better if one could toggle the key.
Anonymous
2012-03-19
I'm trying to output a comma delimited table of values, using operator in list for each column. I tried this
lis:={SIGR,SIGH,SIGE,TAUMAX,EPSR,EPSH,EPSZ,GAMMAX,DISPR}$ on fort$ out "COMCYL.DAT"$ s:={"-"," "," "}$ for x := a step (b-a)/201 until b do << write part(s,sign(x)+2),abs(x) foreach i in lis do << y := {x}; z := (part(y,0) := i; write ", ", part(s,sign(z))+2),abs(z)>>; >>$ shut "COMCYL.DAT"$ off fort$
but returned error. What am I doing wrong?
Anonymous
2012-03-19
This does what I want, but can the write statement be looped?
print_precision 6$ lis:={SIGR,SIGH,SIGE,TAUMAX,EPSR,EPSH,EPSZ,GAMMAX,DISPR}$ on fort$ on fortupper$ fort_width := 144$ out "COMCYL.CSV"$ write "RADIUS, ","SIGR, ","SIGH, ","SIGE, ","TAUMAX, ","EPSR, ","EPSH, ","EPSZ, ", "GAMMAX, ","DISPR, "$ s:={"-"," "," "}$ for x := a step (b-a)/201 until b do << y := {x}$ write part(s,sign(x)+2),abs(x), ", ",part(s,sign(z := (part(y,0) := part(lis,1)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,2)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,3)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,4)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,5)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,6)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,7)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,8)))+2),abs(z), ", ",part(s,sign(z := (part(y,0) := part(lis,9)))+2),abs(z) >>$ shut "COMCYL.CSV"$ off fort$