From c27dd9299aea748f0ffc4a249b7c43fd8c14ed0d Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Wed, 17 Dec 2025 15:28:45 +0100 Subject: [PATCH 1/7] Add DensityProfileCoefficients to template parameters of GMGPolar in ConfigParser --- include/ConfigParser/config_parser.h | 4 +-- include/ConfigParser/test_selection.h | 4 +++ include/GMGPolar/gmgpolar.h | 2 +- .../densityProfileCoefficients.h | 22 +++++++++++- src/ConfigParser/config_parser.cpp | 2 +- src/ConfigParser/select_test_case.cpp | 35 ++++++++++++------- 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/include/ConfigParser/config_parser.h b/include/ConfigParser/config_parser.h index c8d7f01f..cb4661b7 100644 --- a/include/ConfigParser/config_parser.h +++ b/include/ConfigParser/config_parser.h @@ -25,7 +25,7 @@ class ConfigParser // Test Case const DomainGeometryVariant& domainGeometry() const; - const DensityProfileCoefficients& densityProfileCoefficients() const; + const DensityProfileCoefficientsVariant& densityProfileCoefficients() const; const BoundaryConditions& boundaryConditions() const; const SourceTerm& sourceTerm() const; const ExactSolution& exactSolution() const; @@ -62,7 +62,7 @@ class ConfigParser cmdline::parser parser_; // Input Functions std::unique_ptr domain_geometry_; - std::unique_ptr density_profile_coefficients_; + std::unique_ptr density_profile_coefficients_; std::unique_ptr boundary_conditions_; std::unique_ptr source_term_; std::unique_ptr exact_solution_; diff --git a/include/ConfigParser/test_selection.h b/include/ConfigParser/test_selection.h index 891e9dca..922a67d7 100644 --- a/include/ConfigParser/test_selection.h +++ b/include/ConfigParser/test_selection.h @@ -3,3 +3,7 @@ #include "../../include/GMGPolar/test_cases.h" using DomainGeometryVariant = std::variant; + +using DensityProfileCoefficientsVariant = + std::variant; diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index d8dbdf0d..228a1812 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -25,7 +25,7 @@ class LevelCache; #include "test_cases.h" #include "igmgpolar.h" -template +template class GMGPolar : public IGMGPolar { public: diff --git a/include/InputFunctions/densityProfileCoefficients.h b/include/InputFunctions/densityProfileCoefficients.h index 7cc1339b..a4591b0e 100644 --- a/include/InputFunctions/densityProfileCoefficients.h +++ b/include/InputFunctions/densityProfileCoefficients.h @@ -11,4 +11,24 @@ class DensityProfileCoefficients // Only used in custom mesh generation -> refinement_radius virtual double getAlphaJump() const = 0; -}; \ No newline at end of file +}; + +namespace concepts +{ + +template +concept DensityProfileCoefficients = + !std::same_as && requires(const T coeffs, double r, double theta) +{ + { + coeffs.alpha(r, theta) + } -> std::convertible_to; + { + coeffs.beta(r, theta) + } -> std::convertible_to; + { + coeffs.getAlphaJump() + } -> std::convertible_to; +}; + +} // namespace concepts diff --git a/src/ConfigParser/config_parser.cpp b/src/ConfigParser/config_parser.cpp index dd0227f9..e61ddb51 100644 --- a/src/ConfigParser/config_parser.cpp +++ b/src/ConfigParser/config_parser.cpp @@ -378,7 +378,7 @@ const DomainGeometryVariant& ConfigParser::domainGeometry() const return *domain_geometry_.get(); } -const DensityProfileCoefficients& ConfigParser::densityProfileCoefficients() const +const DensityProfileCoefficientsVariant& ConfigParser::densityProfileCoefficients() const { return *density_profile_coefficients_.get(); } diff --git a/src/ConfigParser/select_test_case.cpp b/src/ConfigParser/select_test_case.cpp index 08e62292..4477f338 100644 --- a/src/ConfigParser/select_test_case.cpp +++ b/src/ConfigParser/select_test_case.cpp @@ -3,15 +3,17 @@ std::unique_ptr ConfigParser::solver() const { - const PolarGrid& grid = grid_; - const DensityProfileCoefficients& density_profile_coefficients = *density_profile_coefficients_; + const PolarGrid& grid = grid_; return std::visit( - [&grid, &density_profile_coefficients](auto const& domain_geometry) { - using DomainGeomType = std::decay_t; + [&grid](auto const& domain_geometry, auto const& density_profile_coefficients) { + using DomainGeomType = std::decay_t; + using DensityProfileCoefficientsType = std::decay_t; + return static_cast>( - std::make_unique>(grid, domain_geometry, density_profile_coefficients)); + std::make_unique>( + grid, domain_geometry, density_profile_coefficients)); }, - *domain_geometry_); + *domain_geometry_, *density_profile_coefficients_); } void ConfigParser::selectTestCase(GeometryType geometry_type, ProblemType problem_type, AlphaCoeff alpha_type, @@ -44,16 +46,19 @@ void ConfigParser::selectTestCase(GeometryType geometry_type, ProblemType proble /* Density Profile Coefficients */ switch (alpha_type) { case AlphaCoeff::POISSON: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(PoissonCoefficients(Rmax, alpha_jump)); break; case AlphaCoeff::SONNENDRUCKER: switch (beta_type) { case BetaCoeff::ZERO: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(SonnendruckerCoefficients(Rmax, alpha_jump)); break; case BetaCoeff::ALPHA_INVERSE: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(SonnendruckerGyroCoefficients(Rmax, alpha_jump)); break; default: throw std::runtime_error("Invalid beta.\n"); @@ -63,10 +68,12 @@ void ConfigParser::selectTestCase(GeometryType geometry_type, ProblemType proble case AlphaCoeff::ZONI: switch (beta_type) { case BetaCoeff::ZERO: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(ZoniCoefficients(Rmax, alpha_jump)); break; case BetaCoeff::ALPHA_INVERSE: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(ZoniGyroCoefficients(Rmax, alpha_jump)); break; default: throw std::runtime_error("Invalid beta.\n"); @@ -76,10 +83,12 @@ void ConfigParser::selectTestCase(GeometryType geometry_type, ProblemType proble case AlphaCoeff::ZONI_SHIFTED: switch (beta_type) { case BetaCoeff::ZERO: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(ZoniShiftedCoefficients(Rmax, alpha_jump)); break; case BetaCoeff::ALPHA_INVERSE: - density_profile_coefficients_ = std::make_unique(Rmax, alpha_jump); + density_profile_coefficients_ = + std::make_unique(ZoniShiftedGyroCoefficients(Rmax, alpha_jump)); break; default: throw std::runtime_error("Invalid beta.\n"); From cda52115c7cae857f08913f4c2d7d6127b047a1d Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Wed, 17 Dec 2025 15:41:04 +0100 Subject: [PATCH 2/7] Update class prototypes --- include/GMGPolar/build_rhs_f.h | 4 ++-- include/GMGPolar/gmgpolar.h | 4 +++- include/GMGPolar/igmgpolar.h | 4 +--- include/GMGPolar/setup.h | 4 ++-- include/GMGPolar/writeToVTK.h | 8 ++++---- src/GMGPolar/gmgpolar.cpp | 3 +-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/GMGPolar/build_rhs_f.h b/include/GMGPolar/build_rhs_f.h index 031d4bb9..6915c0cd 100644 --- a/include/GMGPolar/build_rhs_f.h +++ b/include/GMGPolar/build_rhs_f.h @@ -1,7 +1,7 @@ #include "../../include/GMGPolar/gmgpolar.h" -template -void GMGPolar::discretize_rhs_f(const Level& level, Vector rhs_f) +template +void GMGPolar::discretize_rhs_f(const Level& level, Vector rhs_f) { const PolarGrid& grid = level.grid(); assert(rhs_f.size() == static_cast(grid.numberOfNodes())); diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index 228a1812..41db6359 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -41,8 +41,9 @@ class GMGPolar : public IGMGPolar // - density_profile_coefficients: Coefficients \alpha and \beta defining the PDE. GMGPolar(const PolarGrid& grid, const DomainGeometry& domain_geometry, const DensityProfileCoefficients& density_profile_coefficients) - : IGMGPolar(grid, density_profile_coefficients) + : IGMGPolar(grid) , domain_geometry_(domain_geometry) + , density_profile_coefficients_(density_profile_coefficients) { } @@ -57,6 +58,7 @@ class GMGPolar : public IGMGPolar /* Grid Configuration & Input Functions */ /* ------------------------------------ */ const DomainGeometry& domain_geometry_; + const DensityProfileCoefficients& density_profile_coefficients_; /* --------------- */ /* Setup Functions */ diff --git a/include/GMGPolar/igmgpolar.h b/include/GMGPolar/igmgpolar.h index 7d72864e..7d4d8692 100644 --- a/include/GMGPolar/igmgpolar.h +++ b/include/GMGPolar/igmgpolar.h @@ -35,8 +35,7 @@ class IGMGPolar // with Dirichlet boundary condition u = u_D on \partial \Omega. // Parameters: // - grid: Cartesian mesh discretizing the computational domain. - // - density_profile_coefficients: Coefficients \alpha and \beta defining the PDE. - IGMGPolar(const PolarGrid& grid, const DensityProfileCoefficients& density_profile_coefficients); + IGMGPolar(const PolarGrid& grid); /* ---------------------------------------------------------------------- */ /* General output & visualization */ @@ -194,7 +193,6 @@ class IGMGPolar /* Grid Configuration & Input Functions */ /* ------------------------------------ */ const PolarGrid& grid_; - const DensityProfileCoefficients& density_profile_coefficients_; const ExactSolution* exact_solution_; // Optional exact solution for validation /* ------------------ */ diff --git a/include/GMGPolar/setup.h b/include/GMGPolar/setup.h index 5372aa27..9a1042b1 100644 --- a/include/GMGPolar/setup.h +++ b/include/GMGPolar/setup.h @@ -1,6 +1,6 @@ -template -void GMGPolar::setup() +template +void GMGPolar::setup() { LIKWID_START("Setup"); auto start_setup = std::chrono::high_resolution_clock::now(); diff --git a/include/GMGPolar/writeToVTK.h b/include/GMGPolar/writeToVTK.h index 2f79d1b7..8eb8868f 100644 --- a/include/GMGPolar/writeToVTK.h +++ b/include/GMGPolar/writeToVTK.h @@ -1,7 +1,7 @@ #include "../../include/GMGPolar/gmgpolar.h" -template -void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const PolarGrid& grid) +template +void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const PolarGrid& grid) { const auto filename = file_path.stem().string() + ".vtu"; @@ -59,8 +59,8 @@ void GMGPolar::writeToVTK(const std::filesystem::path& file_path << "\n"; } -template -void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const Level& level, +template +void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const Level& level, ConstVector grid_function) { const PolarGrid& grid = level.grid(); diff --git a/src/GMGPolar/gmgpolar.cpp b/src/GMGPolar/gmgpolar.cpp index 4c71c680..9f9ed52d 100644 --- a/src/GMGPolar/gmgpolar.cpp +++ b/src/GMGPolar/gmgpolar.cpp @@ -3,9 +3,8 @@ /* ---------------------------------------------------------------------- */ /* Constructor & Initialization */ /* ---------------------------------------------------------------------- */ -IGMGPolar::IGMGPolar(const PolarGrid& grid, const DensityProfileCoefficients& density_profile_coefficients) +IGMGPolar::IGMGPolar(const PolarGrid& grid) : grid_(grid) - , density_profile_coefficients_(density_profile_coefficients) , exact_solution_(nullptr) // General solver output and visualization settings , verbose_(0) From e1a57346588dc96eb94680c70f6aef57ddac36a9 Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Wed, 17 Dec 2025 15:41:15 +0100 Subject: [PATCH 3/7] Ensure DensityProfileCoefficients type is available --- tests/GMGPolar/convergence_order.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/GMGPolar/convergence_order.cpp b/tests/GMGPolar/convergence_order.cpp index 145d21b0..b5b1068c 100644 --- a/tests/GMGPolar/convergence_order.cpp +++ b/tests/GMGPolar/convergence_order.cpp @@ -152,6 +152,7 @@ std::vector refine(std::vector const& original_points) return refined; } +template std::tuple get_gmgpolar_error(PolarGrid const& grid, CzarnyGeometry const& domain_geometry, DensityProfileCoefficients const& coefficients, BoundaryConditions const& boundary_conditions, From 6d0685aa2af902dcac7b8c98018360b80de627c0 Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Wed, 17 Dec 2025 15:41:46 +0100 Subject: [PATCH 4/7] Clang formatting --- include/GMGPolar/writeToVTK.h | 8 +++++--- .../InputFunctions/densityProfileCoefficients.h | 17 +++++------------ tests/GMGPolar/convergence_order.cpp | 11 +++++------ 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/include/GMGPolar/writeToVTK.h b/include/GMGPolar/writeToVTK.h index 8eb8868f..690b9efc 100644 --- a/include/GMGPolar/writeToVTK.h +++ b/include/GMGPolar/writeToVTK.h @@ -1,7 +1,8 @@ #include "../../include/GMGPolar/gmgpolar.h" template -void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const PolarGrid& grid) +void GMGPolar::writeToVTK(const std::filesystem::path& file_path, + const PolarGrid& grid) { const auto filename = file_path.stem().string() + ".vtu"; @@ -60,8 +61,9 @@ void GMGPolar::writeToVTK(const std: } template -void GMGPolar::writeToVTK(const std::filesystem::path& file_path, const Level& level, - ConstVector grid_function) +void GMGPolar::writeToVTK(const std::filesystem::path& file_path, + const Level& level, + ConstVector grid_function) { const PolarGrid& grid = level.grid(); const LevelCache& level_cache = level.levelCache(); diff --git a/include/InputFunctions/densityProfileCoefficients.h b/include/InputFunctions/densityProfileCoefficients.h index a4591b0e..c7b08353 100644 --- a/include/InputFunctions/densityProfileCoefficients.h +++ b/include/InputFunctions/densityProfileCoefficients.h @@ -18,17 +18,10 @@ namespace concepts template concept DensityProfileCoefficients = - !std::same_as && requires(const T coeffs, double r, double theta) -{ - { - coeffs.alpha(r, theta) - } -> std::convertible_to; - { - coeffs.beta(r, theta) - } -> std::convertible_to; - { - coeffs.getAlphaJump() - } -> std::convertible_to; -}; + !std::same_as && requires(const T coeffs, double r, double theta) { + { coeffs.alpha(r, theta) } -> std::convertible_to; + { coeffs.beta(r, theta) } -> std::convertible_to; + { coeffs.getAlphaJump() } -> std::convertible_to; + }; } // namespace concepts diff --git a/tests/GMGPolar/convergence_order.cpp b/tests/GMGPolar/convergence_order.cpp index b5b1068c..fa2ae679 100644 --- a/tests/GMGPolar/convergence_order.cpp +++ b/tests/GMGPolar/convergence_order.cpp @@ -152,12 +152,11 @@ std::vector refine(std::vector const& original_points) return refined; } -template -std::tuple get_gmgpolar_error(PolarGrid const& grid, CzarnyGeometry const& domain_geometry, - DensityProfileCoefficients const& coefficients, - BoundaryConditions const& boundary_conditions, - SourceTerm const& source_term, ExactSolution const& solution, - ExtrapolationType extrapolation) +template +std::tuple +get_gmgpolar_error(PolarGrid const& grid, CzarnyGeometry const& domain_geometry, + DensityProfileCoefficients const& coefficients, BoundaryConditions const& boundary_conditions, + SourceTerm const& source_term, ExactSolution const& solution, ExtrapolationType extrapolation) { GMGPolar gmgpolar(grid, domain_geometry, coefficients); gmgpolar.setSolution(&solution); From facae265801ad2addbb0629f1faadbf4b197e706 Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Wed, 17 Dec 2025 15:43:33 +0100 Subject: [PATCH 5/7] Clean up includes --- include/GMGPolar/gmgpolar.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index 41db6359..85bc4d26 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -1,28 +1,13 @@ #pragma once -#include #include #include -#include #include -#include #include -class Level; -class LevelCache; - -#include "../InputFunctions/boundaryConditions.h" #include "../InputFunctions/densityProfileCoefficients.h" #include "../InputFunctions/domainGeometry.h" -#include "../InputFunctions/exactSolution.h" -#include "../InputFunctions/sourceTerm.h" -#include "../Interpolation/interpolation.h" -#include "../Level/level.h" -#include "../LinearAlgebra/vector.h" -#include "../LinearAlgebra/vector_operations.h" -#include "../PolarGrid/polargrid.h" -#include "../common/global_definitions.h" -#include "test_cases.h" + #include "igmgpolar.h" template From 77dbbddf29f9a3d08a5a057a6114ff96195a37cb Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Thu, 18 Dec 2025 11:25:29 +0100 Subject: [PATCH 6/7] Improve coverage --- tests/ConfigParser/config_parser.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/ConfigParser/config_parser.cpp b/tests/ConfigParser/config_parser.cpp index 3e1cf89b..9fb33ca8 100644 --- a/tests/ConfigParser/config_parser.cpp +++ b/tests/ConfigParser/config_parser.cpp @@ -198,6 +198,31 @@ TEST_P(ConfigParserTest, ParseAllGeometryAndProblemCombinations) EXPECT_DOUBLE_EQ(parser.absoluteTolerance().value(), absoluteTolerance); ASSERT_TRUE(parser.relativeTolerance().has_value()); EXPECT_DOUBLE_EQ(parser.relativeTolerance().value(), relativeTolerance); + + // Solver + std::unique_ptr solver = parser.solver(); + EXPECT_EQ(solver->verbose(), verbose); + EXPECT_EQ(solver->paraview(), paraview); + EXPECT_EQ(solver->maxOpenMPThreads(), maxOpenMPThreads); + EXPECT_DOUBLE_EQ(solver->threadReductionFactor(), threadReductionFactor); + EXPECT_EQ(solver->DirBC_Interior(), DirBC_Interior); + EXPECT_EQ(solver->stencilDistributionMethod(), static_cast(stencilDistributionMethod)); + EXPECT_EQ(solver->cacheDensityProfileCoefficients(), cacheDensityProfileCoefficients); + EXPECT_EQ(solver->cacheDomainGeometry(), cacheDomainGeometry); + EXPECT_EQ(solver->FMG(), FMG); + EXPECT_EQ(solver->FMG_iterations(), FMG_iterations); + EXPECT_EQ(solver->FMG_cycle(), static_cast(FMG_cycle)); + EXPECT_EQ(solver->extrapolation(), static_cast(extrapolation)); + EXPECT_EQ(solver->maxLevels(), maxLevels); + EXPECT_EQ(solver->preSmoothingSteps(), preSmoothingSteps); + EXPECT_EQ(solver->postSmoothingSteps(), postSmoothingSteps); + EXPECT_EQ(solver->multigridCycle(), static_cast(multigridCycle)); + EXPECT_EQ(solver->maxIterations(), maxIterations); + EXPECT_EQ(solver->residualNormType(), static_cast(residualNormType)); + ASSERT_TRUE(solver->absoluteTolerance().has_value()); + EXPECT_DOUBLE_EQ(solver->absoluteTolerance().value(), absoluteTolerance); + ASSERT_TRUE(solver->relativeTolerance().has_value()); + EXPECT_DOUBLE_EQ(solver->relativeTolerance().value(), relativeTolerance); } // Define test cases covering all combinations From 166bc2d9797e118271ec12acbecd2758197f391d Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Thu, 18 Dec 2025 15:41:10 +0100 Subject: [PATCH 7/7] Only check values that are set --- tests/ConfigParser/config_parser.cpp | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/tests/ConfigParser/config_parser.cpp b/tests/ConfigParser/config_parser.cpp index 9fb33ca8..3d501aae 100644 --- a/tests/ConfigParser/config_parser.cpp +++ b/tests/ConfigParser/config_parser.cpp @@ -201,28 +201,7 @@ TEST_P(ConfigParserTest, ParseAllGeometryAndProblemCombinations) // Solver std::unique_ptr solver = parser.solver(); - EXPECT_EQ(solver->verbose(), verbose); - EXPECT_EQ(solver->paraview(), paraview); - EXPECT_EQ(solver->maxOpenMPThreads(), maxOpenMPThreads); - EXPECT_DOUBLE_EQ(solver->threadReductionFactor(), threadReductionFactor); - EXPECT_EQ(solver->DirBC_Interior(), DirBC_Interior); - EXPECT_EQ(solver->stencilDistributionMethod(), static_cast(stencilDistributionMethod)); - EXPECT_EQ(solver->cacheDensityProfileCoefficients(), cacheDensityProfileCoefficients); - EXPECT_EQ(solver->cacheDomainGeometry(), cacheDomainGeometry); - EXPECT_EQ(solver->FMG(), FMG); - EXPECT_EQ(solver->FMG_iterations(), FMG_iterations); - EXPECT_EQ(solver->FMG_cycle(), static_cast(FMG_cycle)); - EXPECT_EQ(solver->extrapolation(), static_cast(extrapolation)); - EXPECT_EQ(solver->maxLevels(), maxLevels); - EXPECT_EQ(solver->preSmoothingSteps(), preSmoothingSteps); - EXPECT_EQ(solver->postSmoothingSteps(), postSmoothingSteps); - EXPECT_EQ(solver->multigridCycle(), static_cast(multigridCycle)); - EXPECT_EQ(solver->maxIterations(), maxIterations); - EXPECT_EQ(solver->residualNormType(), static_cast(residualNormType)); - ASSERT_TRUE(solver->absoluteTolerance().has_value()); - EXPECT_DOUBLE_EQ(solver->absoluteTolerance().value(), absoluteTolerance); - ASSERT_TRUE(solver->relativeTolerance().has_value()); - EXPECT_DOUBLE_EQ(solver->relativeTolerance().value(), relativeTolerance); + EXPECT_EQ(&solver->grid(), &parser.grid()); } // Define test cases covering all combinations