acer

32303 Reputation

29 Badges

19 years, 310 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

You could call rsolve on the system, after converting floats to exact rationals. This produces an explicit solution.

You could then utilize the explicit result, eg. applying evalf to the result formulas, or applying evalf after using values for t.  See each of ansE, andF, and ansFF below. Of those, offhand I would suggest the first scheme with ansE, substituting values of t into the exact formulas and then applying evalf as a last step. Your mileage may vary.

You could experiment with higher Digits, when evaluating and evalf'ing at concrete values of t.

restart

eqns := {x(t+1) = (1+10^(-6)*(0.4e-2-0.6e-2)/(0.1e-3))*x(t)+0.7e-1*10^(-6)*y(t), y(t+1) = 0.6e-2*10^(-6)*x(t)/(0.1e-3)+(1-0.7e-1*10^(-6))*y(t)};

{x(t+1) = .9999800000*x(t)+0.7000000000e-7*y(t), y(t+1) = 0.6000000000e-4*x(t)+.9999999300*y(t)}

(1)

ics := x(0) = 1, y(0) = 0.6e-2/(0.1e-3*0.7e-1);

x(0) = 1, y(0) = 857.1428571

(2)

exactsys := convert(`union`(eqns, {ics}), rational, exact);

{x(0) = 1, x(t+1) = (49999/50000)*x(t)+(7/100000000)*y(t), y(0) = 8571428571/10000000, y(t+1) = (3/50000)*x(t)+(99999993/100000000)*y(t)}

(3)

ansE := rsolve(exactsys, {x(t), y(t)}):

seq(evalf(eval([x(t), y(t)], ansE)), t = 0 .. 10);

[1.000000000, 857.1428571], [1.000040000, 857.1428578], [1.000079998, 857.1428571], [1.000119996, 857.1428571], [1.000159995, 857.1428578], [1.000199991, 857.1428571], [1.000239985, 857.1428578], [1.000279982, 857.1428571], [1.000319976, 857.1428571], [1.000359969, 857.1428564], [1.000399962, 857.1428571]

(4)

ansF := evalf(simplify(evala(ansE)))

{x(t) = 2.959071540*1.000000139^t-1.959071540*.9999797914^t, y(t) = 851.3060785*1.000000139^t+5.836778856*.9999797914^t}

(5)

seq(eval([x(t), y(t)], ansF), t = 0 .. 10);

[1.000000000, 857.1428574], [1.000040001, 857.1428577], [1.000080002, 857.1428582], [1.000120002, 857.1428585], [1.000160001, 857.1428589], [1.000199999, 857.1428593], [1.000239997, 857.1428597], [1.000279993, 857.1428600], [1.000319988, 857.1428605], [1.000359984, 857.1428609], [1.000399978, 857.1428612]

(6)

ansFF := simplify(ansF);

{x(t) = 2.959071540*exp(0.1389999903e-6*t)-1.959071540*exp(-0.2020880420e-4*t), y(t) = 851.3060785*exp(0.1389999903e-6*t)+5.836778856*exp(-0.2020880420e-4*t)}

(7)

seq(eval([x(t), y(t)], ansFF), t = 0 .. 10);

[1.000000000, 857.1428574], [1.000040001, 857.1428577], [1.000080002, 857.1428582], [1.000120002, 857.1428585], [1.000160000, 857.1428589], [1.000199999, 857.1428593], [1.000239997, 857.1428597], [1.000279993, 857.1428600], [1.000319988, 857.1428605], [1.000359984, 857.1428609], [1.000399978, 857.1428612]

(8)

``NULL

Download SystemRecursive_ac.mw

You could compare results with those from a recursive procedure such as Kitonum supplied. Don't expect both to agree to all decimal places.

The following attachment demonstrates re-using the "preconditioned" information (eg. column switching to minimize fill-in, etc), given that the new Matrix has the exact same sparsity pattern as the original.

sparse_direct_symb8.mw

The next attachment replaces my SLU procedure from my previous code, as an edit to your revision of the original worksheet. It implements the previous SLU's actions but in a finer set of steps, allowing the "symbolic precontioninging" to be reused for subsequent calls.

Phasefield2DBaseCodeParametricMay02_ac1.mw

It gets some timing improvement over my previous. But I have not had time to replace the Jac1 procedure with an efficient scheme of generating the sparse matrix's triple-of-vectors (neither compressed nor uncompressed row-column index vectors). As the problem size grew that Jac1 incurred a significant portion of the time cost.

As bonus, UMFPACK's Control array is here directly available, and you could even try tweaking certain parameters of the solver. (Earlier I had mistakenly presumed that array was a struct, so it was easier than I'd imagined.)

