Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation for derivatives #94

Closed
Mv77 opened this issue Jul 9, 2022 · 9 comments
Closed

Documentation for derivatives #94

Mv77 opened this issue Jul 9, 2022 · 9 comments

Comments

@Mv77
Copy link
Contributor

Mv77 commented Jul 9, 2022

Hi,

I've recently been working on wrappers for this repos' interpolators in HARK.

I now want to add the capability of computing derivatives. I have been trying to figure out how to use the derivatives in eval_splines from your test files. I've now run into a question I can't resolve and I was hoping you could provide some guidance.

Consider the following example, which calculates the 0-1-2 order derivatives of f(x) = 2 + 1*x at some points (1.5, 2.5, 3.5, 4.5):

x = np.linspace(0,10,6)
y = 2 + 1.0 * x

grad = eval_spline(
    UCGrid(x),
     y,
     np.array([1.5,2.5,3.5,4.5])[...,None],
     out=None,
     order=1,
     diff=str(((0,), (1,), (2,))),
     extrap_mode="linear"
)

The output is

array([[3.5, 4. , 0. ],
       [4.5, 4. , 0. ],
       [5.5, 4. , 0. ],
       [6.5, 4. , 0. ]])

Which has some properties of the right solution: the first and third column are right, and the second column rightly is a constant. But, in the second column, I'd expect the first order derivative which should be 1.0.

Could you help me figure out if there is something I am misinterpreting?

@aniecon
Copy link

aniecon commented Jul 22, 2022

Hi Mateo, I tried this as well. And it gave me the correct first derivative only when the grid was set to x = np.linspace(1.5,4.5,4).

@llorracc
Copy link

Pablo,

Some context for this: We've embarked on a goal of wiring your interpolation.py into the core of HARK, but can't do that until we figure out this issue. It sure looks like a bug to me; or, if not a bug, then probably there is some place where the documentation should be improved. Is there someone on your team who can look at this, maybe with collaboration/help from @Mv77 and/or @alanlujan91

@albop
Copy link
Member

albop commented Jul 22, 2022 via email

@albop
Copy link
Member

albop commented Jul 27, 2022

Indeed, there was a bug with the evaluation of derivatives for linear interpolators.
I have pushed a fix in master. It should in principle work for uniform and nonuniform grids.

@Mv77 or @aniecon : can you check it works as you expect ? Would you submit a test file ? In principle, it should work for regular and irregular grids, linear and cubic splines. When we are sure it works we can add it to the doc.

NB: a grid is represented as a tuple of 1d grid. A 1d grid can itself be regular, it which case it is given by (min, max, n) or irregular in which case it must be a numpy vector of increasing coordintates. In your example, there is a hidden bug: UCGrid should not accept x as argument. Instead, you should do UCGrid( (0.,10.,11) ) which leads to faster interpolation. And to construct nonuniform grid CGrid( x ) (then x can be either a vector or a min,max,n, tuple). I have pushed another little change so that CGrid, and UCGrid actually do some type check (in the long run my intention was to use python type system for that but so far it will do).

NB2: to debug I used the call code = (get_code_spline(1,1,False,True,allocate=True,extrap_mode="linear", orders=((0,), (1,), (2,)))) to see what code had been generated and noticed 1.0*δ_0 instead of 1.0/δ_0 in the derivative of the basis functions.

@Mv77
Copy link
Contributor Author

Mv77 commented Jul 27, 2022

@albop thank you for the fix and for the tips.

I'd be happy to create a test file. I'll submit a PR in the next few days and confirm that it works.

@Mv77
Copy link
Contributor Author

Mv77 commented Jul 30, 2022

@albop I'm already working on tests and should have a PR soon. It's looking good. Thank you!

Just a question: I am using order=1 interpolators. First order derivatives look right. Second order derivatives are always coming out as 0. Just wanted to check that this is expected behavior (second derivative of a linear function), and that the interpolators are not expected to get a 2nd order derivative from some other numerical approach.

@llorracc
Copy link

llorracc commented Jul 30, 2022 via email

@albop
Copy link
Member

albop commented Aug 6, 2022 via email

@llorracc
Copy link

llorracc commented Aug 6, 2022

So linear splines are differentiable everywhere from the right,
but not differentiable from the left at the knots points. This is actually
the expected mathematical result

That's surprising to me. It seems as though it should either be defined both from right and from left with slopes of the corresponding segments, or be undefined from either direction because it is undefined exactly at the knot.

If you do not specify the direction you are coming from, I guess it returns the derivative from the right? To prevent code from breaking when people use it without thinking about the knots point?

In practice, because actual kink points can be so ornery, it has occurred to me to handle this by adding two points to the grid symmetrically slightly to the left and slightly to the right, and connecting them with the unique quadratic that matches the (well-defined) slopes at the left and right. This would yield a function that was differentiable everywhere, and that would preserve the concavity (or convexity) of the function; and with the disadvantage that the quadratic would not yield exactly the right answer exactly at the kink point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants