# NSolve super slow for a parameter scan

I am using NSolve to solve two equations for two variables while scanning through several values of angles. The strange thing is that when I manual enter a value for the angle and Nsolve the answer is instantly found. But, when I scan through a bunch of angles it takes forever (/.theta->{0.1,0.2,0.3,0.4,0.5...etc})

SLOW:

be[theta_,
r_] := {{Cos[theta], r*Sin[theta], 0, 0, 0,
r (1 - Cos[theta])}, {-1/r Sin[theta], Cos[theta], 0, 0, 0,
Sin[theta]}, {0, 0, 1, r*theta, 0, 0}, {0, 0, 0, 1, 0,
0}, {-Sin[theta], -r*(1 - Cos[theta]), 0, 0,
1, -r*(theta - Sin[theta])}, {0, 0, 0, 0, 0, 1}}
ed[theta_,
r_] := {{1, 0, 0, 0, 0, 0}, {1/r Tan[theta], 1, 0, 0, 0, 0}, {0, 0,
1, 0, 0, 0}, {0, 0, -1/r Tan[theta], 1, 0, 0}, {0, 0, 0, 0, 1,
0}, {0, 0, 0, 0, 0, 1}}
dr[x_] := {{1, x, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {0, 0, 1, x, 0,
0}, {0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1}}

lb1 = 0.2;
lb2 = 0.2;
theta1 = 0.16683602;
theta2 = 0.063;
(*theta3=0.043;*)
r1 = lb1/theta1;
r2 = lb1/theta2;
r3 = lb2/(theta2 + theta3);
r4 = lb2/theta3;

system =
be[theta3, r4].ed[theta3, r4].dr[
g].ed[-theta3, -r3].be[-theta2 -
theta3, -r3].ed[-theta2, -r3].dr[f].ed[theta2, r2].be[
theta2, r2].dr[1.0926].be[theta1, r1].ed[theta1, r1].dr[
d].ed[-theta1, -r1].be[-theta1, -r1];

Dis = system[[1, 6]];
Com = system[[5, 6]];

g = 2.5;
NSolve[{Dis == 0, Com == 0.025}, {d, f}]/.theta3 -> {0.01, 0.02}


FAST:

be[theta_,
r_] := {{Cos[theta], r*Sin[theta], 0, 0, 0,
r (1 - Cos[theta])}, {-1/r Sin[theta], Cos[theta], 0, 0, 0,
Sin[theta]}, {0, 0, 1, r*theta, 0, 0}, {0, 0, 0, 1, 0,
0}, {-Sin[theta], -r*(1 - Cos[theta]), 0, 0,
1, -r*(theta - Sin[theta])}, {0, 0, 0, 0, 0, 1}}
ed[theta_,
r_] := {{1, 0, 0, 0, 0, 0}, {1/r Tan[theta], 1, 0, 0, 0, 0}, {0, 0,
1, 0, 0, 0}, {0, 0, -1/r Tan[theta], 1, 0, 0}, {0, 0, 0, 0, 1,
0}, {0, 0, 0, 0, 0, 1}}
dr[x_] := {{1, x, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {0, 0, 1, x, 0,
0}, {0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1}}

lb1 = 0.2;
lb2 = 0.2;
theta1 = 0.16683602;
theta2 = 0.063;
(*theta3=0.043;*)
r1 = lb1/theta1;
r2 = lb1/theta2;
r3 = lb2/(theta2 + theta3);
r4 = lb2/theta3;

system =
be[theta3, r4].ed[theta3, r4].dr[
g].ed[-theta3, -r3].be[-theta2 -
theta3, -r3].ed[-theta2, -r3].dr[f].ed[theta2, r2].be[
theta2, r2].dr[1.0926].be[theta1, r1].ed[theta1, r1].dr[
d].ed[-theta1, -r1].be[-theta1, -r1];

Dis = system[[1, 6]];
Com = system[[5, 6]];

g = 2.5;
theta3=0.01;
NSolve[{Dis == 0, Com == 0.025}, {d, f}]


The reason your first block of code doesn't work is that you make the replacement for theta3 after invoking NSolve on the system of equations. At the time it is invoked, the system of equations doesn't have a numerical value for theta3 to work with.

So you simply have to change the last line as follows (copying the whole first code block for consistency):

Clear[theta3]

be[theta_,
r_] := {{Cos[theta], r*Sin[theta], 0, 0, 0,
r (1 - Cos[theta])}, {-1/r Sin[theta], Cos[theta], 0, 0, 0,
Sin[theta]}, {0, 0, 1, r*theta, 0, 0}, {0, 0, 0, 1, 0,
0}, {-Sin[theta], -r*(1 - Cos[theta]), 0, 0,
1, -r*(theta - Sin[theta])}, {0, 0, 0, 0, 0, 1}}
ed[theta_,
r_] := {{1, 0, 0, 0, 0, 0}, {1/r Tan[theta], 1, 0, 0, 0, 0}, {0, 0,
1, 0, 0, 0}, {0, 0, -1/r Tan[theta], 1, 0, 0}, {0, 0, 0, 0, 1,
0}, {0, 0, 0, 0, 0, 1}}
dr[x_] := {{1, x, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {0, 0, 1, x, 0,
0}, {0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1}}

lb1 = 0.2;
lb2 = 0.2;
theta1 = 0.16683602;
theta2 = 0.063;
(*theta3=0.043;*)
r1 = lb1/theta1;
r2 = lb1/theta2;
r3 = lb2/(theta2 + theta3);
r4 = lb2/theta3;

system = be[theta3, r4].ed[theta3, r4].dr[
g].ed[-theta3, -r3].be[-theta2 - theta3, -r3].ed[-theta2, -r3].dr[
f].ed[theta2, r2].be[theta2, r2].dr[1.0926].be[theta1, r1].ed[
theta1, r1].dr[d].ed[-theta1, -r1].be[-theta1, -r1];

Dis = system[[1, 6]];
Com = system[[5, 6]];

g = 2.5;
Table[NSolve[{Dis == 0, Com == 0.025} /. theta3 -> angle, {d,
f}], {angle, {0.01, 0.02}}]

(*
==> {{{d -> 0.446548, f -> 1.96807}}, {{d -> 0.383928,
f -> 2.2263}}}
*)


Here I replaced your last line by a Table that runs over the desired values and makes the replacements in the equations inside NSolve. This runs very fast, just like your second code block.

• Hi Jens, thank so much, but I want the answer to be outputted like: d->{1,2,3,4,5}, f->{1,2,3,4,5}....This is how the output would be for a non-trig equation solving. Any ideas? Commented Oct 4, 2014 at 8:45
• That just requires some reshaping of the result. E.g., if the output from above is called ans, then one could do Thread[{d,f}->({d,f}/.Flatten[ans,1])] (where Thread adds the Rule arrow to each list of d and f values, resp.
– Jens
Commented Oct 4, 2014 at 16:01
• Whenever I try to scan more than two values for theta3 I get the error:"Objects of unequal length in {d,f}->" Any help? I have about sixty values to scan... Commented Oct 5, 2014 at 8:16