I have written some Python code to determine the numerical roots of the following non-linear equation: $$f_m=\tan\lambda_m - \frac{\lambda_m}{1+a}$$ where $\lambda_m\gt0$ and $a\geq0$. The code is:
import numpy as np
from scipy.optimize import root
func = lambda λm, a: np.tan(λm) - λm/(1+a)
λm0 = np.linspace(np.pi, m*np.pi, m) # initial guess
sol = root(func, λm0, args=(a), method='lm') # least-square optimization
This works fine, e.g. for input $m, a = 3, 1$ the result is: $$\lambda_m=[4.27478227, 7.59654602, 10.81267333]$$ which are the roots to $f_m=0$ for $m=1,2,3$ as can be checked easily.
As a next step, I would like to provide the Jacobian, which i think should be: $$J_{m,n}=\frac{\partial f_{m}}{\partial\lambda_{n}}=\begin{cases} \frac{1}{\cos^2\lambda_{m}}-\frac{1}{1+a} & m=n\\ 0 & m\neq n \end{cases}$$ i.e. in matrix-form with the above values for $\lambda_m$: $$\boldsymbol{J}=\begin{bmatrix} 5.06844087 & 0 & 0\\ 0 & 14.92687786 & 0\\ 0 & 0 & 29.72847616 \end{bmatrix}$$
However, the approximated Jacobian being output by the optimization routine is: $$\boldsymbol{\tilde{J}}=\begin{bmatrix} -29.72850523 & 0 & 1\\ 0 & -14.92688569 & 0\\ 0 & 0 & 5.06844398 \end{bmatrix}$$
Clearly the magnitudes of approximated derivatives on the diagonal correspond to my analytical values for the Jacobian, but the order of the values is somehow different (running backwards from $n=3,2,1$) and some of the values are negative. Furthermore, an additional $\tilde{J}_{1,3}=1$ is present (more of these spurious ones seem to appear as $n$ grows) which shouldn't be present.
Can someone explain the differences between the approximate and analytical Jacobian?
brentq(f, (k - 0.5)*pi + 1e-8, (k + 0.5)*pi - 1e-8)
), and it computed the first 1000 roots in 25ms. This seems to work up to $k\leq 10^7$, but you could probably come up with a better bracket with a little more work. $\endgroup$