Repository navigation
Speed up GCRS<->(TETE, CIRS) by smarter location conversions - #11069
Conversation
|
Sorry, this is definitely not right: obsgeoloc and obsgeovel become all 0; I'm doing something stupid. |
|
More generally, a sequence of matrix multiplications cannot make the velocity non-zero, so |
|
That check against Horizons is off by 288 mas. This suggests that there is something wrong at the polar motion level. |
|
Oh, never mind. I see you have already discovered the error. |
This helps performance of the TETE/CIRS<->GCRS transforms.
db502ad to
ce7e1c0
Compare
|
OK, I get tests to pass again by reverting to what used to be done in |
|
|
||
| def get_location_gcrs(reference, gcrs_to_reference_matrix): | ||
| """Create a GCRS frame at the location and obstime of a given reference. | ||
| OMEGA_EARTH = u.Quantity(7.292115855306589e-5, 1./u.s) |
There was a problem hiding this comment.
Actually, still defined in earth.py, although it is not used there. I wonder if we should revert to the old code there too...
If we do revert to the old and much faster way, we can also revert out the "include_velocity" argument....
And if we do that, we perhaps can instead allow passing in a matrix in get_gcrs_posvel - though let's leave that for another PR
There was a problem hiding this comment.
Yes - let’s leave earth.py alone for now.
|
Ah, this is neat: with this change, the GCRS->CIRS->ICRS and GCRS->TETE->ICRS paths again give consistent results within 1 mm! I added a commit with the tightened test. |
| obsgeovel=gcrs_cart.differentials['s'].to_cartesian()) | ||
| itrs_cart = reference.location.get_itrs(obstime).cartesian | ||
| obsgeoloc = itrs_cart.transform(matrix_transpose(gcrs_to_itrs_matrix)) | ||
| vel_x = -OMEGA_EARTH * obsgeoloc.y |
There was a problem hiding this comment.
@mkbrewer - is there an ERFA routine that does this (maybe even in a better way)?
There was a problem hiding this comment.
Hmm, looking through why we changed it in earth.py, I came back to #6699, which planned to do:
# CIRS velocity
rotation_vector = CartesianRepresentation(0/u.s, 0/u.s, OMEGA_EARTH)
cirs_cart = itrs.transform_to(cirs_frame).cartesian
cirs_vel = rotation_vector.cross(cirs_cart)
# Transform to GCRS (rotation)
obsgeovel = cirs_vel.transform(matrix_transpose(gcrs_to_cirs_mat(obstime)))
return obsgeoloc, obsgeovel
But then in #6861 it was changed to its present state. @StuartLittlefair - both were your PRs, so you probably remember better what is right/wrong with it.
There was a problem hiding this comment.
This was removed when velocities were added to coordinates purely because it was simpler.
|
The ERFA routine is |
|
Hmm, I wonder why my comment was automatically deleted there. Anyway, yes, we both thought of that at basically the same time. |
|
Ah, from that routine, it looks like I should be calculating the velocity in CIRS, as was done in #6699, so this needs an update. |
|
It is because I deleted it, following your example. Sorry!! |
|
If we need to go to CIRS to add the velocity, maybe it makes more sense after all to go for your second option, i.e., transform the ITRS location to GCRS via CIRS also for TETE positions. |
|
I think you are fine there. You are just calculating the velocity after the final rotation. Otherwise, you'd need to rotate the velocity also. See |
|
btw, in fact, |
|
OK, that's good, so the plan would be to get the location it in ITRS, transform it to either CIRS or TETE using one matrix, then add the velocity as I do now, and finally transform to GCRS with the second matrix (which applies directly to the velocity as well). That should be a straightforward change! |
|
I don't see the point of making that change. Unless you actually want the velocity in CIRS or TETE, you might as well calculate it in GCRS. That saves one extra rotation. |
|
But I now assume the velocity is perpendicular to the GCRS Z axis, while I think it should be perpendicular to the real Earth's polar axis (and the matrix looked like it had rotations around x and y, but perhaps I misinterpreted c2i06a) |
|
Well, it is perpendicular to the CIP. The transformation to GCRS just aligns the CIP with the ICRF. That's why |
|
It's not quite perpendicular, though, and for some applications that small difference may matter (which was the reason for #6699 and the subsequent #6861) |
|
That's actually a quite interesting demonstration of the stability of the CIO. In ten years it only moved by 14 cm while the equator moved by 10 km. |
|
Since it seems that I'm not going be able to convince you, here's an experiment that you could do. First calculate the velocity in the CIRS frame and then rotate the position and velocity into the GCRS frame. Then recalculate the velocity from the GCRS position and compare the two. |
|
My lack of being convinced is just because of @StuartLittlefair's old #6699... But strengthened by the fact that with the current PR, |
|
If we go this route, we should make sure |
|
OK, you're right. The frame rotates, but the vectors don't. Therefore the spin picks up a z component in the new frame. I was erroneously thinking that the vectors stayed aligned with the CIP. Sorry about that. Omega is defined in pvtob.c: This is just a sidereal second converted to radians. |
|
A lot happens when I’m asleep! It looks like you’ve sorted out all the issues; as you say velocity should be added in CIRS or TETE and then rotated from there. I’m very pleased this also fixes the slight inaccuracies in the ICRS round trip as well as providing a massive speed up. |
|
There is a slight discrepancy between SOFA and Astropy regarding |
|
@mkbrewer - thanks, I think we might as well be consistent with what SOFA has. I'll make another commit that updates the value and adds a changelog entry about the speed and accuracy improvements. |
|
OK, I changed |
|
I put some follow-up items in #11072 |
Following the suggestion by @mkbrewer in #11067, this speeds up TETE<->GCRS considerably by using the
rbpnmatrix also for getting the sidereal time for the conversion of the observer location from ITRS to TETE.fixes #11067
Note: need to re-unify code so for now just a draft so we have something to look at.(done)EDIT: quick timing: