solving a trig equation numerically with in-browse

2019-07-07 17:16发布

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?

singular transcendental trig equation

I'm wanting a JS algorithm for use in-browser.

2条回答
再贱就再见
2楼-- · 2019-07-07 18:04

Separating variables and parameters

You could start by substituting b = a/h. That would turn your equation into

2b*sinh(1/(2b)) = sqrt(s²-v²)/h

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:

Plot of the function

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.

2a*sinh(h/(2a)) - sqrt(s²-v²)

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 function

(2a*sinh(h/(2a)) - sqrt(s²-v²))²

interpreted 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:

g(b) = (f(b) - 1)^(-1/2)

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.

Plot of g

查看更多
成全新的幸福
3楼-- · 2019-07-07 18:10
  1. 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)

  2. 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 let c=sqrt(s.s-v.v) for simplicity and speed up. As I see it c >= 0 so if h >= 0 then a = <0,+inf)

  3. find value crossing

    double a0,a1,da=initial accuracy step;
    for (a1=0.0;2a.sinh(h/2a)<=sqrt(s.s-v.v);a1+=da);
    

    now a1 holds approximate top bound solution

    for (a0=a1;2a.sinh(h/2a)>sqrt(s.s-v.v);a0-=da);
    

    now a0 holds approximate low bound solution

  4. find solution in desired accuracy


    if a0==a1 then you have found exact solution so stop
    if fabs(a1-a0)<=accuracy you are inside your accuracy so stop and lower the da for example da*=0.01; this will boost accuracy 100 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:

查看更多
登录 后发表回答