acer

32303 Reputation

29 Badges

19 years, 308 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

You specifically inquired about implicitplot3d, so in coding below I will address that in particular. It's documented [123] and not too difficult to color/shade a surface constructed by plot3d, etc. Hence if you could break up your implicit x-y-z region into explicitly defined portions then you could use another 3d plotting command. So I'm supposing that you wouldn't be asking about implicitplot3d if you had only an example that was subject to such recourse.

I'm just going to address coloring (arbitrarily) with implicitplot3d, since dharr's already treated your particular surface examples with a split into explicitly formulated portions.

You can in fact utilize a float[8] Array to color the triangles by which the GUI renders the surface, when it displays an ISOSURFACE plotting structure generated by the implicitplot3d command. You can use such an Array to specify coloring by either RGB or HSV values.

But the big problem is that those triangles don't match the set of x-y-z points stored as data in the ISOSURFACE. The ISOSURFACE values are just for the regularly spaced points in the ranges. The location of the vertices of those triangles are a result of the interpolating process by which the GUI's plot driver figures out where the surface might be, and we are not privy to that. So we lack programmatic access to the x-y-z values for the vertices of the GUI-rendered triangles.

Even the number of the mesh points of stored function values doesn't match the number of triangles in the rendered surface. And that number of triangles is also a function of the proportion of the plotting window which the surface occupies.

Here's an example. This code does not form those triangles. The GUI does that. This code merely adds a COLOR substructure to a usual implicitplot3d result, to specifiy hue values for its rendered triangles.

subsindets(plots:-implicitplot3d(x^2+y^2+z^2=3.9,x=-2..2,y=-2..2,z=-2..2,grid=[6,6,6],
                                 lightmodel=none,orientation=[60,75,0]),
           specfunc(ISOSURFACE),
           Iso->ISOSURFACE(op(Iso),
                           COLOUR(HSV,Array(1..1528,1..3,
                                            (ijk,hsv)->
                                              `if`(hsv=1,
                                                   piecewise[1.0](irem(ijk,3)=0,0.1,
                                                                  irem(ijk,3)=1,0.4,
                                                                  irem(ijk,3)=2,0.7),
                                                   1.0),
                                            datatype=float[8]))));

 

 

 

Download ISO_col_0.mw

note: If you changed that to utilize grid=[6,6,7] instead then in Maple 2016.2 and later you could see an example of the GUI message spit out when the coloring Array doesn't have the right number of entries.

