acer

32348 Reputation

29 Badges

19 years, 330 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@emendes I was already adding it, immediately after submission. (Sorry, my internet connection is very flaky these days.)

I see that Carl has given the same one-liner (the minor difference being that I also extracted the two list results so as to assign them to separate names, while Carl left it as a list of the two results).

Are you willing to accept as "solutions" some constraining relationships between the k__i, or are you are only interested in solutions in which the k__i are all free?

For example, what if there were additional constraints,
   {k__2 = k__3 + k__6 - k__7,
    k__4 = k__1 - k__3 + k__7,
    k__5 = - k__1 + 2*k__3 + k__6 - k__7}
Would that be acceptable, or does your problem demand that the k__i may be arbitrary?

@boe In the original version the mapped operator (procedure) has SF declared as a local. That is done automatically by Maple 2019, because of the detection of code to assign to that name.

The intention of the source code is to assign into the global SF, at that last stage. However if the mapped procedure declare SF as a local name then the assignments won't do the desired assignments into the global SF, and the code won't work as intended.

There are several ways to force the assignments done within the mapped procedure to be made using the global SF name rather than any local SF name. Here below are the ones suggested so far.

In the original source the mapped procedure is an arrow operator, and used anonymously. I've named it P below, to try and make it more clear that what matters is how various versions of procedure P happen to access names SF.

restart; # This first version is like the original.
SF := table([]):  # empty table
P := proc(x) assign(SF[x], foo); end proc:
Warning, `SF` is implicitly declared local to procedure `P`
map(P, [g]):
eval(SF);  # still empty, oops
                           TABLE([])

restart; # This is like Preben's.
SF := table([]):  # empty table
P := proc(x) global SF; assign(SF[x], foo); end proc:
map(P, [g]):
eval(SF);  # hoorah
                        TABLE([g = foo])

restart; # This is like Carl's first.
SF := table([]):  # empty table
P := proc(x) assign(:-SF[x], foo); end proc:
map(P, [g]):
eval(SF);  # hoorah
                        TABLE([g = foo])

restart; # This is like mine.
SF := table([]):  # empty table
P := proc(x) assign('SF'[x], foo); end proc:
map(P, [g]):
eval(SF);  # hoorah
                        TABLE([g = foo])

I don't really think that mine is best, but it's also not outright wrong. The fagility depends on what goes on in the session before the read of the source. Usually I'd read source once and store to a .mla archive, rather than read each session -- that's my preference, so I don't have to worry about it -- the session is clean prior to the read. In that scenario my answer is just fine. If you want that final mapped assignment to be more robust then Carl's second suggestion ':-SF' is good, as is the combination of mine and Preben's. But since there are other things in the source that are also fragile (wrt to prior work in the session) then I think it's relatively moot. Just make the read be first in the session that uses the package, or store it to an archive.

@weidade37211 Yes, the essential idea is to have a rational numeric exponent rather than a floating-point exponent.

It might be a hard call, to discern whether the Statistics routine ought to emit that float exponent in the first place. After all, it is doing what it was told, when the distribution is requested with an explicit float as the second parameter. As I showed in my answer, one alternative is to pass an exact rational as that parameter of the distribution and still do (successful) purely numeric integration.

As for the numeric integration routines, they are able to recognize and handle the singular end-point in the case of the exact rational exponent. But for the floating-point exponent it does not to try a symbolic analysis, which could blow up in general because rational conversion could result in huge numerator and denominator. Then, when it detects the singularity, it doesn't handle it.

See attached, and raise infolevel for even more details. Note: in the case of Digits<=15 it computes in evalhf mode by the _d01ajc NAG integrator, which has its own purely numeric mechanisms to handle the discontinuity. Your original used Digits:=20 . The attachment shows both.

NumericInt_floatexponent.mw

 

You are welcome.

I just added yet another way to animate it in 3D, in my previous comment.

