* @brief Computes the geodesics from the established metric, 4-vector positions * and velocities * * @param pos4 * @param vel4 * @return af::array */
| 586 | * @return af::array |
| 587 | */ |
| 588 | af::array geodesics(const af::array& pos4, const af::array& vel4) { |
| 589 | auto N = vel4.dims()[1]; |
| 590 | |
| 591 | af::array uu = af::matmul(af::moddims(vel4, af::dim4(4, 1, N)), |
| 592 | af::moddims(vel4, af::dim4(1, 4, N))); |
| 593 | uu = af::moddims(uu, af::dim4(1, 4, 4, N)); |
| 594 | |
| 595 | af::array metric = metric4(pos4); |
| 596 | af::array invmetric = af::moddims(inv_metric(metric), af::dim4(4, 4, 1, N)); |
| 597 | |
| 598 | // Compute the partials of the metric with respect to coordinates indices |
| 599 | af::array dt = af::constant(0, 4, 4, 1, N, f64); |
| 600 | |
| 601 | auto dr = partials(pos4, 1, 1e-6, 1e-12); |
| 602 | auto dtheta = partials(pos4, 2, 1e-6, 1e-12); |
| 603 | auto dphi = partials(pos4, 3, 1e-6, 1e-12); |
| 604 | |
| 605 | dr = af::moddims(dr, af::dim4(4, 4, 1, N)); |
| 606 | dtheta = af::moddims(dtheta, af::dim4(4, 4, 1, N)); |
| 607 | dphi = af::moddims(dphi, af::dim4(4, 4, 1, N)); |
| 608 | |
| 609 | // Compute the einsum for each of the christoffel terms |
| 610 | af::array partials = af::join(2, dt, dr, dtheta, dphi); |
| 611 | af::array p1 = af::matmul(invmetric, partials); |
| 612 | af::array p2 = af::reorder(p1, 0, 2, 1, 3); |
| 613 | af::array p3 = af::matmul(invmetric, af::reorder(partials, 2, 0, 1, 3)); |
| 614 | |
| 615 | auto christoffels = -0.5 * (p1 + p2 - p3); |
| 616 | |
| 617 | // Use the geodesics equation to find the 4-vector acceleration |
| 618 | return af::moddims(af::sum(af::sum(christoffels * uu, 1), 2), |
| 619 | af::dim4(4, N)); |
| 620 | } |
| 621 | |
| 622 | /** |
| 623 | * @brief Camera struct |
no test coverage detected