Given values for the variables s
, v
, and h
, and given a library such as numeric.js how can I numerically solve the following equation for a
within a given degree of accuracy?
I'm wanting a JS algorithm for use in-browser.
Given values for the variables s
, v
, and h
, and given a library such as numeric.js how can I numerically solve the following equation for a
within a given degree of accuracy?
I'm wanting a JS algorithm for use in-browser.
Separating variables and parameters
You could start by substituting b = a/h. That would turn your equation into
That way you have all the inputs on the right hand side, and the variable on the left hand side, but unfortunately still occuring in several places in a transcendental form. The benefit is that we can now treat the right-hand side as a single number in order to gain some understanding of this function.
First look at a plot
The function seems reasonably well-behaved:
So you can do standard numerical root-finding methods, e.g. Newton's method, to find the position where this function takes a given value (i.e. the one you computed from the right-hand side). If you interpret root-finding as finding locations where a function is zero, then the function for which you want to find zeros is the difference, i.e.
Using optimization from numeric.js
If you want to make use of numeric.js,
numeric.uncmin
would likely be your best bet. At least it's the best I could find in the docs so far. (Perhaps there is some bare root-finding implementation in there, but if so, I couldn't find it yet.) You'd try to find the minimum of the functioninterpreted as a function of a, and hope that that minimum is actually (close to) zero. You might get better results (i.e. faster convergence and/or lower error) by also providing the gradient (derivative) of that function as a separate argument. You can use Wolfram Alpha to find that derivative.
Further rewriting of the function
Let's define f as f(b) = 2b*sinh(1/(2b)). You are trying to find out at what position f assumes a given value. In order to make convergence faster, you can try to turn this f into a different function which will be close to linear. Toying around with plots, I've come up with this:
You can apply the same conversion to the right hand side to see the desired value for this function. For b > 0.06 this looks fairly linear, so it should converge really fast. Provided your parameters are expected to be in that range where it is almost linear, but even for smaller b it should be no worse than the original formulation. You could use the linear form to compute the starting position of your Newton's method, but I wouldn't bother: as long as you start with a reasonably big value, the first step of Newton's method will do just that.
this is transcendent equation
I assume real domain in that case you can not separate the unknown from it (in general) instead you still can solve it numerically (as you intended)
I am too lazy to do proper analysis of
2a.sinh(h/2a)=sqrt(s.s-v.v)
but if I see it right then
2a.sinh(h/2a)
is monotone so letc=sqrt(s.s-v.v)
for simplicity and speed up. As I see itc >= 0
so ifh >= 0
thena = <0,+inf)
find value crossing
now
a1
holds approximate top bound solutionnow
a0
holds approximate low bound solutionfind solution in desired accuracy
if
a0==a1
then you have found exact solution so stopif
fabs(a1-a0)<=accuracy
you are inside your accuracy so stop and lower theda
for exampleda*=0.01;
this will boost accuracy100
times. Now search for solution again but only on interval<a0,a1>
and repeat this until solution is found[notes]
Another example of solution of transcendent equation is here: solving Kepler`s equation. When nothing else works you still can try this: