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);