As it happens that COLOR substructure's Array can match either the number of segments of the number of vertices (whichever is closest, I suspect). And the GUI spits out a message when there's a bad mismatch. But in neither case do we know the x-y-z coordinates of those vertices, and so we don't know how to populate that COLOR structure's Array. (If I had such a means I'd ditch ISOSURFACE myself, and do the math and draw those portions by my own construction, with full control...)

If I had to distinguish such from a mere procedure call then I'd refer to such as an indexed procedure call.

Now, an index on the base name of a procedure call only would only have a special effect if someone had actually written the original Library procedure to make use of such an index. Otherwise it'd act as it would without the indexing, ie. the index would be simply ignored.

Run your combine and simplify examples involving indexed procedure calls again, but now without the index, and you should get the same results as with the index. Those routines are not coded to recognize and act according to such an index.

Eg, the index [trig] on combine is not what makes this example work as it does. It's just the same result as if no optional arguments were supplied.

combine[trig](exp(sin(a)*cos(b))*exp(cos(a)*sin(b)));

           exp(sin(a + b))

combine(exp(sin(a)*cos(b))*exp(cos(a)*sin(b)));

           exp(sin(a + b))

I don't really understand why you thought that all your modified examples of indexed procedure calls would do something special. The documentation Calling Sequence, Description, and Examples don't indicate that they would.

As for your examples with extra passed options, perhaps additional commentary or examples might make it more clear on the Help page ?combine that the choice of such supplied options may restrict (by virtue of specifying) what manner of combining gets done. Notice how in the following examples the results are each combined only in the sense of the specified option,

combine(exp(sin(a)*cos(b))*exp(cos(a)*sin(b)),[exp]);

combine(exp(sin(a)*cos(b))*exp(cos(a)*sin(b)),[trig]);

combine(exp(sin(a)*cos(b))*exp(cos(a)*sin(b))
        +exp(sin(a)*cos(b)+cos(a)*sin(b)),[trig]);

As for your evalf[n] mention, evalf has been specially written to take account of an index on the called procedure name, and use it like an option. That is documented.

You could utilize the known option of dsolve, using a wrapper around Mt that is just a procedure (that returned unevaluated for nonnumeric input).

The known option is a usual way to inform dsolve that you have a helper (black box) function.

The dsolve command (with its known option) does not appear to recognize directly the kind of appliable object that Interpolation returns. Hence my kludge with a constructed wrapping operator/procedure.

You can compare the result with simply using a linear expression as the rhs driver.

restart;

M := Array(1 .. 10, 1 .. 2):
for i to 10 do
    M[i, 1] := i;
    M[i, 2] := 3*i;
end do:

Mt := Interpolation:-LinearInterpolation(M):

E := unapply('Mt'(t),t,numeric):

diffeq := D(C)(t) = E(t);

(D(C))(t) = E(t)

solA := dsolve({diffeq, C(0) = 0}, {C(t)}, numeric, known=E):

plots:-odeplot(solA,[t,C(t)]);

diffeqB := D(C)(t) = 3*t;
solB := dsolve({diffeqB, C(0) = 0}, {C(t)}, numeric):

(D(C))(t) = 3*t

plots:-odeplot(solB,[t,C(t)]);


Download ds_kn.mw

A variety of ways, with fun still defined outside the procedure.

restart;

fun := x^2+y^2;

x^2+y^2

xt := -1: yt := 2:


Your procedure could evaluate the expression fun by
replacing the global x,y (in fun) by the values of the
procedure's parameters x,y.

Also, more efficiently doing just a single call to the procedure
and making a multiple assignment of its returned sequence.

temp_proc := proc(x, y)
  local lfun, out1, out2, out3;
  lfun := eval(fun,[:-x=x,:-y=y]);
  if x > 0 then
    out1,out2,out3 := lfun, 2*lfun, k*lfun;
  elif x <= 0 then
    out1,out2,out3 := lfun, -2*lfun, -k*lfun;
  end if;
  return out1, out2, out3;
end proc:

out1_fin,out2_fin,out3_fin := temp_proc(xt, yt);

5, -10, -5*k


The same as before, but assigning the sequence of three results
to a single local out.

temp_procB := proc(x, y)
  local lfun, out;
  lfun := eval(fun,[:-x=x,:-y=y]);
  if x > 0 then
    out := lfun, 2*lfun, k*lfun;
  elif x <= 0 then
    out := lfun, -2*lfun, -k*lfun;
  end if;
  return out;
end proc:

out1_fin,out2_fin,out3_fin := temp_procB(xt, yt);

5, -10, -5*k


The same as the last, but without assigning to a
local out. The last result in the proc is what gets returned.

temp_procC := proc(x, y)
  local lfun;
  lfun := eval(fun,[:-x=x,:-y=y]);
  if x > 0 then
    lfun, 2*lfun, k*lfun;
  elif x <= 0 then
    lfun, -2*lfun, -k*lfun;
  end if;
end proc:

out1_fin,out2_fin,out3_fin := temp_procC(xt, yt);

5, -10, -5*k


The same a the last, but using a passed operator (formed
just once from the expression fun) instead of evaluating
to replace the global name instances.

Note that Fun is only called once, inside the procedure,
which is efficient.

 

One point that might be key to you is that you might already
have fun as an expression computed elsewhere. The unapply constructs
the operator from that.

 

temp_procD := proc(x, y, F)
  local lfun;
  lfun := F(x,y);
  if x > 0 then
    lfun, 2*lfun, k*lfun;
  elif x <= 0 then
    lfun, -2*lfun, -k*lfun;
  end if;
end proc:

Fun := unapply(fun,x,y);

proc (x, y) options operator, arrow; x^2+y^2 end proc

out1_fin,out2_fin,out3_fin := temp_procD(xt, yt, Fun);

5, -10, -5*k

 

Like the previous, but without passing in the operator.

 

temp_procE := proc(x, y)
  local lfun;
  lfun := Fun(x,y);
  if x > 0 then
    lfun, 2*lfun, k*lfun;
  elif x <= 0 then
    lfun, -2*lfun, -k*lfun;
  end if;
end proc:

Fun := unapply(fun,x,y);

proc (x, y) options operator, arrow; x^2+y^2 end proc

out1_fin,out2_fin,out3_fin := temp_procE(xt, yt);

5, -10, -5*k

 

Download fun_var.mw

f := x -> (1-k*x)/(1+x^2):

Student:-Calculus1:-Tangent(f(x), x=3);

(2/25)*k*x-(3/50)*x-(27/50)*k+7/25

 

And, optionally,

 

collect(%, x);

x*((2/25)*k-3/50)-(27/50)*k+7/25

Download Tg_ex.mw

You didn't state how wide you wanted the columns.

The following shows that your stated goal of getting the columns centered at 1,2,3 can be done using only one extra (option) value chosen by you. Here the other options can be just functions of that -- see last example.

You could use 0 < width <= 1 below.

restart;

x:= Vector([1,2,3]):

Statistics:-ColumnGraph(x,'offset'=0.5,'distance'=0,'width'=1);

Statistics:-ColumnGraph(x,'offset'=1-0.7/2,'distance'=1-0.7,'width'=0.7);

Download CG_ex.mw

You don't actually need to assign to locals DV,RV1,RV2 inside the procedure. You could simply utilize the parameters DVA,RV1A,RV2A instead. Your choice.

At least one of your worksheets (you had multiple attachments, apparently duplucates...) has at least one instance of hidden characters, making the statement with the RV1 assignment not as it appeared.

" restart: with(plots):with(DEtools):with(Student[ODEs]):infolevel[Student]:=3 ;"

3

DV := y(x)*diff(y(x), x) = exp(x);

y(x)*(diff(y(x), x)) = exp(x)

RV1 := y(1) = 1;
RV2 := y(1) = -1;

y(1) = 1

y(1) = -1

opl_1 := dsolve({DV, RV1}, y(x));

y(x) = (2*exp(x)-2*exp(1)+1)^(1/2)

opl_2 := dsolve({DV, RV2}, y(x));

y(x) = -(2*exp(x)-2*exp(1)+1)^(1/2)

opl := plot({rhs(opl_1), rhs(opl_2)}, x = 0 .. 5, y = -10 .. 10, thickness = 3)

lijnelement := dfieldplot(DV, y(x), x = 0 .. 5, y = -10 .. 10, title = "lijnelementveld met intergaalkromme door (1,1)(1,-1)")

display({opl, lijnelement}, size = [500, 400])

restart

DVplot:=proc(DVA,RV1A,RV2A)
          local DV,RV1,RV2,opl_1,opl_2,opl,lijnelement;
          DV := DVA;
          RV1 := RV1A;
          RV2 := RV2A;
          opl_1 := dsolve({DV, RV1}, y(x));
          opl_2 := dsolve({DV, RV2}, y(x));
          opl := plot({rhs(opl_1), rhs(opl_2)}, x = 0 .. 5, y = -10 .. 10, 'thickness' = 3);
          lijnelement := DEtools:-dfieldplot(DV, y(x), x = 0 .. 5, y = -10 .. 10,
                                             'title' = "lijnelementveld met intergaalkromme door (1,1)(1,-1)");
          plots:-display({opl, lijnelement}, _rest);
end proc:

DVA := y(x)*(diff(y(x), x)) = exp(x)

y(x)*(diff(y(x), x)) = exp(x)

RV1A := y(1) = 1

y(1) = 1

RV2A := y(1) = -1

y(1) = -1

DVplot(DVA, RV1A, RV2A, size = [500, 400])

NULL

Download DV_plotten-_procedure_ac.mw

[edit] Earlier I wondered why you didn't use DEplot. But now I see that your explicit symbolic solution makes it easier to handle the left-endpoint.

 

pow := x -> x^op(1,procname):

pow[3](7);

             343
pow[4](1.1);

            1.4641

pow[3/2](1.1);

         1.153689732

One problem with evalf(...,n) is that it can be confusing to some users when the first argument is a name that has been assigned a sequence.

The evaluation rules of evalf keep that sequence from being flattened before evalf receives them.

It keeps things more clear to use evalf[n] intead.

A made-up example:

restart;

 

L := Int(sin(x)/3,x=0..Pi), 13;

Int((1/3)*sin(x), x = 0 .. Pi), 13

The intent and behavior here is clear.

evalf[ L[2] ]( L[1] );

.6666666666667

This also gets the same effect, but when evalf(...,n)
was documented then some people would get surprised
that the final example doesn't get this same result.

evalf( L[1], L[2] );

.6666666666667

Some people might mistakenly expect the following
to use 13 digits of working precision while computing
only the numeric integral.

But instead it does floating-point computation of each
entry in sequence L, at default 10 Digits.

evalf( L );

.6666666667, 13.

Download evalf_seq_ex.mw

For backwards compatibility evalf(...,n) still works. But it seems more user-friendly to only document the less potentially confusing syntax.

 

restart;

r := Vector[row](3, symbol=R);

Vector[row](3, {(1) = R[1], (2) = R[2], (3) = R[3]})

c := Vector(3, symbol=C);

Vector(3, {(1) = C[1], (2) = C[2], (3) = C[3]})

c.r;

Matrix(3, 3, {(1, 1) = C[1]*R[1], (1, 2) = C[1]*R[2], (1, 3) = C[1]*R[3], (2, 1) = C[2]*R[1], (2, 2) = C[2]*R[2], (2, 3) = C[2]*R[3], (3, 1) = C[3]*R[1], (3, 2) = C[3]*R[2], (3, 3) = C[3]*R[3]})

(c.r)^%T

Matrix(3, 3, {(1, 1) = C[1]*R[1], (1, 2) = C[2]*R[1], (1, 3) = C[3]*R[1], (2, 1) = C[1]*R[2], (2, 2) = C[2]*R[2], (2, 3) = C[3]*R[2], (3, 1) = C[1]*R[3], (3, 2) = C[2]*R[3], (3, 3) = C[3]*R[3]})

with(LinearAlgebra):

OuterProductMatrix(r,c);

Matrix(3, 3, {(1, 1) = C[1]*R[1], (1, 2) = C[2]*R[1], (1, 3) = C[3]*R[1], (2, 1) = C[1]*R[2], (2, 2) = C[2]*R[2], (2, 3) = C[3]*R[2], (3, 1) = C[1]*R[3], (3, 2) = C[2]*R[3], (3, 3) = C[3]*R[3]})

OuterProductMatrix(r,c)^%T;

Matrix(3, 3, {(1, 1) = C[1]*R[1], (1, 2) = C[1]*R[2], (1, 3) = C[1]*R[3], (2, 1) = C[2]*R[1], (2, 2) = C[2]*R[2], (2, 3) = C[2]*R[3], (3, 1) = C[3]*R[1], (3, 2) = C[3]*R[2], (3, 3) = C[3]*R[3]})

Download OPM.mw

You didn't state whether you were using the numeric option of dsolve.

I'll give an example of a system solution both without and with the numeric option.

For the symbolic solution you can plot the solutions using either expressions or operators (constructed using unapply). I show both. For the numeric solution you can use odeplot (or plot the operators that I obtain).

restart;

>

 

ode := diff(f(x),x,x) = -f(x), diff(g(x),x)=g(x)-2*f(x);

diff(diff(f(x), x), x) = -f(x), diff(g(x), x) = g(x)-2*f(x)

ics := f(0)=0, D(f)(0)=1, g(0)=1;

f(0) = 0, (D(f))(0) = 1, g(0) = 1

Sans := dsolve({ode, ics}, {f(x),g(x)});

{f(x) = sin(x), g(x) = sin(x)+cos(x)}

fexpr := eval(f(x),Sans);
gexpr := eval(g(x),Sans);

sin(x)

sin(x)+cos(x)

plot([fexpr, gexpr], x=0..2*Pi);

eval( [fexpr,gexpr], x=Pi/3 );

[(1/2)*3^(1/2), (1/2)*3^(1/2)+1/2]

Sf := unapply(fexpr,x);

proc (x) options operator, arrow; sin(x) end proc

Sg := unapply(gexpr,x);

proc (x) options operator, arrow; sin(x)+cos(x) end proc

plot([Sf, Sg], 0..2*Pi);

[Sf(Pi/3), Sg(Pi/3)];
evalf(%);

[(1/2)*3^(1/2), (1/2)*3^(1/2)+1/2]

[.8660254040, 1.366025404]

Sf(x), Sg(x);

sin(x), sin(x)+cos(x)

Fans := dsolve({ode, ics}, {f(x),g(x)}, numeric, output=listprocedure):

plots:-odeplot(Fans, [[x,f(x)],[x,g(x)]], x=0..2*Pi, size=[600,200]);

Ff := eval(f(x),Fans):

Fg := eval(g(x),Fans):

[Ff(Pi/3), Fg(Pi/3)];

[HFloat(0.8660254938907389), HFloat(1.3660255551127731)]

 

Download ds_func_ex.mw

You can also read the documentation.

restart;

expr:=exp(2*a);

exp(2*a)

 

The following does a structural change. And the result displays
differently, accordingly and not just as some typesetting effect.
(This Question originally had the `typesetting` tag.)

 

G := expand(expr);

(exp(a))^2

 

The two expressions can behave differently, in particular under
arithmetic operations.

 

indets(expr);

{a, exp(2*a)}

indets(G);

{a, exp(a)}

expr/exp(a);

exp(2*a)/exp(a)

G/exp(a);

exp(a)

 

There are other operations which do not normally "see" that
exp(2*a)=exp(a)^2.

 

factor( exp(2*a)+2*exp(a)+1 );

exp(2*a)+2*exp(a)+1

factor( expand( exp(2*a)+2*exp(a)+1 ) );

(exp(a)+1)^2

 

You can control what does or does not get expanded.

 

expr2 := sin(x+y) + exp(2*a);

sin(x+y)+exp(2*a)

expand( expr2 );

sin(x)*cos(y)+cos(x)*sin(y)+(exp(a))^2

expand(expr2, exp(2*a) );

sin(x)*cos(y)+cos(x)*sin(y)+exp(2*a)

This one is like an example on the expand Help page.

expand(expr2, op(indets(expr2,specfunc(exp))) );

sin(x)*cos(y)+cos(x)*sin(y)+exp(2*a)

frontend(expand, [expr2], [{`+`,trig}]);

sin(x)*cos(y)+cos(x)*sin(y)+exp(2*a)

 

The behavior is not restricted to just exp.

 

expr3 := t^(2*a);

t^(2*a)

expand( expr3 );

(t^a)^2

combine( % );

t^(2*a)

combine( expand( expr ) );

exp(2*a)

 

The ability to forcibly change the structure in such ways is
fundamentally useful to symbolic programming.

 

Download expand_exp_notes0.mw

Does this serve your purpose?

restart;

ode1:= diff(c(T),T)=-2*c(T)*(1+beta__c*c(T)^2/p__c(T)^2):
ode2:= diff(p__c(T),T)=2*(1+beta__c*c(T)^2/p__c(T)^2)*p__c(T):

alt:=map(solve,eval([dsolve(eval([ode1,ode2],[p__c(T)=P__c(T)*beta__c]),
                            [c(T),P__c(T)],'explicit')],
                    [P__c(T)=p__c(T)/beta__c]),
         {p__c(T),c(T)});

[{c(T) = -2*2^(1/2)*(c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = -((1/2)*I)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = 2*2^(1/2)*(c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = -((1/2)*I)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = -2*2^(1/2)*(c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = ((1/2)*I)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = 2*2^(1/2)*(c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = ((1/2)*I)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = -2*(-2*c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = -(1/2)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = 2*(-2*c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = -(1/2)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = -2*(-2*c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = (1/2)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}, {c(T) = 2*(-2*c__2*beta__c/(2*c__1*(exp(T))^8+16*c__2)^(1/2))^(1/2), p__c(T) = (1/2)*(8*c__1*(exp(T))^8+64*c__2)^(1/4)*beta__c}]

map(X->odetest(X,[ode1,ode2]),alt);

[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]

Download ode_sc.mw

 

Yes, one way to see that this is automatically simplified is to
observe that it occurs even if evaluation is delayed via quotes.

 

Automatic simplification occurs between parsing and evaluation.

 

'[a,b]/2';

[(1/2)*a, (1/2)*b]

 

Your second example did not automatically act across the list
because the factor was not of type numeric.

[a,b]/exp(2);

[a, b]/exp(2)

 

You can avoid the hammer of an expand call by dividing elementwise.

 

[a,b]/~c;

[a/c, b/c]

Download list_auto_ex.mw

What do you think it means to integrate w.r.t. y an expression containing both y and y[1]?!

Try changing y[1] to something like y1 or y__1, if you intend it to be wholly independent of y the variable of integration.

[edit] It should be obvious that this applies to y[2] as well, or any other indexed instance of the variable of integration. It doesn't make sense at all to have such present in the integrand.

First 25 26 27 28 29 30 31 Last Page 27 of 336