@Anthrazit Yes, I see now that it happens even without restart. I usually start my worksheets with an explicit restart, so I hadn't noticed.

I do not like this behavior and I think that it is wrong, since it is "on" by default but there is no easy way to prevent it.

The opposite behavior ("off" by default) would be easy to alter by simply adding restart at the top of the worksheet.

If this behavior is documented on the Help page for Startup Code then I've missed it. Does anyone else see it?

The 3D surface is defined by two variables x and t. So what is left in that, to vary from frame to frame of an animation?

Look at the title of your own Question. It says "1D wave". How do you expect to animate that in 3D? The surface I showed is not a snapshot of a 2D wave in two spatial dimensions -- it is a 2D surface made by extruding a 1D wave over variable t.

As I mentioned, you could vary the number of terms in the sum (say, n terms in the summation), but it might converge too quickly for that to be meaningfully animated.

You continue to be exceptionally vague about what you want.

I updated my previous comment to animate the 2D curve superimposed on the 3D plot.

If that's not what you mean, then you'll have to explain properly how you think that a 3D figure can ne animated here.

Is it because you want to animate with respect to n!?

So far, you haven't been clear about what you want.

You didn't mention 3D earlier.

Using the same code as before,

    plot3d( sol15, x=0..1, t=0..2 )

Also somewhat fun,

restart;
L:=1: c:=2: g:=0:
f:=(8*x*(L-x)^2)/L^3:
pde:=diff(u(x,t),t$2)=c^2*diff(u(x,t),x$2):
bc:=u(0,t)=0,u(L,t)=0:
ic:=u(x,0)=f,D[2](u)(x,0)=g:
sol:=pdsolve([pde, ic, bc],u(x,t)):
sol15 := rhs(subs(infinity=15,sol)):
tfinal := 2.0:
bg := plot3d( sol15, x=0..1, t=0..tfinal, transparency=0.5 ):
d23 := (p,T) -> plottools:-transform((X,Y)->[X,T,Y])(p):
mk3 := T -> d23(plot(eval(sol15,t=T), x=0..1,
                     color=red, thickness=3), T):
plots:-animate(mk3,[T],T=0..tfinal, frames=50,
               background=bg, orientation=[-20,70]);

[edited, 17/04/2020] Or, another. I know, I know, this is not constructed efficiently. I do prefer using plot with its adaptive plotting instead of spacecurve. But still it would be more efficient to build up the surface as row upon row computed inplace on a re-usable Matrix passed to surfdata, and the rendered surface would appear more stable visually. Maybe when I get a little time.

restart;
L:=1: c:=2: g:=0:
f:=(8*x*(L-x)^2)/L^3:
pde:=diff(u(x,t),t$2)=c^2*diff(u(x,t),x$2):
bc:=u(0,t)=0,u(L,t)=0:
ic:=u(x,0)=f,D[2](u)(x,0)=g:
sol:=pdsolve([pde, ic, bc],u(x,t)):
sol15 := rhs(subs(infinity=15,sol)):
tfinal := 2.0:
d23 := (p,T) -> plottools:-transform((X,Y)->[X,T,Y])(p):
mk3 := proc(T)
         plots:-display(
           d23(plot(eval(sol15,t=T), x=0..1,
                    color=red, thickness=5), T),
           plot3d( sol15, x=0..1, t=0..T,
                   style=surface,
                   grid=[49,5+ceil(45*tfinal/(max(1,T)))] ));
       end proc:
plots:-animate(mk3,[T],T=0..tfinal, frames=100,
               orientation=[45,70]);