Perhaps you could utilize this (slightly modified, accordingly) alongside your code that efficiently produces the sparse Matrix directly in a triple-vector format.

[edit] For anyone else reading this, the goal here is to remove the need for calling umfpack_dl_symbolic following the first sparse linear solve. This is remove duplicated effort in constructing the preconditioning -- given that the sparsity pattern of the lhs matrix remains the same for all linear solves.

The goal here is not to provide functionality to allow different rhs B in repeated linear solving. In fact since I didn't provide a way to undefine the module's Sym and Num locals then at present it can only be used for a single sparsity pattern per restart. And it also doesn't have functionlity to "free" memory associate with those handles.

You can use the eval command for this, to evaluate expressions using substitutions for x.

These eval calls can each be passed directly as the first argument in calls to the plot command.

V1 := -x:
V2:= -2*x + 4.95:
V3:= -x + 1.665:

l_1:=1.665: l_2:=4.95:

eval(V2, x=x-l_1);

        -2 x + 8.280

eval(V3, x=x-l_1-l_2);

         -x + 8.280

There are several variants on all that. Here is one such, in which l_1 and l_2 do not need to actually be assigned.

restart;
V1 := -x:
V2:= -2*x + 4.95:
V3:= -x + 1.665:

params := [ l_1=1.665, l_2=4.95 ]:

eval(V2, x=eval(x-l_1, params));

        -2 x + 8.280

eval(V3, x=eval(x-l_1-l_2, params));

         -x + 8.280

kernelopts(version);

`Maple 18.02, X86 64 LINUX, Oct 20 2014, Build ID 991181`

A:= {{a, b, c}, {a, b, d}};

{{a, b, c}, {a, b, d}}

`+`(op((`+`@op)~(A)));

2*a+2*b+c+d

add(add(xx,xx=x),x=A);

2*a+2*b+c+d

Download add_map_sets.mw

The following uses RootFinding:-NextZero (internally):

   fsolve(cos(x)=x^2/1000,x=-40..40,maxsols=infinity);

On my Maple 2022.0 (and 2018.2, which is what the OP seems to have used) that returns 22 roots.

This is a common mistake.

One way to deal with it is to construct the operator (procedure) G by using the unapply command.

Another way is to use expressions instead of operators for g and G.

restart;

g := x -> 1;

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

G := unapply(int(g(x),x),x);

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

G(x);

x

G(5);

5

restart;

g := 1;

1

G := int(g, x);

x

eval(G, x=5);

5

Download expr_vs_operators.mw

f:=(x,y)->piecewise(x<>0 or y<>0,(y^2+x^2)^x,1):

DX,DY:=D[1](f),D[2](f):

DX(1,1),DY(1,1);

               2 ln(2) + 2, 2

If you are looking to construct the following (or similar) then you could utilize the foldl command instead of rolling your own implementation.

L:=[a,b,c,d]:
v:=[p,q,r,s]:

foldl((z,j)->F(z,L[j])-v[j],y,$1..nops(L));

   F(F(F(F(y, a) - p, b) - q, c) - r, d) - s

I added option redraw=false to the plots:-display calls, and option adaptive=true to the plot calls.

I also changed sum to add, and Int to Int, and a few other minor edits.

The result runs in my 2022.0 about 5% faster than in 2020.2.

marlin01.mw

Here's one way:

restart;

eq1 := 2*(k+1)*X(k+1)+(k+1)*Y(k+1)-X(k)-Y(k)+(1)/k!=0:

eq2 := (k+1)*X(k+1)+(k+1)*Y(k+1)+2*X(k)+Y(k)+(1)/k!=0:

temp := rsolve({eq1-eq2,Y(0)=1},{Y(k)});

{Y(0) = 1, Y(k) = (1/2)*X(k+1)*k+(1/2)*X(k+1)-(3/2)*X(k)}

extra :=eval[recurse](solve(select(has,temp,X(k+1)),X(k+1)),
                      [k=0,X(0)=2,Y(0)=1]);

{X(1) = 8}

ansX := convert( rsolve({eval(eq2,Y=unapply(eval(Y(k),temp),k)),
                         X(0)=2} union extra, {X(k)}),
                 factorial );

(-1+3*cos((1/2)*k*Pi)+9*sin((1/2)*k*Pi))/factorial(k)

ansY := convert( simplify(eval(eval(Y(k),temp),X=unapply(ansX,k))),
                 factorial );

-(k+1)*(15*sin((1/2)*k*Pi)-1)/factorial(k+1)

seq([ansX,ansY],k=0..5);

[2, 1], [8, -14], [-2, 1/2], [-5/3, 8/3], [1/12, 1/24], [1/15, -7/60]

Download rsolve_fun.mw

I did that in Maple 2022.0. In, say, Maple 2020.2 I could wrap evalc(simplify(ansX)) to get the pure trig form instead of terms like I^k and (-I)^k. I guess that aspect of the form is a matter of preference.

restart;

ee := sum(-5*3^(-k-1)*(x-2)^k, k=0..infinity);

sum(-5*3^(-k-1)*(x-2)^k, k = 0 .. infinity)

temp1 := map(uu->map(u->`if`(u::algebraic,
                             expand(simplify(content(u))*simplify(u/content(u))),
                             u),
                     uu),simplify(ee));

-(5/3)*(sum((x-2)^k/3^k, k = 0 .. infinity))

temp2 := (u->sign(u)*content(u) %* (u/(sign(u)*content(u))))(temp1);
                           

`%*`(-5/3, sum((x-2)^k/3^k, k = 0 .. infinity))

InertForm:-Display(temp2, ':-inert'=false);

0, "%1 is not a command in the %2 package", _Hold, Typesetting

InertForm:-Display(temp2 = `assuming`([value(temp1)],[abs(x-2)<3]),
                   ':-inert'=false);

`%*`(-5/3, sum((x-2)^k/3^k, k = 0 .. infinity)) = 5/(x-5)

 

Download sum_simp.mw

That temp1 could also be attained by the following.

subsindets(simplify(ee),specfunc({sum,Sum}),
           u->expand(op(0,u)(simplify(content(op(1,u)))
                             *simplify(op(1,u)/content(op(1,u))),
                             op(2..,u))));

The later steps are just for formatting of an inert multiplication by -5/3.

Other examples might require slightly different formulations -- I can't tell what might be your more general case (... if there is such).

Here are two similar approaches, both using `%*` for an inert multiplication. The second gets pretty-printed nicely under both extended and standard typesetting level, whereas the first does so only for extended.

restart;

interface(version);

`Standard Worksheet Interface, Maple 2015.2, Linux, December 21 2015 Build ID 1097895`

ee:=(1/1296)*cBooP0-(1/1296)*cSRP0-(1/1296)*tStartRamp*f__SR/N;

(1/1296)*cBooP0-(1/1296)*cSRP0-(1/1296)*tStartRamp*f__SR/N

interface(typesetting=extended):

(u->`%*`(u,ee/u))(content(numer(ee))/content(denom(ee)));

`%*`(1/1296, cBooP0-cSRP0-tStartRamp*f__SR/N)

interface(typesetting=standard):

InertForm:-Display((u->`%*`(u,ee/u))(content(numer(ee))/content(denom(ee))),
                   ':-inert'=false);

1/1296*(cBooP0-cSRP0-tStartRamp*f__SR/N)

Download yank.mw

That numeric (rational) factor will get distributed across that sum (when that N is not also put into the denominator). That happens due to automatic simplification, which occurs between parsing and evaluation and which thus cannot be prevented by unevaluation quotes.

'4*(x-y)';

                4 x - 4 y

In the solution above I've prevented the automatic distribution by using an inert multiplication. There are other ways around it. One is to wrap the numeric factor in a call to ``(...), ie. ``(1/1296) but I don't like thay because it renders wrapped in extraneous round brackets.

lprint(indets(sys, name));

   {x, c[0], c[1], c[2], c[3], eqq[0], eqq[3]}

Your last loop only assigns to eqq[1] and eqq[2]. Your code has that loop as,

for i to n-1 do
  eq[i] := RHS_weak_form(i);
end do

Perhaps you intended something more like the following (I am guessing):

for i from 0 to n do
  eqq[i] := evalf(eq[i]-RHS(i));
end do;

But if that is the case then your system would have five unknowns: {x, c[0], c[1], c[2], c[3]}, but x is a dummy name of integration. By informing fsolve that the variables are only {c[0], c[1], c[2], c[3]}, I get the following,

SOL := fsolve(sys, {c[0], c[1], c[2], c[3]});

    {c[0] = 1.000000000, c[1] = -13.06296523,
     c[2] = -11.79236213, c[3] = 2.718281828}

Revised worksheet:

restart

n := 3:

for i from 0 to n do L[i] := Typesetting:-delayDotProduct(product((x-t[j])/(t[i]-t[j]), j = 0 .. i-1), product((x-t[k])/(t[i]-t[k]), k = i+1 .. n)); phi[i] := unapply(%, x) end do:

unassign('u', 'v');

u_g := unapply(add(c[i]*phi[i](x), i = 0 .. n), x);

