SpECTRE Documentation Coverage Report
Current view: top level - Evolution/DgSubcell/Tags - Jacobians.hpp Hit Total Coverage
Commit: c428a3e2e0ca78fe0364ec1b0e0493c627d428d4 Lines: 13 56 23.2 %
Date: 2026-04-26 20:20:36
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 1.14