The following constructs more efficiently (although it could easily be made even more so, by ripping the spacecurve data from Array AA instead of recomputing it, forming AA by layer without the nested `if`, etc). But the animation now gets constructed fast enough. (I could make it construct this animation yet ten or more times faster, but one would hardly notice as it's already quick. But the GUI would just get overwhelmed playing it, if such improvements in the construction speed used to build it with far more resolution or frames.) A more important improvement here is that the surface drawn "so far" doesn't change from frame to frame, even when the wireframe lines are included.

restart;
L:=1: c:=2: g:=0:
f:=(8*x*(L-x)^2)/L^3:
pde:=diff(u(x,t),t$2)=c^2*diff(u(x,t),x$2):
bc:=u(0,t)=0,u(L,t)=0:
ic:=u(x,0)=f,D[2](u)(x,0)=g:
sol:=pdsolve([pde, ic, bc],u(x,t)):
sol15 := rhs(subs(infinity=15,sol)):
(xa,xb,ta,tb):=0,1,0,2:
M,N := 49,85:
d23 := proc(i::posint, N)
  plots:-spacecurve(eval([x, t, sol15],t=ta+(tb-ta)*(i-1)/(N-1)),
                    x=0..1, numpoints=M, color=red, thickness=4):
end proc:
AA:=Array(1..M,1..N,1..3,(i,j,k)->
          evalhf(`if`(k=1,xa+(xb-xa)*(i-1)/(M-1),
             `if`(k=2,ta+(tb-ta)*(j-1)/(N-1),
                eval(sol15,[x=xa+(xb-xa)*(i-1)/(M-1),
                            t=ta+(tb-ta)*(j-1)/(N-1)])))),
          datatype=float[8]):
mk3 := proc(i,N) local temp; uses plots;
  temp := d23(trunc(i),N);
  if i=1 then temp;
  else display(temp,surfdata(AA[..,1..trunc(i),..]));
  end if;
end proc:
plots:-animate(mk3, [i,N], i=1..N, frames=N,
               orientation=[45,70], paraminfo=false);

Please include a complete example, eg. a worksheet as an attachment uploaded using the green up-arrow in the Mapleprimes editor's menubar. Please include an example of the data, if necessary to execute.

note. Presumably your Maple version is at least as recent as Maple 2015, in which the dataplot command was introduced. If not then examples could still be dispatched to other plotting commands.

@Kitonum Right, that's exactly what I was suggesting. (It was done previously, in a couple of those old postings which I linked to in my Answer.)

@digerdiga You've misunderstood the key point (which is probably my fault for not explaining myself better, sorry).

Of course we can program the operation to convert wrt some key prime factors in the denominator, as Kitonum showed. That is of course very simple to do -- so simple that I deliberately focused instead on the more generally applicable question.

If you know how to handle a particular example then you may build a re-usable identity. We all know various half-angle and double-angle formulas (and can apply in a compound manner). The example you gave is trivial to do.

But if you also want to be able to handle cos(Pi/17), cos(Pi/(3*17)), and other examples then you're better off with a way to generate conversion identities (or an efficient re-usable mechanism) that could then be later applied (and compounded if need be).

Sure, such formulas or a mechanism may only need to be generated once, and stored. But one needs to know how to do that.

More general rules for convert(...,radical) can be constructed. I think that's far more interesting that handling the original example by trivially iterating a formula that is already well known.

@Carl Love In my opinion this is not great general workaround, for a few reasons.

It forces the value to be computed and returned, getting in the way of further programmatic use of the inert sum form. Eg, following natural use of simplify or expand on a larger expression that merely contains the inert sum. And it can take measurably longer than value (even if that's an acceptable result).

So, rather than being a workaround for simplifcation -- even if that were just a "no-op", and the original text suggests that is acceptable here --  it seems like a way to accidentally force a slower value computation.

And doesn't help deal with some related tricky cases with symbolic end-points.

But, who knows, perhaps it will serve the OP's purposes -- in which case, OK.

Somebody removed the original attachment on this Question.

It is here: copy1.mw

@JAMET You have,

   found=false

instead of,

   found:=false

as Carl had in his code.

First 181 182 183 184 185 186 187 Last Page 183 of 592