SpECTRE Documentation Coverage Report
Current view: top level - Domain - ElementMap.hpp Hit Total Coverage
Commit: 9f349d3c09e1c03107f00c2135ca40e209d3b84c Lines: 1 23 4.3 %
Date: 2023-06-09 21:05:06
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 <array>
       7             : #include <cstddef>
       8             : #include <limits>
       9             : #include <memory>
      10             : 
      11             : #include "DataStructures/Tensor/Tensor.hpp"
      12             : #include "Domain/CoordinateMaps/CoordinateMap.hpp"
      13             : #include "Domain/Structure/ElementId.hpp"
      14             : #include "Utilities/Gsl.hpp"
      15             : #include "Utilities/MakeArray.hpp"
      16             : 
      17             : namespace PUP {
      18             : class er;
      19             : }  // namespace PUP
      20             : 
      21             : /*!
      22             :  * \ingroup ComputationalDomainGroup
      23             :  * \brief The CoordinateMap for the Element from the Logical frame to the
      24             :  * `TargetFrame`
      25             :  *
      26             :  * An ElementMap takes a CoordinateMap for a Block and an ElementId as input,
      27             :  * and then "prepends" the correct affine map to the CoordinateMap so that the
      28             :  * map corresponds to the coordinate map for the Element rather than the Block.
      29             :  * This allows DomainCreators to only specify the maps for the Blocks without
      30             :  * worrying about how the domain may be decomposed beyond that.
      31             :  */
      32             : template <size_t Dim, typename TargetFrame>
      33           1 : class ElementMap {
      34             :  public:
      35           0 :   static constexpr size_t dim = Dim;
      36           0 :   using source_frame = Frame::ElementLogical;
      37           0 :   using target_frame = TargetFrame;
      38             : 
      39             :   /// \cond HIDDEN_SYMBOLS
      40             :   ElementMap() = default;
      41             :   /// \endcond
      42             : 
      43           0 :   ElementMap(ElementId<Dim> element_id,
      44             :              std::unique_ptr<domain::CoordinateMapBase<Frame::BlockLogical,
      45             :                                                        TargetFrame, Dim>>
      46             :                  block_map);
      47             : 
      48             :   const domain::CoordinateMapBase<Frame::BlockLogical, TargetFrame, Dim>&
      49           0 :   block_map() const {
      50             :     return *block_map_;
      51             :   }
      52             : 
      53           0 :   const ElementId<Dim>& element_id() const { return element_id_; }
      54             : 
      55             :   template <typename T>
      56           0 :   tnsr::I<T, Dim, TargetFrame> operator()(
      57             :       const tnsr::I<T, Dim, Frame::ElementLogical>& source_point) const {
      58             :     auto block_source_point =
      59             :         apply_affine_transformation_to_point(source_point);
      60             :     return block_map_->operator()(std::move(block_source_point));
      61             :   }
      62             : 
      63             :   template <typename T>
      64           0 :   tnsr::I<T, Dim, Frame::ElementLogical> inverse(
      65             :       tnsr::I<T, Dim, TargetFrame> target_point) const {
      66             :     auto block_source_point{
      67             :         block_map_->inverse(std::move(target_point)).value()};
      68             :     // Apply the affine map to the points
      69             :     tnsr::I<T, Dim, Frame::ElementLogical> source_point;
      70             :     for (size_t d = 0; d < Dim; ++d) {
      71             :       source_point.get(d) =
      72             :           block_source_point.get(d) * gsl::at(map_inverse_slope_, d) +
      73             :           gsl::at(map_inverse_offset_, d);
      74             :     }
      75             :     return source_point;
      76             :   }
      77             : 
      78             :   template <typename T>
      79           0 :   InverseJacobian<T, Dim, Frame::ElementLogical, TargetFrame> inv_jacobian(
      80             :       const tnsr::I<T, Dim, Frame::ElementLogical>& source_point) const {
      81             :     auto block_source_point =
      82             :         apply_affine_transformation_to_point(source_point);
      83             :     auto block_inv_jac =
      84             :         block_map_->inv_jacobian(std::move(block_source_point));
      85             :     InverseJacobian<T, Dim, Frame::ElementLogical, TargetFrame> inv_jac;
      86             :     for (size_t d = 0; d < Dim; ++d) {
      87             :       for (size_t i = 0; i < Dim; ++i) {
      88             :         inv_jac.get(d, i) =
      89             :             block_inv_jac.get(d, i) * gsl::at(inverse_jacobian_, d);
      90             :       }
      91             :     }
      92             :     return inv_jac;
      93             :   }
      94             : 
      95             :   template <typename T>
      96           0 :   Jacobian<T, Dim, Frame::ElementLogical, TargetFrame> jacobian(
      97             :       const tnsr::I<T, Dim, Frame::ElementLogical>& source_point) const {
      98             :     auto block_source_point =
      99             :         apply_affine_transformation_to_point(source_point);
     100             :     auto block_jac = block_map_->jacobian(std::move(block_source_point));
     101             :     Jacobian<T, Dim, Frame::ElementLogical, TargetFrame> jac;
     102             :     for (size_t d = 0; d < Dim; ++d) {
     103             :       for (size_t i = 0; i < Dim; ++i) {
     104             :         jac.get(i, d) = block_jac.get(i, d) * gsl::at(jacobian_, d);
     105             :       }
     106             :     }
     107             :     return jac;
     108             :   }
     109             : 
     110             :   // NOLINTNEXTLINE(google-runtime-references)
     111           0 :   void pup(PUP::er& p);
     112             : 
     113             :  private:
     114             :   template <typename T>
     115           0 :   tnsr::I<T, Dim, Frame::BlockLogical> apply_affine_transformation_to_point(
     116             :       const tnsr::I<T, Dim, Frame::ElementLogical>& source_point) const {
     117             :     tnsr::I<T, Dim, Frame::BlockLogical> block_source_point;
     118             :     for (size_t d = 0; d < Dim; ++d) {
     119             :       block_source_point.get(d) = source_point.get(d) * gsl::at(map_slope_, d) +
     120             :                                   gsl::at(map_offset_, d);
     121             :     }
     122             :     return block_source_point;
     123             :   }
     124             : 
     125             :   std::unique_ptr<
     126             :       domain::CoordinateMapBase<Frame::BlockLogical, TargetFrame, Dim>>
     127           0 :       block_map_{nullptr};
     128           0 :   ElementId<Dim> element_id_{};
     129             :   // map_slope_[i] = 0.5 * (segment_ids[i].endpoint(Side::Upper) -
     130             :   //                        segment_ids[i].endpoint(Side::Lower))
     131           0 :   std::array<double, Dim> map_slope_{
     132             :       make_array<Dim>(std::numeric_limits<double>::signaling_NaN())};
     133             :   // map_offset_[i] = 0.5 * (segment_ids[i].endpoint(Side::Upper) +
     134             :   //                         segment_ids[i].endpoint(Side::Lower))
     135           0 :   std::array<double, Dim> map_offset_{
     136             :       make_array<Dim>(std::numeric_limits<double>::signaling_NaN())};
     137             :   // map_inverse_slope_[i] = 1.0 / map_slope_[i]
     138           0 :   std::array<double, Dim> map_inverse_slope_{
     139             :       make_array<Dim>(std::numeric_limits<double>::signaling_NaN())};
     140             :   // map_inverse_offset_[i] = -map_offset_[i] / map_slope_[i]
     141           0 :   std::array<double, Dim> map_inverse_offset_{
     142             :       make_array<Dim>(std::numeric_limits<double>::signaling_NaN())};
     143             :   // Note: The Jacobian is diagonal
     144           0 :   std::array<double, Dim> jacobian_{map_slope_};
     145           0 :   std::array<double, Dim> inverse_jacobian_{map_inverse_slope_};
     146             : };
     147             : 
     148             : template <size_t Dim, typename TargetFrame>
     149           0 : ElementMap(ElementId<Dim> element_id,
     150             :            std::unique_ptr<
     151             :                domain::CoordinateMapBase<Frame::BlockLogical, TargetFrame, Dim>>
     152             :                block_map) -> ElementMap<Dim, TargetFrame>;

Generated by: LCOV version 1.14