-
Notifications
You must be signed in to change notification settings - Fork 109
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
More boundary conditions for quadratic B-splines #9
Conversation
Unless I'm confused, I get that the "edge" equation is |
Hm, I meant to say y1=A[1], but I'm still missing the second term so that may very well be it. I'll try it out when I've recharged my laptop :p |
Nope, that didn't work either. I'm thinking maybe we're overlooking something here... I wrote a small latex document outlining the math behind what I've tried - I'd be very grateful if you had time to look at it and see if I'm overlooking something fundamental. |
I'll definitely try to take a look. Your formula is the right one; I had the sign of It occurs to me that the source of the problem might be that you want to constrain the slope of the interpolated function, and that |
To make this even more complicated, I just reminded myself about our discussion about on-grid/on-cell interpolations; the governing equations for these things will of course need to be different depending on which type we're talking about. I've started patching up the work I've already committed to take this into account, using the following assumptions and consequences:
Following from definition 3, we should specify the boundary conditions for From 4, we can also conclude that we don't need to worry too much about where the implementation makes the switch between cells inside the domain, as long as we get the boundary conditions and extrapolation behavior correct under both grid representations, it's perfectly fine e.g. for So the code I've shown here is really only valid for |
OK, I looked at this a bit. I think we have to introduce two ghost points, at 0 and -1, because the interpolating function is quadratic and so we have two equations to solve: one that the coefficient of the quadratic component is zero (gives linear behavior), and the other that the slope matches the slope we want. If you have a PDF document I believe I sent quite some months ago, this refers to Eqs. 1 and 7-10 (if I didn't edit the document in the meantime 😄). The equation I get for the vanishing of the quadratic term (on the interval from -0.5 to 0.5) is |
There is another way too: just introduce one equation, that specifies that the quadratic component vanishes, and then use whatever slope that turns out to be for the linear extrapolation (i.e. the linear term at the edge determines the slope of the extrapolation). I'm not sure which I think is more correct (or useful). |
I like the "free floating" slope version, because you can use a grid of the same size as the original array. If you use my version, it seems that technically |
I think I like the free slope better too, given that I can figure out how to evaluate it ;) But setting the quadratic term to 0 is a good first step; for |
I haven't read up on your math about Bottom line, I suspect that you should insist that all "control points" are on the unit grid. Define the extrapolation function |
Yeah, I thought some more about it and realized that the discrete 2nd derivative on And for future reference, I put a link to the most relevant (although already slightly outdated) notebook in the readme =) |
Thanks for the link. |
787ac62
to
30b598d
Compare
The extra equations from the boundary conditions will not always allow indexing as we did before, by e.g. doing cm_d = cp_d at the lower boundary for some BC:s. In order to generalize better, we instead pad the equation system with one line for each extra equation to allow more general BC specs. This had the advantage of significantly simplifying some of the code (and, even better, some of the concepts) required to implement new functionality, so even though some of the underlying infrastructure is now more complicated than before, new contributors will hopefully have a lower threshold to start adding features.
30b598d
to
61aab26
Compare
I feel this is merge-ready now, although there are still a couple of issues that I thought this would resolve when I started working on this PR. Most notably, the linear extrapolation doesn't work at all, because it gets its slope from some mathematically insane assumption. However, since I want to implement gradient and Hessian evaluation anyway, I figured it could wait until I can just do Also, there are a couple of other BC:s that aren't implemented yet, but the infrastructure changes here do make that stuff somewhat easier to deal with, so I feel it's better to merge this and start working on those separately. There is quite possible some performance loss here, because the most significant change I've done is to introduce padding for all BC:s for quadratic interpolations. The rationale behind that is that I wanted to get away from the voodoo surrounding interpolation evaluation close to the boundary that we had before with the |
I got the periodic BC/extrapolation working too =) Also, I have had a notebook with some Gadfly plots of the various configuraitons as a sanity check I figured I could just as well share it: here. Once it's merged, I'll link to it from the readme as well. (And all the code it runs is under As you can see in the notebook, everything seems to work well except linear extrapolation, which - as noted above - I'll fix when |
I am not worried about the copy/padding operation; compared to solving the system of equations along slices, it will be trivial (for anything higher than 1d). However, right now the implementation of the filtering is sure to be very slow. I'd say, get started with a slow implementation and I'll try to write a standalone package to handle this step (I haven't had time to start it, however). |
One really good way to debug 2d problems is to make one of the dimensions constant, i.e., just duplicate one column (or one row) many times. The advantage of this trick is then you can use the 1d functions for comparison, since the 1d functions applied to that same column (or row) should give the same answer. |
I've figured out what the problem is, and it turns out it's really simple: because I've padded the matrix that stores the coefficient, I have to compensate for that when indexing into it. I'll see if I can get a fix in later tonight (and if I can, I think I can pass all Grid's tests except the ones that make use of |
Hm. I got the indexing right now, but I still don't get correct results - it seems I still have some of the math related to the prefiltering step to grok. I'm all good with how it works in 1D, both mathematically and in code. What I'm having problems with is how it works in the multi-dimensional case. Take 2D as an example: the input data to the interpolation is a matrix. When calculating the coefficients, we do it first column-wise, using each column of the matrix in the right-hand side of the same equation system as we did for 1D. Then, we do the same thing row-wise. (This is your "pencils aligned along all directions" analogy, if you remember...). However, it seems that I ask mainly because now that I got the indexing working, I was fairly sure that I did almost exactly the same things as |
It's more accurate to say that Grid double-filters: it filters the column-wise solution over rows. I do everything in-place for performance reasons, but there's nothing magical about that---if you're taking the solution from column-wise filtering and feeding it into the row-wise filtering, it should work. I haven't looked in detail at your filtering code, but I would recommend basing it on |
OK - that at least answers the question on what I'm aming for. If you have any resources (now or at a more convenient, less vacation-y, time - just because I like to spend my holidays coding 24/7 doesn't mean you have to 😉) on why that works, I'd be happy to indulge in some reading! I've started looking at
Quick searches through the docs, as well as the first page of Google results, don't give me any hints. Any ideas? |
Huzza! This PR now (usually, see below) passes all tests, including the ones I ported from Grid.jl that don't index with ranges =) Unfortunately, it only does so most of the time - sometimes I get the weird Any suggestions on how we can make the test suite less brittle? |
There - I've added a bunch of tests that do the same thing as the ones in the old A faster way of reproducing this is to open a REPL and do The error message is always something like
In every single failure, @timholy, do you have any idea what might cause this, and/or any suggestion on how to trouble-shoot it since it doesn't seem deterministic? |
I haven't had time to look into this in detail. But it occurs to me that if you're getting random failures from what looks like deterministic code:
|
Yep, |
@timholy, you deserve a medal! The tip on |
More boundary conditions for quadratic B-splines
This is really exciting. Seems like this has gone from "promising package" to "something that's already useful." I'm going to have to start kicking the tires directly, and of course work on the efficiency of the filtering. |
Nice! Tire-kicking (and performance enhancements) are always welcome! In the meantime, I've started working on gradient evaluation; I'll file a separate PR for that soon. |
I made an attempt at building linear extrapolation and boundar conditions as well, but I can't seem to get it right.
The math behind is quite straightforward; in the middle of the (1D) domain, the relevant in the tridiagonal system matrix is
[1/8 3/4 1/8]
. In order to specify thef'
at the edge, I introduce a ghost pointy0
atx=0
and give it a value such that it is on the line betweeny1
andy2
, yieldingy0 = 2y1 - y2
. Inserting in the equationy0/8 + 3y1/4 + y2/8 = A[1]
yieldsy1 = 0
. Thus, I modify the system (here) so that the first row is[1, 0, ...]
and the last row is[ ... 0, 1 ]
.However, this doesn't seem to give me enough to get where I want - I suspect I have to do something more (like what I did for flat BC here) but I can't figure out what. I just stole that piece from Grid, but there is no corresponding BC implemented in Grid to look at for this.