proc (x) options operator, arrow; c[0]*(-3*x+1)*(-(3/2)*x+1)*(-x+1)+3*c[1]*(x.((-3*x+2)*(-(3/2)*x+3/2)))+(3/2)*c[2]*(x*(3*x-1).(-3*x+3))+c[3]*x*((3/2)*x-1/2)*(3*x-2) end proc

(1)

RHS_weak_form := proc (i) options operator, arrow; a(u_g, phi[i])+L(u_g^2, phi[i]) end proc;

proc (i) options operator, arrow; a(u_g, phi[i])+L(u_g^2, phi[i]) end proc

(2)

for i to n-1 do eq[i] := RHS_weak_form(i) end do:

f := proc (t) options operator, arrow; exp(t)+exp(2*t) end proc:

RHS := proc (i) options operator, arrow; evalf(L(f, phi[i])) end proc:

eq[0] := u_g(0) = 1:

sys := [seq(eqq[j], j = 0 .. n)]:

SOL := fsolve(sys, {c[0], c[1], c[2], c[3]});

{c[0] = 1.000000000, c[1] = -13.06296523, c[2] = -11.79236213, c[3] = 2.718281828}

(3)

NULL

Download problem_solve_system_ac.mw

Either rationalize or evalc can get that task done. And then you might further adjust as you wish.

restart;

Zin := Rin + omega*L*I + (omega*L)^2/(RL + omega*L*I);

Rin+I*omega*L+omega^2*L^2/(RL+I*omega*L)

rationalize(Zin);

-(I*L*RL*omega+I*L*Rin*omega+RL*Rin)*(I*omega*L-RL)/(L^2*omega^2+RL^2)

simplify(expand(rationalize(Zin)));

(L^2*(RL+Rin)*omega^2+I*L*RL^2*omega+RL^2*Rin)/(L^2*omega^2+RL^2)

simplify(evalc(Zin));

(L^2*(RL+Rin)*omega^2+I*L*RL^2*omega+RL^2*Rin)/(L^2*omega^2+RL^2)

Download simpex.mw

note: You used rationalize to similar effect in a previous Question.

Here is another way, with a single call to solve.

Its result fortuitously contains the pair of solutions with calls to 2-argument arctan, as you wanted.

Each also happens to contain the beta(t) solution, but if needed then it's trivial to sieve that out -- as shown in the last line below.

restart

kernelopts(version)

`Maple 2022.0, X86 64 LINUX, Mar 8 2022, Build ID 1599809`

(1)

Vector(3, {(1) = (l+s(t))*cos(beta(t))+xo+s(t)-x(t), (2) = sin(beta(t))*(l+s(t))*sin(alpha(t))-y(t), (3) = -sin(beta(t))*(l+s(t))*cos(alpha(t))-z(t)})

Vector[column](%id = 36893628144889207972)

(2)

"solve([?[2],?[3]],[alpha(t),beta(t)],explicit);"

[[alpha(t) = arctan(y(t)/(z(t)^2+y(t)^2)^(1/2), -z(t)/(z(t)^2+y(t)^2)^(1/2)), beta(t) = arcsin((z(t)^2+y(t)^2)^(1/2)/(l+s(t)))], [alpha(t) = arctan(-y(t)/(z(t)^2+y(t)^2)^(1/2), z(t)/(z(t)^2+y(t)^2)^(1/2)), beta(t) = -arcsin((z(t)^2+y(t)^2)^(1/2)/(l+s(t)))]]

(3)

map(proc (u) options operator, arrow; alpha(t) = eval(alpha(t), u) end proc, %)

[alpha(t) = arctan(y(t)/(z(t)^2+y(t)^2)^(1/2), -z(t)/(z(t)^2+y(t)^2)^(1/2)), alpha(t) = arctan(-y(t)/(z(t)^2+y(t)^2)^(1/2), z(t)/(z(t)^2+y(t)^2)^(1/2))]

(4)

NULL

Download Arctan_ac.mw

You're original example happened to get the intermediate solution (for beta(t)) unsimplified, because subs does not induce a final evaluation.

Your undesired example was not due to automatic simplification, which has a very specific meaning. It was due to the usual full evaluation that happens to arguments of procedure calls, eg. calls to solve. You can also pass the intermediate result from subs -- referenced as its own separate result -- in an argument of a call to solve, while avoiding the usual full evaluation by means forced 1-level eval.  Arctan_ex.mw

But this is all quite problem-specific. I don't see how you can reasonably expect always to be able to get semi-generic solutions that just happen to cover (explicitly, separately) only a pair of branches.

First 68 69 70 71 72 73 74 Last Page 70 of 336