diff --git a/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.cpp b/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.cpp index 33ee7e78f304..beadfe9e0219 100644 --- a/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.cpp +++ b/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.cpp @@ -65,44 +65,6 @@ Strahlkorper::Strahlkorper(const size_t l_max, const size_t m_max, strahlkorper_coefs_.begin()); } -template -Strahlkorper::Strahlkorper(const size_t l_max, const size_t m_max, - const Strahlkorper& another_strahlkorper) - : l_max_(l_max), - m_max_(m_max), - ylm_(l_max, m_max), - center_(another_strahlkorper.center_), - strahlkorper_coefs_(another_strahlkorper.ylm_.prolong_or_restrict( - another_strahlkorper.strahlkorper_coefs_, ylm_)) {} - -template -Strahlkorper::Strahlkorper(DataVector coefs, - const Strahlkorper& another_strahlkorper) - : l_max_(another_strahlkorper.l_max_), - m_max_(another_strahlkorper.m_max_), - ylm_(another_strahlkorper.ylm_), - center_(another_strahlkorper.center_), - strahlkorper_coefs_(std::move(coefs)) { - ASSERT( - strahlkorper_coefs_.size() == another_strahlkorper.ylm_.spectral_size(), - "Bad size " << strahlkorper_coefs_.size() << ", expected " - << another_strahlkorper.ylm_.spectral_size()); -} - -template -Strahlkorper::Strahlkorper(DataVector coefs, - Strahlkorper&& another_strahlkorper) - : l_max_(another_strahlkorper.l_max_), - m_max_(another_strahlkorper.m_max_), - ylm_(std::move(another_strahlkorper.ylm_)), - // clang-tidy: do not std::move trivially constructable types - center_(std::move(another_strahlkorper.center_)), // NOLINT - strahlkorper_coefs_(std::move(coefs)) { - ASSERT(strahlkorper_coefs_.size() == ylm_.spectral_size(), - "Bad size " << strahlkorper_coefs_.size() << ", expected " - << ylm_.spectral_size()); -} - template void Strahlkorper::pup(PUP::er& p) { p | l_max_; diff --git a/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp b/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp index 150d34680366..cd54f4fff849 100644 --- a/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp +++ b/src/NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp @@ -11,6 +11,7 @@ #include "NumericalAlgorithms/SphericalHarmonics/Spherepack.hpp" #include "Options/String.hpp" #include "Utilities/ForceInline.hpp" +#include "Utilities/StdArrayHelpers.hpp" /// \cond namespace PUP { @@ -49,6 +50,10 @@ class Strahlkorper { // Pup needs default constructor Strahlkorper() = default; + Strahlkorper(const Strahlkorper&) = default; + Strahlkorper(Strahlkorper&&) = default; + Strahlkorper& operator=(const Strahlkorper&) = default; + Strahlkorper& operator=(Strahlkorper&&) = default; /// Construct a sphere of radius `radius` with a given center. Strahlkorper(size_t l_max, size_t m_max, double radius, @@ -87,19 +92,51 @@ class Strahlkorper { const ModalVector& spectral_coefficients, std::array center); + /// Copies a Strahlkorper from another frame into this Strahlkorper. + /// + /// \note The `OtherFrame` is ignored. + template + explicit Strahlkorper(const Strahlkorper& another_strahlkorper) + : l_max_(another_strahlkorper.l_max()), + m_max_(another_strahlkorper.m_max()), + ylm_(l_max_, m_max_), + center_(another_strahlkorper.expansion_center()), + strahlkorper_coefs_(another_strahlkorper.coefficients()) {} + /// Prolong or restrict another surface to the given `l_max` and `m_max`. + /// + /// \note The `OtherFrame` is ignored. + template Strahlkorper(size_t l_max, size_t m_max, - const Strahlkorper& another_strahlkorper); + const Strahlkorper& another_strahlkorper) + : l_max_(l_max), + m_max_(m_max), + ylm_(l_max, m_max), + center_(another_strahlkorper.expansion_center()), + strahlkorper_coefs_( + another_strahlkorper.ylm_spherepack().prolong_or_restrict( + another_strahlkorper.coefficients(), ylm_)) {} /// Construct a Strahlkorper from another Strahlkorper, /// but explicitly specifying the coefficients. /// Here coefficients are in the same storage scheme /// as the `coefficients()` member function returns. - Strahlkorper(DataVector coefs, const Strahlkorper& another_strahlkorper); - - /// Move-construct a Strahlkorper from another Strahlkorper, - /// explicitly specifying the coefficients. - Strahlkorper(DataVector coefs, Strahlkorper&& another_strahlkorper); + /// + /// \note The `OtherFrame` is ignored. + template + Strahlkorper(DataVector coefs, + const Strahlkorper& another_strahlkorper) + : l_max_(another_strahlkorper.l_max()), + m_max_(another_strahlkorper.m_max()), + ylm_(another_strahlkorper.ylm_spherepack()), + center_(another_strahlkorper.expansion_center()), + strahlkorper_coefs_(std::move(coefs)) { + ASSERT( + strahlkorper_coefs_.size() == + another_strahlkorper.ylm_spherepack().spectral_size(), + "Bad size " << strahlkorper_coefs_.size() << ", expected " + << another_strahlkorper.ylm_spherepack().spectral_size()); + } /// Serialization for Charm++ // NOLINTNEXTLINE(google-runtime-references) @@ -186,7 +223,7 @@ struct Strahlkorper { using type = ylm::Strahlkorper; static constexpr Options::String help{"A star-shaped surface"}; }; -} // namespace OptionTags +} // namespace OptionTags template bool operator==(const Strahlkorper& lhs, diff --git a/tests/Unit/NumericalAlgorithms/SphericalHarmonics/Test_Strahlkorper.cpp b/tests/Unit/NumericalAlgorithms/SphericalHarmonics/Test_Strahlkorper.cpp index a80b5cb0c9da..aef3221ac82d 100644 --- a/tests/Unit/NumericalAlgorithms/SphericalHarmonics/Test_Strahlkorper.cpp +++ b/tests/Unit/NumericalAlgorithms/SphericalHarmonics/Test_Strahlkorper.cpp @@ -196,6 +196,32 @@ void test_construct_from_options() { Strahlkorper(6, 6, 4.5, {{1., 2., 3.}})); } +void test_strahlkorper_from_other_strahlkorper() { + const Strahlkorper inertial_strahlkorper{ + 4_st, 1.2, std::array{1.0, 2.0, 3.0}}; + Strahlkorper grid_strahlkorper{inertial_strahlkorper}; + + const auto check_equal = [](const auto& s1, const auto& s2) { + CHECK(s1.coefficients() == s2.coefficients()); + CHECK(s1.l_max() == s2.l_max()); + CHECK(s1.m_max() == s2.m_max()); + CHECK(s1.expansion_center() == s2.expansion_center()); + }; + + check_equal(inertial_strahlkorper, grid_strahlkorper); + + grid_strahlkorper = Strahlkorper{ + inertial_strahlkorper.coefficients(), inertial_strahlkorper}; + + check_equal(inertial_strahlkorper, grid_strahlkorper); + + grid_strahlkorper = + Strahlkorper{8_st, 8_st, inertial_strahlkorper}; + + check_equal(Strahlkorper(8_st, 1.2, std::array{1.0, 2.0, 3.0}), + grid_strahlkorper); +} + } // namespace SPECTRE_TEST_CASE("Unit.ApparentHorizonFinder.Strahlkorper", @@ -225,11 +251,10 @@ SPECTRE_TEST_CASE("Unit.ApparentHorizonFinder.Strahlkorper", return Strahlkorper(std::move(sk)); }); test_construct_from_options(); -} - -SPECTRE_TEST_CASE("Unit.ApparentHorizonFinder.Strahlkorper.Serialization", - "[ApparentHorizonFinder][Unit]") { - Strahlkorper s(4, 4, 2.0, {{1.0, 2.0, 3.0}}); - test_serialization(s); + test_strahlkorper_from_other_strahlkorper(); + { + Strahlkorper s(4, 4, 2.0, {{1.0, 2.0, 3.0}}); + test_serialization(s); + } } } // namespace ylm diff --git a/tests/Unit/PointwiseFunctions/GeneralRelativity/Surfaces/Test_GrSurfaces.cpp b/tests/Unit/PointwiseFunctions/GeneralRelativity/Surfaces/Test_GrSurfaces.cpp index 79a701a1c85b..cca554e8f5d7 100644 --- a/tests/Unit/PointwiseFunctions/GeneralRelativity/Surfaces/Test_GrSurfaces.cpp +++ b/tests/Unit/PointwiseFunctions/GeneralRelativity/Surfaces/Test_GrSurfaces.cpp @@ -1152,24 +1152,25 @@ SPECTRE_TEST_CASE("Unit.GrSurfaces.RadialDistance", // Check cases where one has more resolution than the other gr::surfaces::radial_distance( make_not_null(&radial_dist), strahlkorper_a, - ylm::Strahlkorper(strahlkorper_b.l_max() - 1, strahlkorper_b.m_max() - 1, - strahlkorper_b)); + ylm::Strahlkorper(strahlkorper_b.l_max() - 1, + strahlkorper_b.m_max() - 1, + strahlkorper_b)); CHECK_ITERABLE_APPROX(radial_dist, expected_radial_dist_a_minus_b); - gr::surfaces::radial_distance( - make_not_null(&radial_dist), - ylm::Strahlkorper(strahlkorper_b.l_max() - 1, strahlkorper_b.m_max() - 1, - strahlkorper_b), - strahlkorper_a); + gr::surfaces::radial_distance(make_not_null(&radial_dist), + ylm::Strahlkorper( + strahlkorper_b.l_max() - 1, + strahlkorper_b.m_max() - 1, strahlkorper_b), + strahlkorper_a); CHECK_ITERABLE_APPROX(radial_dist, expected_radial_dist_b_minus_a); gr::surfaces::radial_distance( make_not_null(&radial_dist), strahlkorper_a, - ylm::Strahlkorper(strahlkorper_b.l_max(), strahlkorper_b.m_max() - 1, - strahlkorper_b)); + ylm::Strahlkorper( + strahlkorper_b.l_max(), strahlkorper_b.m_max() - 1, strahlkorper_b)); CHECK_ITERABLE_APPROX(radial_dist, expected_radial_dist_a_minus_b); gr::surfaces::radial_distance( make_not_null(&radial_dist), - ylm::Strahlkorper(strahlkorper_b.l_max(), strahlkorper_b.m_max() - 1, - strahlkorper_b), + ylm::Strahlkorper( + strahlkorper_b.l_max(), strahlkorper_b.m_max() - 1, strahlkorper_b), strahlkorper_a); CHECK_ITERABLE_APPROX(radial_dist, expected_radial_dist_b_minus_a);