SpECTRE Documentation Coverage Report
Current view: top level - Evolution/DgSubcell/Tags - Jacobians.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 23.2 % 56 13
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <cstddef>
       7              : #include <string>
       8              : 
       9              : #include "DataStructures/DataBox/Tag.hpp"
      10              : #include "DataStructures/Tensor/EagerMath/Determinant.hpp"
      11              : #include "DataStructures/Tensor/TypeAliases.hpp"
      12              : #include "Domain/ElementMap.hpp"
      13              : #include "Evolution/DgSubcell/Tags/Coordinates.hpp"
      14              : #include "Utilities/SetNumberOfGridPoints.hpp"
      15              : 
      16              : /// \cond
      17              : namespace Tags {
      18              : struct Time;
      19              : }  // namespace Tags
      20              : /// \endcond
      21              : 
      22            1 : namespace evolution::dg::subcell::fd::Tags {
      23              : /// \brief The inverse Jacobian from the element logical frame to the grid frame
      24              : /// at the cell centers.
      25              : ///
      26              : /// Specifically, \f$\partial x^{\bar{i}} / \partial x^i\f$, where \f$\bar{i}\f$
      27              : /// denotes the element logical frame and \f$i\f$ denotes the grid frame.
      28              : template <size_t Dim>
      29            1 : struct InverseJacobianLogicalToGrid : db::SimpleTag {
      30            0 :   static std::string name() { return "InverseJacobian(Logical,Grid)"; }
      31            0 :   using type =
      32              :       ::InverseJacobian<DataVector, Dim, Frame::ElementLogical, Frame::Grid>;
      33              : };
      34              : 
      35              : /// \brief The determinant of the inverse Jacobian from the element logical
      36              : /// frame to the grid frame at the cell centers.
      37            1 : struct DetInverseJacobianLogicalToGrid : db::SimpleTag {
      38            0 :   static std::string name() { return "Det(InverseJacobian(Logical,Grid))"; }
      39            0 :   using type = Scalar<DataVector>;
      40              : };
      41              : 
      42              : /// \brief The determinant of the inverse Jacobian from the element logical
      43              : /// frame to the inertial frame at the cell centers.
      44            1 : struct DetInverseJacobianLogicalToInertial : db::SimpleTag {
      45            0 :   static std::string name() { return "Det(InverseJacobian(Logical,Inertial))"; }
      46            0 :   using type = Scalar<DataVector>;
      47              : };
      48              : 
      49              : /// \brief The inverse Jacobian from the element logical frame to the inertial
      50              : /// frame at the cell centers.
      51              : ///
      52              : /// Specifically, \f$\partial x^{\bar{i}} / \partial x^i\f$, where \f$\bar{i}\f$
      53              : /// denotes the element logical frame and \f$i\f$ denotes the inertial frame.
      54              : template <size_t Dim>
      55            1 : struct InverseJacobianLogicalToInertial : db::SimpleTag {
      56            0 :   static std::string name() { return "InverseJacobian(Logical,Inertial)"; }
      57            0 :   using type = ::InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      58              :                                  Frame::Inertial>;
      59              : };
      60              : 
      61              : /// \brief The inverse Hessian from the element logical frame to the grid frame
      62              : /// at the cell centers.
      63              : ///
      64              : /// Specifically, \f$\partial^2 x^{\bar{i}} / {\partial x^i \partial x^j}\f$,
      65              : /// where \f$\bar{i}\f$ denotes the element logical frame and \f$i\f$ denotes
      66              : /// the grid frame.
      67              : template <size_t Dim>
      68            1 : struct InverseHessianLogicalToGrid : db::SimpleTag {
      69            0 :   static std::string name() { return "InverseHessian(Logical,Grid)"; }
      70            0 :   using type =
      71              :       ::InverseHessian<DataVector, Dim, Frame::ElementLogical, Frame::Grid>;
      72              : };
      73              : 
      74              : /// \brief The inverse Hessian from the element logical frame to the inertial
      75              : /// frame at the cell centers.
      76              : ///
      77              : /// Specifically, \f$\partial^2 x^{\bar{i}} / {\partial x^i \partial x^j}\f$,
      78              : /// where \f$\bar{i}\f$ denotes the element logical frame and \f$i\f$ denotes
      79              : /// the inertial frame.
      80              : template <size_t Dim>
      81            1 : struct InverseHessianLogicalToInertial : db::SimpleTag {
      82            0 :   static std::string name() { return "InverseHessian(Logical,Inertial)"; }
      83            0 :   using type =
      84              :       ::InverseHessian<DataVector, Dim, Frame::ElementLogical, Frame::Inertial>;
      85              : };
      86              : 
      87              : /// Compute item for the inverse jacobian matrix from logical to
      88              : /// grid coordinates
      89              : template <typename MapTagLogicalToGrid, size_t Dim>
      90            1 : struct InverseJacobianLogicalToGridCompute : InverseJacobianLogicalToGrid<Dim>,
      91              :                                              db::ComputeTag {
      92            0 :   static constexpr size_t dim = Dim;
      93            0 :   using base = InverseJacobianLogicalToGrid<Dim>;
      94            0 :   using return_type = typename base::type;
      95            0 :   using argument_tags = tmpl::list<
      96              :       MapTagLogicalToGrid,
      97              :       evolution::dg::subcell::Tags::Coordinates<dim, Frame::ElementLogical>>;
      98            0 :   static void function(
      99              :       const gsl::not_null<return_type*> inverse_jacobian_logical_to_grid,
     100              :       const ElementMap<Dim, Frame::Grid>& logical_to_grid_map,
     101              :       const tnsr::I<DataVector, dim, Frame::ElementLogical>& logical_coords) {
     102              :     *inverse_jacobian_logical_to_grid =
     103              :         logical_to_grid_map.inv_jacobian(logical_coords);
     104              :   }
     105              : };
     106              : 
     107              : /// Compute item for the determinant of the inverse jacobian matrix
     108              : /// from logical to grid coordinates
     109              : template <size_t Dim>
     110            1 : struct DetInverseJacobianLogicalToGridCompute
     111              :     : DetInverseJacobianLogicalToGrid,
     112              :       db::ComputeTag {
     113            0 :   static constexpr size_t dim = Dim;
     114            0 :   using base = DetInverseJacobianLogicalToGrid;
     115            0 :   using return_type = typename base::type;
     116            0 :   using argument_tags = tmpl::list<InverseJacobianLogicalToGrid<Dim>>;
     117            0 :   static void function(
     118              :       const gsl::not_null<return_type*> det_inverse_jacobian_logical_to_grid,
     119              :       const ::InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     120              :                               Frame::Grid>& inverse_jacobian_logical_to_grid) {
     121              :     *det_inverse_jacobian_logical_to_grid =
     122              :         determinant(inverse_jacobian_logical_to_grid);
     123              :   }
     124              : };
     125              : 
     126              : /// Compute item for the inverse jacobian matrix from logical to
     127              : /// inertial coordinates
     128              : template <typename MapTagGridToInertial, size_t Dim>
     129            1 : struct InverseJacobianLogicalToInertialCompute
     130              :     : InverseJacobianLogicalToInertial<Dim>,
     131              :       db::ComputeTag {
     132            0 :   static constexpr size_t dim = Dim;
     133            0 :   using base = InverseJacobianLogicalToInertial<Dim>;
     134            0 :   using return_type = typename base::type;
     135            0 :   using argument_tags =
     136              :       tmpl::list<MapTagGridToInertial,
     137              :                  evolution::dg::subcell::Tags::Coordinates<dim, Frame::Grid>,
     138              :                  ::Tags::Time, ::domain::Tags::FunctionsOfTime,
     139              :                  InverseJacobianLogicalToGrid<Dim>>;
     140            0 :   static void function(
     141              :       const gsl::not_null<return_type*> inverse_jacobian_logical_to_inertial,
     142              :       const ::domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, dim>&
     143              :           grid_to_inertial_map,
     144              :       const tnsr::I<DataVector, dim, Frame::Grid>& grid_coords,
     145              :       const double time,
     146              :       const std::unordered_map<
     147              :           std::string,
     148              :           std::unique_ptr<::domain::FunctionsOfTime::FunctionOfTime>>&
     149              :           functions_of_time,
     150              :       const ::InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     151              :                               Frame::Grid>& inverse_jacobian_logical_to_grid) {
     152              :     if (grid_to_inertial_map.is_identity()) {
     153              :       // Optimization for time-independent maps; we just point to the
     154              :       // logical-to-grid inverse jacobian.
     155              :       const size_t num_pts = inverse_jacobian_logical_to_grid[0].size();
     156              :       for (size_t storage_index = 0;
     157              :            storage_index < inverse_jacobian_logical_to_grid.size();
     158              :            ++storage_index) {
     159              :         make_const_view(
     160              :             make_not_null(&std::as_const(
     161              :                 (*inverse_jacobian_logical_to_inertial)[storage_index])),
     162              :             inverse_jacobian_logical_to_grid[storage_index], 0, num_pts);
     163              :       }
     164              :     } else {
     165              :       set_number_of_grid_points(inverse_jacobian_logical_to_inertial,
     166              :                                 get<0>(grid_coords).size());
     167              :       // Get grid to inertial inverse jacobian
     168              :       const auto& inverse_jacobian_grid_to_inertial =
     169              :           grid_to_inertial_map.inv_jacobian(grid_coords, time,
     170              :                                             functions_of_time);
     171              :       for (size_t i = 0; i < Dim; i++) {
     172              :         for (size_t j = 0; j < Dim; j++) {
     173              :           auto& inv_jacobian_component =
     174              :               inverse_jacobian_logical_to_inertial->get(i, j);
     175              :           inv_jacobian_component = 0.;
     176              :           for (size_t k = 0; k < Dim; k++) {
     177              :             inv_jacobian_component +=
     178              :                 inverse_jacobian_logical_to_grid.get(i, k) *
     179              :                 inverse_jacobian_grid_to_inertial.get(k, j);
     180              :           }
     181              :         }
     182              :       }
     183              :     }
     184              :   }
     185              : };
     186              : 
     187              : /// Compute item for the determinant of the inverse jacobian matrix
     188              : /// from logical to inertial coordinates
     189              : template <typename MapTagGridToInertial, size_t Dim>
     190            1 : struct DetInverseJacobianLogicalToInertialCompute
     191              :     : DetInverseJacobianLogicalToInertial,
     192              :       db::ComputeTag {
     193            0 :   static constexpr size_t dim = Dim;
     194            0 :   using base = DetInverseJacobianLogicalToInertial;
     195            0 :   using return_type = typename base::type;
     196            0 :   using argument_tags =
     197              :       tmpl::list<MapTagGridToInertial, InverseJacobianLogicalToInertial<Dim>,
     198              :                  DetInverseJacobianLogicalToGrid>;
     199            0 :   static void function(
     200              :       const gsl::not_null<return_type*>
     201              :           det_inverse_jacobian_logical_to_inertial,
     202              :       const ::domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, dim>&
     203              :           grid_to_inertial_map,
     204              :       const ::InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     205              :                               Frame::Inertial>&
     206              :           inverse_jacobian_logical_to_inertial,
     207              :       const Scalar<DataVector>& det_inverse_jacobian_logical_to_grid) {
     208              :     if (grid_to_inertial_map.is_identity()) {
     209              :       const size_t num_pts = get(det_inverse_jacobian_logical_to_grid).size();
     210              :       make_const_view(make_not_null(&std::as_const(
     211              :                           get(*det_inverse_jacobian_logical_to_inertial))),
     212              :                       get(det_inverse_jacobian_logical_to_grid), 0, num_pts);
     213              :     } else {
     214              :       *det_inverse_jacobian_logical_to_inertial =
     215              :           determinant(inverse_jacobian_logical_to_inertial);
     216              :     }
     217              :   }
     218              : };
     219              : 
     220              : #ifdef SPECTRE_AUTODIFF
     221              : /// Compute item for the inverse hessian matrix from logical to
     222              : /// grid coordinates
     223              : template <typename MapTagLogicalToGrid, size_t Dim>
     224            1 : struct InverseHessianLogicalToGridCompute : InverseHessianLogicalToGrid<Dim>,
     225              :                                             db::ComputeTag {
     226            0 :   static constexpr size_t dim = Dim;
     227            0 :   using base = InverseHessianLogicalToGrid<Dim>;
     228            0 :   using return_type = typename base::type;
     229            0 :   using argument_tags = tmpl::list<
     230              :       MapTagLogicalToGrid,
     231              :       evolution::dg::subcell::Tags::Coordinates<dim, Frame::ElementLogical>>;
     232            0 :   static void function(
     233              :       const gsl::not_null<return_type*> inverse_hessian_logical_to_grid,
     234              :       const ElementMap<Dim, Frame::Grid>& logical_to_grid_map,
     235              :       const tnsr::I<DataVector, dim, Frame::ElementLogical>& logical_coords) {
     236              :     *inverse_hessian_logical_to_grid =
     237              :         logical_to_grid_map.inv_hessian(logical_coords);
     238              :   }
     239              : };
     240              : 
     241              : /// Compute item for the inverse hessian matrix from logical to
     242              : /// inertial coordinates
     243              : template <typename MapTagGridToInertial, size_t Dim>
     244            1 : struct InverseHessianLogicalToInertialCompute
     245              :     : InverseHessianLogicalToInertial<Dim>,
     246              :       db::ComputeTag {
     247            0 :   static constexpr size_t dim = Dim;
     248            0 :   using base = InverseHessianLogicalToInertial<Dim>;
     249            0 :   using return_type = typename base::type;
     250            0 :   using argument_tags =
     251              :       tmpl::list<MapTagGridToInertial,
     252              :                  evolution::dg::subcell::Tags::Coordinates<dim, Frame::Grid>,
     253              :                  ::Tags::Time, ::domain::Tags::FunctionsOfTime,
     254              :                  InverseJacobianLogicalToGrid<Dim>,
     255              :                  InverseHessianLogicalToGrid<Dim>>;
     256            0 :   static void function(
     257              :       const gsl::not_null<return_type*> inverse_hessian_logical_to_inertial,
     258              :       const ::domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, dim>&
     259              :           grid_to_inertial_map,
     260              :       const tnsr::I<DataVector, dim, Frame::Grid>& grid_coords,
     261              :       const double time,
     262              :       const std::unordered_map<
     263              :           std::string,
     264              :           std::unique_ptr<::domain::FunctionsOfTime::FunctionOfTime>>&
     265              :           functions_of_time,
     266              :       const ::InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     267              :                               Frame::Grid>& inverse_jacobian_logical_to_grid,
     268              :       const ::InverseHessian<DataVector, Dim, Frame::ElementLogical,
     269              :                              Frame::Grid>& inverse_hessian_logical_to_grid) {
     270              :     if (grid_to_inertial_map.is_identity()) {
     271              :       // Optimization for time-independent maps; we just point to the
     272              :       // logical-to-grid inverse hessian.
     273              :       const size_t num_pts = inverse_hessian_logical_to_grid[0].size();
     274              :       for (size_t storage_index = 0;
     275              :            storage_index < inverse_hessian_logical_to_grid.size();
     276              :            ++storage_index) {
     277              :         make_const_view(
     278              :             make_not_null(&std::as_const(
     279              :                 (*inverse_hessian_logical_to_inertial)[storage_index])),
     280              :             inverse_hessian_logical_to_grid[storage_index], 0, num_pts);
     281              :       }
     282              :     } else {
     283              :       set_number_of_grid_points(inverse_hessian_logical_to_inertial,
     284              :                                 get<0>(grid_coords).size());
     285              :       // Get grid to inertial inverse jacobian
     286              :       const auto& inverse_jacobian_grid_to_inertial =
     287              :           grid_to_inertial_map.inv_jacobian(grid_coords, time,
     288              :                                             functions_of_time);
     289              :       // Get grid to inertial inverse hessian
     290              :       const auto& inverse_hessian_grid_to_inertial =
     291              :           grid_to_inertial_map.inv_hessian(grid_coords,
     292              :                                            inverse_jacobian_grid_to_inertial,
     293              :                                            time, functions_of_time);
     294              :       for (size_t i = 0; i < Dim; i++) {
     295              :         for (size_t j = 0; j < Dim; j++) {
     296              :           for (size_t k = j; k < Dim; k++) {
     297              :             auto& inv_hessian_component =
     298              :                 inverse_hessian_logical_to_inertial->get(i, j, k);
     299              :             inv_hessian_component = 0.;
     300              :             for (size_t n = 0; n < Dim; n++) {
     301              :               inv_hessian_component +=
     302              :                   inverse_hessian_grid_to_inertial.get(n, j, k) *
     303              :                   inverse_jacobian_logical_to_grid.get(i, n);
     304              :               for (size_t m = 0; m < Dim; m++) {
     305              :                 inv_hessian_component +=
     306              :                     inverse_jacobian_grid_to_inertial.get(n, k) *
     307              :                     inverse_hessian_logical_to_grid.get(i, m, n) *
     308              :                     inverse_jacobian_grid_to_inertial.get(m, j);
     309              :               }
     310              :             }
     311              :           }
     312              :         }
     313              :       }
     314              :     }
     315              :   }
     316              : };
     317              : #endif  // SPECTRE_AUTODIFF
     318              : }  // namespace evolution::dg::subcell::fd::Tags
        

Generated by: LCOV version 2.0-1