> 
expr:=tan(theta_n)  C_a*Z_0*(v^2*(Pi*ntheta_n)^2/x_l^2 +omega_a^2)*x_l/(v*(Pi*ntheta_n)):

> 
Equate([omega_a,v,x_l,C_a,Z_0],[100e9, 1e8, 0.3, 20e14, 50.0]): ee:=simplify(eval(expr,%));

2 0.003333333333 (Pi n  theta_n)  300.0000000 ee := tan(theta_n) +  Pi n  theta_n
> 
# We hope that this provides a contraction mapping which # converges quickly: ff:=simplify(map(arctan,op(1,ee)=op(2..1,ee))) assuming theta_n>Pi/2, theta_n<Pi/2;

/ 2 \ 0.003333333333 (Pi n  theta_n)  300.0000000 ff := theta_n = arctan \ Pi n  theta_n /
> 
F:=N>unapply(eval(evalf(rhs(ff)),n=N),theta_n,proc_options=[hfloat]):

> 
# Applying F to n produces a procedure, which we can # iterate at initial values of theta_n. F(117);

proc(theta_n) option hfloat; 1.*arctan((0.003333333333*(%1)^2  300.0000000)/(%1)) end proc; %1 := 367.5663405  1.*theta_n
> 
# For most all initial theta_n, F(117) converges in a # small number of iterations. It might be that 10 iterations # is enough, in general. seq( (F(117)@@i)(11.0), i=0..10 );

11.0, 0.334174918606374, 0.389865087453356, 0.390129467304736, 0.390130722191024, 0.390130728147372, 0.390130728175643, 0.390130728175778, 0.390130728175778, 0.390130728175778, 0.390130728175778
> 
# Let's see whether many initial guesses converge to the same value # after 10 iterations. plot( (F(117)@@10), 0.1..11.0 );

> 
# Let's always use 1.0 as the initial theta_n guess, and produce a # plot for various values of n. forget(evalf): CodeTools:Usage( plot( '(F(n)@@10)(1.0)', n=1..1000) );

memory used=6.09MiB, alloc change=0 bytes, cpu time=151.00ms, real time=146.00ms, gc time=0ns
> 
restart: # Now lets put it into a procedure.

> 
new_get_theta_n_array:=proc(max_n::integer, omega_a::float, v::float, x_l::float, C_a::float, Z_0::float)

> 
local ff, F, theta_n_array; ff:=simplify(expand(arctan(C_a*Z_0*(v^2*(Pi*ntheta_n)^2 /x_l^2+omega_a^2)*x_l/(v*(Pi*ntheta_n))))); F:=N>unapply(eval(evalf(ff),n=N),'theta_n',proc_options=[hfloat]); # Here we always start iterating from guess theta_n=1.0, but # it might be even faster to start iterating from the previous # n's final iterate. If we keep it as is, though, we could Thread:Task # this action and split across all the values of n to be computed. # Also, if convergence were ever slow then we could consider making # the number of iterations ba according to some additional proc argument # rather than fixed at 10 iterations. theta_n_array:=Array([seq( '(F(n)@@10)(1.0)', n=1..1000 )],datatype=float[8]); if ArrayNumElems(theta_n_array) <> max_n then

> 
printf("Bad Array Dimensions! Got too many or not enough solutions.");

> 
theta_n_array:="CHECK: get_theta_n_array()":

> 
CodeTools:Usage( new_get_theta_n_array(1000,100e9,1e8,0.3,20e14,50.0) ):

memory used=9.21MiB, alloc change=32.00MiB, cpu time=151.00ms, real time=158.00ms, gc time=20.00ms
> 
get_theta_n_array:=proc(max_n::integer, omega_a::float, v::float, x_l::float, C_a::float, Z_0::float)

> 
local theta_n_array:=Array(

> 
select(x>Re(x)<evalf(Pi/2) and Re(x)>=evalf(Pi/2), [seq(

> 
#NOTE: careful with fsolve  in some cases returns # unevaluated equation

> 
fsolve(tan(theta_n)  C_a*Z_0*(v^2*(Pi*ntheta_n)^2 /x_l^2+omega_a^2)*x_l/(v*(Pi*ntheta_n)), theta_n) , n=1..max_n)]

> 
if ArrayNumElems(theta_n_array) <> max_n then

> 
printf("Bad Array Dimensions! Got too many or not enough solutions.");

> 
theta_n_array:="CHECK: get_theta_n_array()":

> 
ans:=CodeTools:Usage( get_theta_n_array(1000,100e9,1e8,0.3,20e14,50.0) ):

memory used=308.13MiB, alloc change=117.85MiB, cpu time=5.28s, real time=5.28s, gc time=130.00ms
