Solving Equations with (wx)Maxima: Control stack exhausted
I'm trying to solve equations with (wx)Maxima: formulate the equation, then let it insert the variables and solve the equation for the missing variable. But I'm having a hard time. Somehow it's having problems in the last line:
Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.
That's my code:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
α: 30*%pi/180;
/*α: 30*°;*/
masse: 1000*kg;
g: 9.80665*m/(s*s);
b: 0.3*m;
B: 0.5*m;
L: 0.1*m;
F_g: masse*g;
F_H: masse * g;
kill(S, x);
S: solve(0=F_H-2*x*sin(α), x);
S: assoc(x, S);
kill(H, x);
H: solve(0=-F_g+2*x, x);
H: assoc(x, H);
kill(Ly, x);
Ly: solve(tan(α)=x/(B/2), x);
Ly: assoc(x, Ly);
kill(FN, x);
FN: solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x);
FN: assoc(x, FN);
If I calculate it "directly", it works though:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
kill(FN, x);
FN: solve([α=30*%pi/180, H=196133/40*N,
B=0.5*m, L=0.1*m,
Ly=sqrt(3)/12*m, S=196133/20*N,
0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly],
[x, α, H, B, L, Ly, S]);
FN: assoc(x, FN[1]);
FN: float(FN);
(FN) 1934473685/128529*N
Unfortunately the unit package has not been updated in some time. I'll suggest to use instead the package ezunits, in which dimensional quantities are represented with a back quote. To solve equations, try dimensionally which goes through some gyrations to help other functions with dimensional quantities, e.g. dimensionally (solve (...)). (Note that dimensionally isn't documented, I'm sorry for the shortcoming.)
I've modified your program a little to remove some unneeded stuff and also to use rational numbers instead of floats; Maxima is generally more comfortable with rationals and integers than with floats. Here is the program:
linel: 65 $
load(ezunits) $
α: 30*%pi/180;
masse: 1000`kg;
g: rationalize(9.80665)`m/(s*s);
b: 3/10`m;
B: 5/10`m;
L: 1/10`m;
F_g: masse*g;
F_H: masse * g;
S: dimensionally (solve(0=F_H-2*x*sin(α), x));
S: assoc(x, S);
Ly: dimensionally (solve(tan(α)=x/(B/2), x));
Ly: assoc(x, Ly);
FN: dimensionally (solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x));
FN: assoc(x, FN);
subst (x = S, F_H-2*x*sin(α));
subst (x = Ly, tan(α)=x/(B/2));
subst (x = FN, H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly);
ratsimp (expand (%));
and here is the output I get. Note that I substituted the solutions back into the equations to verify them. It looks like it worked as expected.
(%i2) linel:65
(%i3) load(ezunits)
(%i4) α:(30*%pi)/180
%pi
(%o4) ---
6
(%i5) masse:1000 ` kg
(%o5) 1000 ` kg
(%i6) g:rationalize(9.80665) ` m/(s*s)
5520653160719109 m
(%o6) ---------------- ` --
562949953421312 2
s
(%i7) b:3/10 ` m
3
(%o7) -- ` m
10
(%i8) B:5/10 ` m
1
(%o8) - ` m
2
(%i9) L:1/10 ` m
1
(%o9) -- ` m
10
(%i10) F_g:masse*g
690081645089888625 kg m
(%o10) ------------------ ` ----
70368744177664 2
s
(%i11) F_H:masse*g
690081645089888625 kg m
(%o11) ------------------ ` ----
70368744177664 2
s
(%i12) S:dimensionally(solve(0 = F_H-2*x*sin(α),x))
690081645089888625 kg m
(%o12) [x = ------------------ ` ----]
70368744177664 2
s
(%i13) S:assoc(x,S)
690081645089888625 kg m
(%o13) ------------------ ` ----
70368744177664 2
s
(%i14) Ly:dimensionally(solve(tan(α) = x/(B/2),x))
1
(%o14) [x = --------- ` m]
4 sqrt(3)
(%i15) Ly:assoc(x,Ly)
1
(%o15) --------- ` m
4 sqrt(3)
(%i16) FN:dimensionally(solve(0 = (H*B)/2-x*(L+Ly)
+(S*sin(α)*B)/2
+S*cos(α)*Ly,x))
1 1
(%o16) [x = (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)]
(%i17) FN:assoc(x,FN)
1 1
(%o17) (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)
(%i18) subst(x = S,F_H-2*x*sin(α))
kg m
(%o18) 0 ` ----
2
s
(%i19) subst(x = Ly,tan(α) = x/(B/2))
1 1
(%o19) ------- = -------
sqrt(3) sqrt(3)
(%i20) subst(x = FN,(H*B)/2-x*(L+Ly)+(S*sin(α)*B)/2+S*cos(α)*Ly)
1 1
(- ---------) - --
4 sqrt(3) 10 1
(%o20) ((----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2 H
+ 1150136075149814375 3 ` kg m) + -) ` m
4
2
690081645089888625 kg m
+ ------------------ ` -----
281474976710656 2
s
(%i21) ratsimp(expand(%))
2
kg m
(%o21) 0 ` -----
2
s
EDIT. About converting kg*m/s^2 to N, you can apply the double back quote operator. For example:
(%i25) F_g `` N
690081645089888625
(%o25) ------------------ ` N
70368744177664
By the way, to convert back to floats, you can apply float:
(%i26) float(%)
(%o26) 9806.649999999998 ` N
Converting FN to N is a little more involved, since it's a more complex expression, especially because of H which doesn't have units attached to it yet. Some inspection seems to show the units of H must be kg*m/s^2. I'll apply declare_units to say that's what are the units of H. Then I'll convert FN to N.
(%i27) declare_units(H,(kg*m)/s^2)
kg m
(%o27) ----
2
s
(%i28) FN `` N
351843720888320 sqrt(3) qty(H)
(%o28) (-----------------------------------------
140737488355328 sqrt(3) + 351843720888320
3/2
1150136075149814375 3
+ -----------------------------------------) ` N
140737488355328 sqrt(3) + 351843720888320
(%i29) float(%)
(%o29) (1.023174629940149 qty(H) + 10033.91548470256) ` N
The notation qty(H) represents the unspecified quantity of H. One could also just subst(H = 100 ` kg*m/s^2, FN) (or any quantity, not just 100) and go from there.
Related
Hello I'm very new to maxima.
How could I have something like dot products noticed and simplfied?
Attempt 1:
tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));
Works for a[1]*b[1]+a[2]*b[2] but not v[1]*w[1]+v[2]*w[2] nor w[2]*v[2]+123+v[1]*w[1].
Attempt 2:
matchdeclare(a, lambda([x], length(x)=2));
matchdeclare(b, lambda([x], length(x)=2));
tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));
Doesn't even work for a[1]*b[1]+a[2]*b[2].
Here's a possible solution. Assuming that you know the names of the arrays, it's straightforward to extract the inner product. Then loop over that with all possible array names, as determined by looking at the subscripted variables in the expression.
/* solution for https://stackoverflow.com/questions/69673365/custom-simplification-rules */
/* try all combinations of potential arrays in succession */
contract_inner_products (e) :=
(for S in powerset (subscripted_variables(e), 2)
do block ([%xx: first(S), %yy: second(S)],
e: apply1 (e, rule_contract_inner_product)),
e);
/* extract potential arrays */
subscripted_variables (e) :=
setify (map (op, sublist (listofvars(e), subvarp)));
/* contract inner product, assuming arrays have been identified */
matchdeclare (aa, lambda([e], freeof(%xx, e) or freeof(%yy, e)),
bb, lambda([e], freeof(%xx, e) and freeof(%yy, e)),
xx, lambda([e], e = %xx), yy, lambda([e], e = %yy));
defrule (rule_contract_inner_product, aa + bb*xx[1]*yy[1] + bb*xx[2]*yy[2], aa + bb*dot(xx, yy));
Here are some examples.
(%i3) dotgh: g[1]*h[1] + g[2]*h[2] $
(%i4) dotab: a[1]*b[1] + a[2]*b[2] $
(%i5) dotxy: x[1]*y[1] + x[2]*y[2] $
(%i6) contract_inner_products (dotgh);
(%o6) dot(g, h)
(%i7) contract_inner_products (dotgh + dotxy);
(%o7) dot(x, y) + dot(g, h)
(%i8) contract_inner_products (dotgh - dotxy);
(%o8) dot(g, h) - dot(x, y)
(%i9) contract_inner_products (dotgh - 2*dotxy);
(%o9) dot(g, h) - 2 dot(x, y)
(%i10) contract_inner_products (n/2*dotgh - 2*dotxy);
dot(g, h) n
(%o10) ----------- - 2 dot(x, y)
2
(%i11) contract_inner_products (n/2*dotgh - 2*dotxy - 6*%pi^2);
dot(g, h) n 2
(%o11) (- 2 dot(x, y)) + ----------- - 6 %pi
2
It seems to work for stuff of the form dot(x, y) + dot(x, z).
(%i12) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2]);
(%o12) dot(g, h) + dot(f, g)
(%i13) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2] + 123);
(%o13) dot(g, h) + dot(f, g) + 123
(%i14) contract_inner_products (dotgh + g[1]*x[1] + g[2]*x[2] + 123);
(%o14) dot(g, x) + dot(g, h) + 123
(%i15) contract_inner_products (dotgh + h[1]*x[1] + h[2]*x[2] + 123);
(%o15) dot(h, x) + dot(g, h) + 123
I didn't really expect it to work for dot(x, y) + dot(x, z), but anyway that's great.
If you try it on other examples, you'll probably find some cases which this approach doesn't recognize.
EDIT: Note that it's not necessary for the would-be dot product to be at the top level of the expression. It looks for potential inner products in subexpressions, too.
(%i11) 1/(1 - dotab/4);
1
(%o11) -----------------
a b + a b
2 2 1 1
1 - -------------
4
(%i12) contract_inner_products(%);
1
(%o12) -------------
dot(a, b)
1 - ---------
4
(%i13) expand (%o11);
1
(%o13) ---------------------
a b a b
2 2 1 1
(- -----) - ----- + 1
4 4
(%i14) contract_inner_products(%);
1
(%o14) -------------
dot(a, b)
1 - ---------
4
I am calculating the following function's Laplace transform, but I get some strange output with limit and realpart etc on (%t5) and (%t6). What I expect is something like a_n = 0 and b_n = -1/(n*%pi).
Why is this happening? Am I defining the function at (%i1) incorrectly? Or is this a limitation of Maxima?
(%i1) f(t) := mod(t, 1);
(%o1) f(t) := mod(t, 1)
(%i2) plot2d(f(t), [t, -2, 2]);
(%o2) [/tmp/maxout1266174.gnuplot_pipes]
(%i3) load(fourie);
(%o3) /usr/share/maxima/5.43.0/share/calculus/fourie.mac
(%i4) fourier(f(t), t, 1);
1
(%t4) a = -
0 2
/
[
(%t5) a = limit I cos(%pi n t) realpart(floor(t)) dt
n t -> - 1 ]
/
/
[
- limit I cos(%pi n t) realpart(floor(t)) dt
t -> 1 ]
/
/
[
(%t6) b = (- limit I sin(%pi n t) realpart(floor(t)) dt)
n t -> 1 ]
/
/
[ 2 sin(%pi n) 2 cos(%pi n)
+ limit I sin(%pi n t) realpart(floor(t)) dt + ------------ - ------------
t -> - 1 ] 2 2 %pi n
/ %pi n
(%o6) [%t4, %t5, %t6]
(%i7)
newbie Maxima question
I have a transfer function in Maxima
E1 : y = K_i*s/(s^2 + w^2);
I'd like to have the closed-form of the equation affter applying the bilinear transform
E2 : s = (2/Ts*(z-1)/(z+1));
I would like to get the transfer function for z, by substituing s by equation E2. How should I proceed?
Regards
Note that subst can apply one or more substitutions stated as equations. In this case, try subst(E2, E1).
That will probably create a messy result -- you can simplify it somewhat by applying ratsimp to the result.
Here's what I get from that.
(%i2) E1 : y = K_i*s/(s^2 + w^2);
K_i s
(%o2) y = -------
2 2
w + s
(%i3) E2 : s = (2/Ts*(z-1)/(z+1));
2 (z - 1)
(%o3) s = ----------
Ts (z + 1)
(%i4) subst (E2, E1);
2 K_i (z - 1)
(%o4) y = ------------------------------
2
4 (z - 1) 2
Ts (z + 1) (------------ + w )
2 2
Ts (z + 1)
(%i5) ratsimp (%);
2
2 K_i Ts z - 2 K_i Ts
(%o5) y = -----------------------------------------------
2 2 2 2 2 2 2
(Ts w + 4) z + (2 Ts w - 8) z + Ts w + 4
(%i1) r: sqrt(x^2+y^2+z^2);
(r) sqrt(z^2+y^2+x^2)
(%i2) dx: diff(r,x);
(dx) x/sqrt(z^2+y^2+x^2)
I just show a simple code because my code is long and complex.
I want to simplify dx and get the result is x/r not x/sqrt(z^2+y^2+x^2).
However, I can't find the useful command.
Could somebody help me to solve this problem?
In this specific case, you can use subst, although ratsubst is probably useful in a greater number of cases.
(%i1) linel:65;
(%o1) 65
(%i2) r: sqrt(x^2+y^2+z^2);
2 2 2
(%o2) sqrt(z + y + x )
(%i3) diff (r, x);
x
(%o3) ------------------
2 2 2
sqrt(z + y + x )
(%i5) subst (r = 'r, %o3);
x
(%o5) -
r
(%i6) ratsubst ('r, r, %o3);
x
(%o6) -
r
Note that the single quote mark prevents evaluation, so that 'r is the symbol r instead of the value of r (namely sqrt(x^2 + y^2 + z^2)).
I'm trying to rearrange equation using maxima, but coefmatrix function does not work well with equation that has some division such as RL_parallel
I am getting all zeroes for the coefficients
RL_series: Rs + %i*w*Ls;
RL_parallel: ratsimp( 1 / [1/Rp + 1/(%i*w*Lp)] );
display2d : false $
eq : RL_series = RL_parallel $
vars : [Rs, Rp, Ls, Lp] $
coeffs : coefmatrix ([eq], vars);
coeffs . vars;
The main problem here is that the equation isn't linear in the variables specified, so extracting a coefficient matrix doesn't make any sense, unfortunately.
I am guessing that you want to solve the equation for vars. It seems to me that you'll need additional data, but it could well be that I'm missing something.
Here's what I get. Note that [ ... ] is a list; use ( ... ) for grouping expressions.
(%i1) RL_series: Rs + %i*w*Ls;
(%o1) %i Ls w + Rs
(%i2) RL_parallel: ratsimp( 1 / (1/Rp + 1/(%i*w*Lp)) );
Lp Rp w
(%o2) ------------
Lp w - %i Rp
(%i3) eq : RL_series = RL_parallel;
Lp Rp w
(%o3) %i Ls w + Rs = ------------
Lp w - %i Rp
(%i4) vars : [Rs, Rp, Ls, Lp];
(%o4) [Rs, Rp, Ls, Lp]
(%i5) denom(rhs(eq)) * eq;
(%o5) (Lp w - %i Rp) (%i Ls w + Rs) = Lp Rp w
(%i6) expand (%);
2
(%o6) %i Lp Ls w + Lp Rs w + Ls Rp w - %i Rp Rs = Lp Rp w
Assuming that vars are real, we can separate the real and imaginary parts of the equation.
(%i7) [realpart(%), imagpart(%)];
2
(%o7) [Lp Rs w + Ls Rp w = Lp Rp w, Lp Ls w - Rp Rs = 0]
(%i8) first(%) / (Lp*Rp*w);
Lp Rs w + Ls Rp w
(%o8) ----------------- = 1
Lp Rp w
(%i9) expand (%);
Rs Ls
(%o9) -- + -- = 1
Rp Lp
So one of the equations has a product Xs*Xp and the other has the ratio Xs/Xp. Maybe that helps direct the search for additional data.
At this point I don't know what more can be said. If anyone can comment on this point I would be interested to hear it.
EDIT: OP says that the goal is to solve for Rp and Lp in terms of Rs and Ls. Given that, we can solve the two equations we obtained in %o7.
(%i10) %o7[2];
2
(%o10) Lp Ls w - Rp Rs = 0
(%i11) solve ([%o9, %o10], [Rp, Lp]);
2 2 2 2 2 2
Ls w + Rs Ls w + Rs
(%o11) [[Rp = ------------, Lp = ------------], [Rp = 0, Lp = 0]]
Rs 2
Ls w
(%i12) subst (%o11[1], [%o9, %o10]);
2 2 2
Ls w Rs
(%o12) [------------ + ------------ = 1, 0 = 0]
2 2 2 2 2 2
Ls w + Rs Ls w + Rs
(%i13) ratsimp(%);
(%o13) [1 = 1, 0 = 0]