Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:57

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2023-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file orange/transform/Transformation.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <algorithm>
0011 
0012 #include "corecel/cont/Span.hh"
0013 #include "corecel/math/ArrayOperators.hh"
0014 #include "geocel/Types.hh"
0015 #include "orange/MatrixUtils.hh"
0016 #include "orange/OrangeTypes.hh"
0017 
0018 namespace celeritas
0019 {
0020 class Translation;
0021 class SignedPermutation;
0022 
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Apply transformations with rotation and/or reflection.
0026  *
0027  * \note The nomenclature in this class assumes the translation vector and
0028  * rotation matrix given represent "daughter-to-parent"! This is because we
0029  * think of rotations being with respect to the daughter's origin rather than
0030  * the parent's.
0031  *
0032  * This class enables transforms between daughter and parent coordinate
0033  * system. The transfer from a daughter into a parent system ("up" in a
0034  * hierarchy of universes) is
0035  * \f[
0036    \mathbf{r}_p = \mathbf{R}\mathbf{r}_d + \mathbf{t}\:,
0037  * \f]
0038  * Where the subscripts \e p,d refer to the parent and daughter coordinate
0039  * systems, respectively.  The vector \b t is a translation vector.  To go
0040  * from the parent into the daughter system ("down" in a universe hierarchy) we
0041  * apply the inverse:
0042  * \f[
0043    \mathbf{r}_d = \mathbf{R}^T(\mathbf{r}_p - \mathbf{t})\:.
0044  * \f]
0045  * where the transpose of \b R is equal to its inverse because the matrix is
0046  * unitary.
0047  *
0048  * The rotation matrix is indexed with C ordering, [i][j].
0049  */
0050 class Transformation
0051 {
0052   public:
0053     //@{
0054     //! \name Type aliases
0055     using StorageSpan = Span<real_type const, 12>;
0056     using Mat3 = SquareMatrixReal3;
0057     //@}
0058 
0059     //! Transformation type identifier
0060     static CELER_CONSTEXPR_FUNCTION TransformType transform_type()
0061     {
0062         return TransformType::transformation;
0063     }
0064 
0065   public:
0066     // Construct by inverting a parent-to-daughter transformation
0067     static Transformation from_inverse(Mat3 const& rot, Real3 const& trans);
0068 
0069     //// CONSTRUCTORS ////
0070 
0071     // Construct and check the input
0072     Transformation(Mat3 const& rot, Real3 const& trans);
0073 
0074     // Construct from an identity transformation + translation
0075     Transformation();
0076 
0077     // Promote from a translation
0078     explicit Transformation(Translation const&);
0079 
0080     // Promote from a signed permutation
0081     explicit Transformation(SignedPermutation const&);
0082 
0083     // Construct inline from storage
0084     explicit inline CELER_FUNCTION Transformation(StorageSpan);
0085 
0086     //// ACCESSORS ////
0087 
0088     //! Rotation matrix
0089     CELER_FORCEINLINE_FUNCTION Mat3 const& rotation() const { return rot_; }
0090 
0091     //! Translation vector
0092     CELER_FORCEINLINE_FUNCTION Real3 const& translation() const
0093     {
0094         return tra_;
0095     }
0096 
0097     //! Get a view to the data for type-deleted storage
0098     CELER_FUNCTION StorageSpan data() const { return {&rot_[0][0], 12}; }
0099 
0100     //// CALCULATION ////
0101 
0102     // Transform from daughter to parent
0103     [[nodiscard]] inline CELER_FUNCTION Real3
0104     transform_up(Real3 const& pos) const;
0105 
0106     // Transform from parent to daughter
0107     [[nodiscard]] inline CELER_FUNCTION Real3
0108     transform_down(Real3 const& parent_pos) const;
0109 
0110     // Rotate from daughter to parent
0111     [[nodiscard]] inline CELER_FUNCTION Real3 rotate_up(Real3 const& dir) const;
0112 
0113     // Rotate from parent to daughter
0114     [[nodiscard]] inline CELER_FUNCTION Real3
0115     rotate_down(Real3 const& parent_dir) const;
0116 
0117     // Calculate the inverse during preprocessing
0118     Transformation calc_inverse() const;
0119 
0120   private:
0121     Mat3 rot_;
0122     Real3 tra_;
0123 };
0124 
0125 //---------------------------------------------------------------------------//
0126 //!@{
0127 //! Host-only comparators
0128 inline bool operator==(Transformation const& a, Transformation const& b)
0129 {
0130     auto a_data = a.data();
0131     return std::equal(a_data.begin(), a_data.end(), b.data().begin());
0132 }
0133 
0134 inline bool operator!=(Transformation const& a, Transformation const& b)
0135 {
0136     return !(a == b);
0137 }
0138 //!@}
0139 
0140 //---------------------------------------------------------------------------//
0141 // INLINE DEFINITIONS
0142 //---------------------------------------------------------------------------//
0143 /*!
0144  * Construct inline from storage.
0145  */
0146 CELER_FUNCTION Transformation::Transformation(StorageSpan s)
0147     : rot_{Real3{s[0], s[1], s[2]},
0148            Real3{s[3], s[4], s[5]},
0149            Real3{s[6], s[7], s[8]}}
0150     , tra_{s[9], s[10], s[11]}
0151 {
0152 }
0153 
0154 //---------------------------------------------------------------------------//
0155 /*!
0156  * Transform from daughter to parent.
0157  *
0158  * Apply the rotation matrix, add the translation.
0159  */
0160 CELER_FUNCTION Real3 Transformation::transform_up(Real3 const& pos) const
0161 {
0162     return gemv(real_type{1}, rot_, pos, real_type{1}, tra_);
0163 }
0164 
0165 //---------------------------------------------------------------------------//
0166 /*!
0167  * Transform from parent to daughter.
0168  *
0169  * Subtract the translation, then apply the inverse of the rotation matrix (its
0170  * transpose).
0171  */
0172 CELER_FUNCTION Real3 Transformation::transform_down(Real3 const& pos) const
0173 {
0174     return gemv(matrix::transpose, rot_, pos - tra_);
0175 }
0176 
0177 //---------------------------------------------------------------------------//
0178 /*!
0179  * Rotate from daughter to parent.
0180  */
0181 CELER_FUNCTION Real3 Transformation::rotate_up(Real3 const& d) const
0182 {
0183     return gemv(rot_, d);
0184 }
0185 
0186 //---------------------------------------------------------------------------//
0187 /*!
0188  * Rotate from parent to daughter.
0189  */
0190 CELER_FUNCTION Real3 Transformation::rotate_down(Real3 const& d) const
0191 {
0192     return gemv(matrix::transpose, rot_, d);
0193 }
0194 
0195 //---------------------------------------------------------------------------//
0196 }  // namespace celeritas