Skip to content

Commit

Permalink
Add transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
sethrj committed Apr 3, 2024
1 parent 6f720e4 commit d72356f
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 60 deletions.
1 change: 0 additions & 1 deletion src/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ endif()
if(CELERITAS_USE_Geant4 AND CELERITAS_REAL_TYPE STREQUAL "double")
set( _cg4org_sources
g4org/SolidConverter.cc
g4org/Transformer.cc
)
celeritas_get_g4libs(_cg4org_libs geometry)
list(APPEND _cg4org_libs Celeritas::corecel Celeritas::geocel)
Expand Down
39 changes: 0 additions & 39 deletions src/orange/g4org/Transformer.cc

This file was deleted.

89 changes: 74 additions & 15 deletions src/orange/g4org/Transformer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ namespace g4org
{
//---------------------------------------------------------------------------//
/*!
* Return a VecGeom transformation from a Geant4 transformation.
* Return an ORANGE transformation from a Geant4 transformation.
*
* In Geant4, "object" or "direct" transform refers to daughter-to-parent, how
* to place the daughter object in the parent. The "frame" transform (raw \c
* GetTransform or the \c fPtrTransform object) is how to transform from parent
* to daughter and is the inverse of that transform.
*
* Even though the affine transform's matrix has a \c operator() which does a
* matrix-vector multiply (aka \c gemv), this is *not* the same as the affine
* transform's rotation, which applies the *inverse* of the stored matrix.
*
* All Celeritas transforms are "daughter to parent". The transforms returned
* from this function \em must be daughter-to-parent!
*/
class Transformer
{
Expand All @@ -36,10 +48,13 @@ class Transformer
inline explicit Transformer(Scaler const& scale);

// Convert a translation
Translation operator()(G4ThreeVector const& t) const;
inline Translation operator()(G4ThreeVector const& t) const;

// Convert a pure rotation
inline Transformation operator()(G4RotationMatrix const& rot) const;

// Convert a translation + rotation
Transformation
inline Transformation
operator()(G4ThreeVector const& t, G4RotationMatrix const& rot) const;

//! Convert a translation + optional rotation
Expand All @@ -55,6 +70,16 @@ class Transformer
Scaler const& scale_;
};

//---------------------------------------------------------------------------//
// FREE FUNCTIONS
//---------------------------------------------------------------------------//
// Convert a rotation matrix
inline SquareMatrixReal3 convert_from_geant(G4RotationMatrix const& rot);

//---------------------------------------------------------------------------//
// Get the transpose/inverse of a rotation matrix
inline SquareMatrixReal3 transposed_from_geant(G4RotationMatrix const& rot);

//---------------------------------------------------------------------------//
// INLINE DEFINITIONS
//---------------------------------------------------------------------------//
Expand All @@ -63,22 +88,33 @@ class Transformer
*/
Transformer::Transformer(Scaler const& scale) : scale_{scale} {}

//---------------------------------------------------------------------------//
/*!
* Create a transform from a translation.
*/
auto Transformer::operator()(G4ThreeVector const& t) const -> Translation
{
return Translation{scale_.to<Real3>(t[0], t[1], t[2])};
}

//---------------------------------------------------------------------------//
/*!
* Create a transform from a translation plus rotation.
*/
auto Transformer::operator()(G4ThreeVector const&,
G4RotationMatrix const&) const -> Transformation
{
CELER_NOT_IMPLEMENTED("transformer");
}

//---------------------------------------------------------------------------//
/*!
* Create a transform from a translation plus optional rotation.
*/
auto Transformer::operator()(G4ThreeVector const& t,
G4RotationMatrix const* rot) const
-> VariantTransform
auto Transformer::operator()(G4ThreeVector const&,
G4RotationMatrix const*) const -> VariantTransform
{
if (rot)
{
return (*this)(t, *rot);
}
else
{
return (*this)(t);
}
CELER_NOT_IMPLEMENTED("transformer");
}

//---------------------------------------------------------------------------//
Expand All @@ -88,7 +124,30 @@ auto Transformer::operator()(G4ThreeVector const& t,
auto Transformer::operator()(G4AffineTransform const& affine) const
-> Transformation
{
return (*this)(affine.NetTranslation(), affine.NetRotation());
return Transformation{transposed_from_geant(affine.NetRotation()),
scale_.to<Real3>(affine.NetTranslation())};
}

//---------------------------------------------------------------------------//
/*!
* Convert a rotation matrix.
*/
SquareMatrixReal3 convert_from_geant(G4RotationMatrix const& rot)
{
return {Real3{{rot.xx(), rot.xy(), rot.xz()}},
Real3{{rot.yx(), rot.yy(), rot.yz()}},
Real3{{rot.zx(), rot.zy(), rot.zz()}}};
}

//---------------------------------------------------------------------------//
/*!
* Get a transposed rotation matrix.
*/
SquareMatrixReal3 transposed_from_geant(G4RotationMatrix const& rot)
{
return {Real3{{rot.xx(), rot.yx(), rot.zx()}},
Real3{{rot.xy(), rot.yy(), rot.zy()}},
Real3{{rot.xz(), rot.yz(), rot.zz()}}};
}

//---------------------------------------------------------------------------//
Expand Down
8 changes: 4 additions & 4 deletions test/geocel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
if(NOT CELERITAS_USE_Geant4)
set(_needs_geant4 DISABLE)
else()
set(_needs_geant4 LINK_LIBRARIES ${Geant4_LIBRARIES})
celeritas_get_g4libs(_g4_geo_libs geometry)
endif()

if(CELERITAS_UNITS STREQUAL "CGS")
Expand Down Expand Up @@ -43,7 +43,7 @@ celeritas_target_link_libraries(testcel_geocel
PUBLIC
Celeritas::testcel_harness Celeritas::geocel
PRIVATE
Celeritas::testcel_core ${Geant4_LIBRARIES} ${VecGeom_LIBRARIES}
Celeritas::testcel_core ${_g4_geo_libs} ${VecGeom_LIBRARIES}
)

#-----------------------------------------------------------------------------#
Expand Down Expand Up @@ -104,10 +104,10 @@ endif()

if(CELERITAS_USE_Geant4 AND CELERITAS_REAL_TYPE STREQUAL "double")
celeritas_add_test(g4/GeantGeo.test.cc
LINK_LIBRARIES ${Geant4_LIBRARIES}
LINK_LIBRARIES ${_g4_geo_libs}
)
celeritas_add_test(GeantGeoUtils.test.cc
LINK_LIBRARIES ${Geant4_LIBRARIES}
LINK_LIBRARIES ${_g4_geo_libs}
)
endif()

Expand Down
16 changes: 15 additions & 1 deletion test/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ if(NOT CELERITAS_USE_JSON)
set(_needs_json DISABLE)
endif()

if(CELERITAS_USE_Geant4)
celeritas_get_g4libs(_g4_geo_libs geometry)
endif()

#-----------------------------------------------------------------------------#
# SETUP
#-----------------------------------------------------------------------------#
Expand Down Expand Up @@ -106,7 +110,7 @@ celeritas_add_test(surf/detail/SurfaceTranslator.test.cc)
celeritas_add_test(surf/detail/SurfaceTransformer.test.cc)

#-----------------------------------------------------------------------------#
# Universe details
# Universe
set(CELERITASTEST_PREFIX orange/univ)
celeritas_add_test(univ/VolumeView.test.cc)
celeritas_add_test(univ/RectArrayTracker.test.cc ${_needs_json})
Expand All @@ -120,4 +124,14 @@ celeritas_add_test(univ/detail/RaggedRightIndexer.test.cc)
celeritas_add_test(univ/detail/SurfaceFunctors.test.cc)
celeritas_add_test(univ/detail/SenseCalculator.test.cc)


#-----------------------------------------------------------------------------#
# Geant4 construction
if(CELERITAS_USE_Geant4 AND CELERITAS_REAL_TYPE STREQUAL "double")
set(CELERITASTEST_PREFIX orange/g4org)
list(APPEND CELERITASTEST_LINK_LIBRARIES ${_g4_geo_libs})

celeritas_add_test(g4org/Transformer.test.cc)
endif()

#-----------------------------------------------------------------------------#
129 changes: 129 additions & 0 deletions test/orange/g4org/Transformer.test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/g4org/Transformer.test.cc
//---------------------------------------------------------------------------//
#include "orange/g4org/Transformer.hh"

#include <G4AffineTransform.hh>
#include <G4RotationMatrix.hh>
#include <G4ThreeVector.hh>

#include "corecel/cont/ArrayIO.hh"
#include "corecel/math/ArrayOperators.hh"
#include "corecel/math/ArrayUtils.hh"
#include "geocel/UnitUtils.hh"
#include "geocel/detail/LengthUnits.hh"
#include "geocel/g4/Convert.geant.hh"
#include "orange/MatrixUtils.hh"
#include "orange/g4org/Scaler.hh"
#include "orange/transform/TransformIO.hh"

#include "celeritas_test.hh"

using celeritas::test::to_cm;

namespace celeritas
{
namespace g4org
{
namespace test
{
//---------------------------------------------------------------------------//
constexpr auto mm = ::celeritas::lengthunits::millimeter;

Real3 from_geant(G4ThreeVector const& tv)
{
return {tv[0], tv[1], tv[2]};
}

G4ThreeVector to_geant(Real3 const& rv)
{
return {rv[0], rv[1], rv[2]};
}

class TransformerTest : public ::celeritas::test::Test
{
protected:
Scaler scale_;
};

TEST_F(TransformerTest, translation)
{
Transformer transform{scale_};

auto trans = transform(G4ThreeVector(1.0, 2.0, 3.0));
EXPECT_VEC_SOFT_EQ((Real3{1 * mm, 2 * mm, 3 * mm}), trans.translation());
}

TEST_F(TransformerTest, affine_transform)
{
// Daughter to parent: +x becomes +y
Real3 const rot_axis = make_unit_vector(Real3{3, 4, 5});
Turn const rot_turn{0.125};

// Construct Geant4 matrix and transforms
G4RotationMatrix g4mat(to_geant(rot_axis), native_value_from(rot_turn));
G4AffineTransform g4tran{g4mat, G4ThreeVector(10.0, 20.0, 30.0)};

// Parent-to-daughter
auto g4tran_inv = g4tran.Inverse();

// Construct Celeritas matrix
auto const mat = make_rotation(rot_axis, rot_turn);
{
auto actual = convert_from_geant(g4mat);
// Check raw matrix conversion
EXPECT_VEC_SOFT_EQ(mat[0], actual[0]);
EXPECT_VEC_SOFT_EQ(mat[1], actual[1]);
EXPECT_VEC_SOFT_EQ(mat[2], actual[2]);
}
EXPECT_VEC_SOFT_EQ(gemv(mat, Real3{1, 0, 0}),
from_geant(g4mat(G4ThreeVector(1, 0, 0))));

// Expected Celeritas transform
Transformation const tran(make_transpose(mat),
Real3{10 * mm, 20 * mm, 30 * mm});
EXPECT_VEC_SOFT_EQ(tran.translation(), scale_(g4tran.NetTranslation()));

Transformer transform{scale_};
{
Transformation const actual = transform(g4tran);
EXPECT_VEC_SOFT_EQ(tran.data(), actual.data());

EXPECT_VEC_SOFT_EQ(
from_geant(g4tran.TransformAxis(G4ThreeVector{1, 0, 0})),
actual.rotate_up(Real3{1, 0, 0}));
EXPECT_VEC_SOFT_EQ(
from_geant(g4tran.TransformAxis(G4ThreeVector{0, 1, 0})),
actual.rotate_up(Real3{0, 1, 0}));
EXPECT_VEC_SOFT_EQ(
from_geant(g4tran.TransformAxis(G4ThreeVector{0, 0, 1})),
actual.rotate_up(Real3{0, 0, 1}));

// Do local-to-global transform from mm.
// See G4DisplacedSolid::DistanceToIn
G4ThreeVector const g4daughter{100, 200, 300};

EXPECT_VEC_SOFT_EQ(scale_(g4tran.TransformPoint(g4daughter)),
actual.transform_up(scale_(g4daughter)));
EXPECT_VEC_SOFT_EQ(scale_(g4tran_inv.TransformPoint(g4daughter)),
actual.transform_down(scale_(g4daughter)));
EXPECT_VEC_SOFT_EQ(
from_geant(g4tran_inv.TransformAxis(G4ThreeVector{1, 0, 0})),
actual.rotate_down(Real3{1, 0, 0}));
EXPECT_VEC_SOFT_EQ(
from_geant(g4tran_inv.TransformAxis(G4ThreeVector{0, 1, 0})),
actual.rotate_down(Real3{0, 1, 0}));
EXPECT_VEC_SOFT_EQ(
from_geant(g4tran_inv.TransformAxis(G4ThreeVector{0, 0, 1})),
actual.rotate_down(Real3{0, 0, 1}));
}
}

//---------------------------------------------------------------------------//
} // namespace test
} // namespace g4org
} // namespace celeritas

0 comments on commit d72356f

Please sign in to comment.