Halfway symbolic halfway numeric evaluation on wxMAXIMA
Subject: Halfway symbolic halfway numeric evaluation on wxMAXIMA
From: Rupert Swarbrick
Date: Wed, 17 Apr 2013 13:48:05 +0100
Berns Buenaobra <berns.buenaobra at gmail.com> writes:
> Hello members:
>
> I have just recently adapted MAXIMA in my teaching for science education
> and physics majors in class - the symbolic math is key and the biggest
> motivator for students to have computer aided solution (to augment the
> previous class training on long hand calculus and ODE etc.).
>
> It seemed that when I started using real values on the my sheet towards the
> of end of my worksheet the earlier cells simply adapted and lost all my
> symbols and computed numerically? Is the effect of say having assigned a
> value to a symbol say R:100, C:100e-6, L:35e-3 (from a problem in network
> analysis) global?
Stavros has suggested one sensible approach. Another approach is not to
bind R, C, L at all. Something like this:
my_scary_formula: V = V0 * exp(-R*C*t);
example1_vars: [R=100, C=100e-6, L=35e-3];
example1_instance: subst(example1_vars, my_scary_formula);
Then you can fiddle with the example1_vars list and update the formulas
that depend on it. As with Stavros, I don't actually use wxMaxima, but I
guess that this method will work perfectly well there.
I find that I very rarely bind the "mathematical variables" like R,C,L
and instead end up bind names for expressions using them
(my_scary_formula etc.)
I wonder if anyone else on the list has neat tricks for the problem of
distinguishing general formulas from their specific instances?
Rupert
PS: I'm attaching an example of a calculation I did reasonably recently
in case it gives you ideas. I've not cleaned it up at all, so if
something looks weird... it's probably wrong! I'm actually
calculating how big / stiff a spring I need for a personal DIY
project, in case you're wondering. General equations are things like
eq_moment, eq_x etc. Then it looks like I substitute in for things
like num_theta, num_W etc. Note I have lists of numerical constants
in the variable "measurements".
PPS: If anyone is wondering why I used but_nth and sub_from_nth rather
than just using eliminate, so am I... I think it was because I
wanted to control which formula got used or something. It's all a
little hazy!
-------------- next part --------------
load(ezunits)$
load(quadratic)$
/*
Assuming that the weight of the support structure is negligible, you
end up with tension
Start with two parallel rods of length l hanging off a
wall. Attached to them is a drill, with weight W, centre of gravity
unspecified (since it doesn't matter. Keeping the whole thing up is
a compression spring attached to the wall and lower rod a distance a
from the hinge. Write F for the force from the spring. Write theta
for the acute angle between the rod and the wall.
Write L for the resolved force perpendicular to the rods that the
lower hinge exerts on the drill. Resolving in this direction for the
translation of the drill, notice that the upper rod only exerts a
force parallel to the rods. As such, we have the simple equation:
L = W * sin(theta)
Now take moments of forces on the lower rod about the other
hinge. You get
l * L = a * F * sin(gamma)
where gamma is the angle between the rod and the spring. The
triangle created by the spring is isoceles and a quick check shows
that sin(gamma) = cos(theta/2). So:
*/
eq_moment: l*W*sin(theta) = a*F*cos(theta/2);
/*
And the cosine rule gives a calculation of x in terms of a,b and
theta.
*/
eq_x: x = a*sqrt(2 - 2*cos(theta));
/*
Hooke's law gives an expression for F in terms of x,s,k.
*/
eq_hooke: F = (s-x)*k;
initial_eqs: [eq_moment, eq_x, eq_hooke];
/*
We want to try and find the correct a for a given spring, so eliminate
psi, F, x
*/
but_nth (n, lst) :=
block([i: 0, acc: []],
for x in lst do if not((i: i+1) = n) then acc: cons(x, acc),
reverse (acc))$
sub_from_nth (n, solve_for, eqns) :=
block([sym: if atom(solve_for) then solve_for else gensym(), solns],
solns: solve(subst(sym, solve_for, eqns[n]), sym),
if not (length (solns) = 1) then
error ("Complicated solution set: ", solns),
subst (first (solns), subst(sym, solve_for, but_nth(n, eqns))))$
assume(a>0);
eqs2: sub_from_nth (2, x, initial_eqs);
eqs3: sub_from_nth (1, F, eqs2);
eq_for_a: first(eqs3);
/*
Naively, We get two solutions because if you jam the thing really
close to the pivot (and assume that everything stays elastic) then
the force will be massive, but the mechanical advantage will be
terrible, and they will cancel each other out. To ignore that
solution, use the quadratic formula to solve the equation by hand.
*/
assume (W >= 0);
assume (k > 0);
assume (theta < %pi/2);
assume (cos(theta/2) >= 0);
assume (x > 0);
eq_a_analysis: analyse_quadratic (eq_for_a, a);
eq_a:
(if not (assoc (solorder, eq_a_analysis) = true) then
error ("Unknown solution order"),
a = second(assoc (solutions, eq_a_analysis)));
/* ***************** */
/*
Some actual numerics (I know theta, F2 etc.)
I have a drill of length h connected below the end of the rod and
want to have a default clearance of c above the floor. The pivot
is a distance H above the floor.
*/
clearance_expr: H - h - cos(theta)*l = c;
eq_theta: first(solve(clearance_expr, theta));
measurements: [H = 19`cm, h = 12`cm, c = 3`cm, l=21`cm];
num_theta: rhs(expand(subst(measurements, eq_theta)));
/*
Suppose that the drill has a mass of 750g.
*/
num_W: (0.75`kg) * (9.8`N/kg);
first_expansion (x) :=
subst(ev(append ([theta = num_theta, W = num_W],
measurements),
numer), x)$
/* ***************** */
ineq_discriminant: assoc (discriminant, eq_a_analysis) > 0;
num_ineq_discriminant: first_expansion (ineq_discriminant);
/* Inputting a metric spring */
Nmm_spring (k, rest_len, max_load, min_len) :=
[spring, 'k = (k`N/mm``N/cm),
's = (rest_len`mm``cm),
'min_len = (min_len`mm``cm),
'max_load = (max_load`N)]$
spring_calculate_a (spring) :=
(if not (qty (subst (rest (spring), num_ineq_discriminant))) then
error ("No solution for the spring ", spring),
rhs (subst (rest (spring), first_expansion (eq_a))))$
spring_calculate_F (spring, a) :=
block([Feq:
first_expansion (
first (solve (first (eliminate([eq_hooke, eq_x], ['x])),
F)))],
subst (['a = a,
's = assoc('s, rest (spring)),
'k = assoc('k, rest (spring))],
rhs (Feq)))$
spring_calculate_min_theta (spring, a) :=
acos(subst(['x = assoc ('min_len, rest (spring)), 'a = a],
rhs (first (solve (eq_x, cos(theta))))));
spring_downwards_movement (spring, a) :=
first_expansion (l*(cos(spring_calculate_min_theta (spring, a)) -
cos(theta)))$
spring_calculate (spring) :=
block([a: spring_calculate_a (spring), x, s, F, travel],
x: subst ('a = a, first_expansion (rhs (eq_x))) `` cm,
s: assoc ('s, rest (spring)) `` cm,
min_len: assoc (min_len, rest (spring)) `` cm,
if is (qty (x) > qty (s)) then
error ("Spring not in compression (", x > s),
if is (qty (x) < qty (min_len)) then
error ("Spring too compressed (", x < min_len),
F: spring_calculate_F (spring, a),
travel: spring_downwards_movement (spring, a),
['a = a, 'x = x, 'F = F, 'travel = travel])$
/* RS!
121-220 ?8.92 for 10
(%i80) spring_calculate(Nmm_spring (4.04, 53.5, 100, 21.5))
(%o80) [a = 2.87631603480254 ` cm, x = 3.65987635551046 ` cm,
F = 68.28099523737744 ` N, travel = 11.13331170542237 ` cm]
*/
1;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 315 bytes
Desc: not available
URL: <http://www.math.utexas.edu/pipermail/maxima/attachments/20130417/f9ed0af6/attachment-0001.pgp>