From 35f37de6471d6aa6e6442bca247c3da168d4b19f Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 11:11:50 +0200 Subject: [PATCH 01/21] Fix call to initializeLineSplitting on GPU --- src/PolarGrid/polargrid.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PolarGrid/polargrid.cpp b/src/PolarGrid/polargrid.cpp index 5337faa2..668c6631 100644 --- a/src/PolarGrid/polargrid.cpp +++ b/src/PolarGrid/polargrid.cpp @@ -214,14 +214,15 @@ void PolarGrid::initializeLineSplitting(std::optional split } } else { + auto h_radius = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, radii_); number_smoother_circles_ = 2; /* We assume numberSmootherCircles_ >= 2 in the further implementation */ for (int i_r = 2; i_r < nr() - 2; i_r++) { /* We assume lengthRadialSmoother_ >= 3 in the further implementation */ const double uniform_theta_k = (2 * M_PI) / ntheta(); - const double radial_dist_h = radius(i_r + 1) - radius(i_r); + const double radial_dist_h = h_radius[i_r + 1] - h_radius[i_r]; const double q = uniform_theta_k / radial_dist_h; - if (q * radius(i_r) > 1.0) { + if (q * h_radius[i_r] > 1.0) { number_smoother_circles_ = i_r; break; } From 06a91d60c76a31d1cacffe193e3749289c274452 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 11:12:10 +0200 Subject: [PATCH 02/21] Port applySystemOperator and applyExtrapolation to GPU --- include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/solver.h | 30 ++++++++++++------- include/Level/level.h | 2 +- include/Level/level.inl | 4 +-- include/Residual/ResidualGive/applyAGive.inl | 7 +---- include/Residual/ResidualGive/residualGive.h | 2 +- .../Residual/ResidualGive/residualGive.inl | 5 ++-- include/Residual/ResidualTake/applyATake.inl | 7 +---- include/Residual/ResidualTake/residualTake.h | 2 +- .../Residual/ResidualTake/residualTake.inl | 5 ++-- include/Residual/residual.h | 2 +- 11 files changed, 35 insertions(+), 33 deletions(-) diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index 92c7a1e9..0a7999bd 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -154,7 +154,7 @@ class GMGPolar : public IGMGPolar /* --------------- */ /* Solve Functions */ - void applyExtrapolation(int current_level, HostVector fine_values, HostConstVector coarse_values); + void applyExtrapolation(int current_level, Vector fine_values, ConstVector coarse_values); private: /* --------------- */ diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index 980887fb..eb6db03e 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -336,13 +336,20 @@ void GMGPolar::solvePCG(double& init while (number_of_iterations_ < max_iterations_) { // A_p = A * p - level.applySystemOperator(level.residual(), pcg_search_direction_); + auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); + auto pcg_search_direction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), pcg_search_direction_); + level.applySystemOperator(level_residual, pcg_search_direction); + Kokkos::deep_copy(level.residual(), level_residual); if (extrapolation_ != ExtrapolationType::NONE) { assert(number_of_levels_ > 1); Level& next_level = levels_[level.level_depth() + 1]; injection(0, next_level.solution(), pcg_search_direction_); - next_level.applySystemOperator(next_level.residual(), next_level.solution()); - applyExtrapolation(0, level.residual(), next_level.residual()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + next_level.applySystemOperator(next_level_residual, next_level_solution); + applyExtrapolation(0, level_residual, next_level_residual); + Kokkos::deep_copy(level.residual(), level_residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); } // alpha = (r^T * z) / (p^T * A*p) @@ -479,7 +486,10 @@ void GMGPolar::updateResidualNorms( Level& next_level = levels_[level.level_depth() + 1]; injection(level.level_depth(), next_level.solution(), level.solution()); next_level.computeResidual(next_level.residual(), next_level.rhs(), next_level.solution()); - applyExtrapolation(level.level_depth(), level.residual(), next_level.residual()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); + applyExtrapolation(level.level_depth(), level_residual, next_level_residual); + Kokkos::deep_copy(level.residual(), level_residual); } current_residual_norm = residualNorm(residual_norm_type_, level, level.residual()); @@ -523,11 +533,11 @@ double GMGPolar::residualNorm( template void GMGPolar::applyExtrapolation(int current_level, - HostVector fine_values, - HostConstVector coarse_values) + Vector fine_values, + ConstVector coarse_values) { - const PolarGrid fineGrid(levels_[current_level].grid()); - const PolarGrid coarseGrid(levels_[current_level + 1].grid()); + const PolarGrid& fineGrid(levels_[current_level].grid()); + const PolarGrid& coarseGrid(levels_[current_level + 1].grid()); assert(std::ssize(fine_values) == fineGrid.numberOfNodes()); assert(std::ssize(coarse_values) == coarseGrid.numberOfNodes()); @@ -539,7 +549,7 @@ void GMGPolar::applyExtrapolation(in /* For loop matches circular access pattern */ Kokkos::parallel_for( "Extrapolation: Apply Extrapolation (Circular)", - Kokkos::MDRangePolicy>( + Kokkos::MDRangePolicy>( {0, 0}, {fineGrid.numberSmootherCircles(), fineGrid.ntheta()}), KOKKOS_LAMBDA(const int i_r, const int i_theta) { const int fine_idx = fineGrid.index(i_r, i_theta); @@ -556,7 +566,7 @@ void GMGPolar::applyExtrapolation(in /* For loop matches radial access pattern */ Kokkos::parallel_for( "Extrapolation: Apply Extrapolation (Radial)", - Kokkos::MDRangePolicy>({0, fineGrid.numberSmootherCircles()}, + Kokkos::MDRangePolicy>({0, fineGrid.numberSmootherCircles()}, {fineGrid.ntheta(), fineGrid.nr()}), KOKKOS_LAMBDA(const int i_theta, const int i_r) { const int fine_idx = fineGrid.index(i_r, i_theta); diff --git a/include/Level/level.h b/include/Level/level.h index 363f4c4b..c7545b56 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -96,7 +96,7 @@ class Level // Apply Residual // void initializeResidual(const bool DirBC_Interior, const StencilDistributionMethod stencil_distribution_method); void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const; - void applySystemOperator(HostVector result, HostConstVector x) const; + void applySystemOperator(Vector result, ConstVector x) const; // ------------------- // // Solve coarse System // diff --git a/include/Level/level.inl b/include/Level/level.inl index bb570e13..13bb18ad 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -114,8 +114,8 @@ void Level::computeResidual(HostVect op_residual_->computeResidual(result, rhs, x); } template -void Level::applySystemOperator(HostVector result, - HostConstVector x) const +void Level::applySystemOperator(Vector result, + ConstVector x) const { if (!op_residual_) throw std::runtime_error("Residual not initialized."); diff --git a/include/Residual/ResidualGive/applyAGive.inl b/include/Residual/ResidualGive/applyAGive.inl index 0e2a4526..c5c0fe17 100644 --- a/include/Residual/ResidualGive/applyAGive.inl +++ b/include/Residual/ResidualGive/applyAGive.inl @@ -195,11 +195,8 @@ static KOKKOS_INLINE_FUNCTION void node_apply_a_give(int i_r, int i_theta, const } // namespace residual_give template -void ResidualGive::applySystemOperator(HostVector h_result, HostConstVector h_x) const +void ResidualGive::applySystemOperator(Vector result, ConstVector x) const { - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - assert(result.size() == x.size()); const PolarGrid& grid = Residual::grid_; @@ -264,6 +261,4 @@ void ResidualGive::applySystemOperator(HostVector h_resu }); Kokkos::fence(); } - - Kokkos::deep_copy(h_result, result); } diff --git a/include/Residual/ResidualGive/residualGive.h b/include/Residual/ResidualGive/residualGive.h index cdbaa0f5..e90f2657 100644 --- a/include/Residual/ResidualGive/residualGive.h +++ b/include/Residual/ResidualGive/residualGive.h @@ -13,7 +13,7 @@ class ResidualGive : public Residual const bool DirBC_Interior); ~ResidualGive() override = default; - void applySystemOperator(HostVector result, HostConstVector x) const final; + void applySystemOperator(Vector result, ConstVector x) const final; void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const final; }; diff --git a/include/Residual/ResidualGive/residualGive.inl b/include/Residual/ResidualGive/residualGive.inl index f6680d4e..61584148 100644 --- a/include/Residual/ResidualGive/residualGive.inl +++ b/include/Residual/ResidualGive/residualGive.inl @@ -15,10 +15,11 @@ void ResidualGive::computeResidual(HostVector h_result, { assert(h_result.size() == h_x.size()); - applySystemOperator(h_result, h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); + auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + + applySystemOperator(result, x); // Subtract A*x from rhs to get the residual. const int n = result.size(); diff --git a/include/Residual/ResidualTake/applyATake.inl b/include/Residual/ResidualTake/applyATake.inl index 5e4d9665..9442515d 100644 --- a/include/Residual/ResidualTake/applyATake.inl +++ b/include/Residual/ResidualTake/applyATake.inl @@ -64,13 +64,10 @@ node_apply_a_take(const int i_r, const int i_theta, const PolarGrid -void ResidualTake::applySystemOperator(HostVector h_result, HostConstVector h_x) const +void ResidualTake::applySystemOperator(Vector result, ConstVector x) const { using residual_take::node_apply_a_take; - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - assert(result.size() == x.size()); const PolarGrid& grid = Residual::grid_; @@ -113,6 +110,4 @@ void ResidualTake::applySystemOperator(HostVector h_resu }); Kokkos::fence(); - - Kokkos::deep_copy(h_result, result); } diff --git a/include/Residual/ResidualTake/residualTake.h b/include/Residual/ResidualTake/residualTake.h index 8af3bd9f..e7c372d6 100644 --- a/include/Residual/ResidualTake/residualTake.h +++ b/include/Residual/ResidualTake/residualTake.h @@ -14,7 +14,7 @@ class ResidualTake : public Residual KOKKOS_DEFAULTED_FUNCTION ResidualTake(const ResidualTake&) = default; KOKKOS_DEFAULTED_FUNCTION ~ResidualTake() override = default; - void applySystemOperator(HostVector result, HostConstVector x) const final; + void applySystemOperator(Vector result, ConstVector x) const final; void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const final; }; diff --git a/include/Residual/ResidualTake/residualTake.inl b/include/Residual/ResidualTake/residualTake.inl index 8f598d67..b7ddd6b9 100644 --- a/include/Residual/ResidualTake/residualTake.inl +++ b/include/Residual/ResidualTake/residualTake.inl @@ -15,10 +15,11 @@ void ResidualTake::computeResidual(HostVector h_result, { assert(h_result.size() == h_x.size()); - applySystemOperator(h_result, h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); + auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + + applySystemOperator(result, x); // Subtract A*x from rhs to get the residual. const int n = result.size(); diff --git a/include/Residual/residual.h b/include/Residual/residual.h index fcb04d00..4c08923b 100644 --- a/include/Residual/residual.h +++ b/include/Residual/residual.h @@ -25,7 +25,7 @@ class Residual } virtual ~Residual() = default; - virtual void applySystemOperator(HostVector result, HostConstVector x) const = 0; + virtual void applySystemOperator(Vector result, ConstVector x) const = 0; virtual void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const = 0; From 4b8a7a849cf224339805812c74919d8ef7ff289c Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 12:45:08 +0200 Subject: [PATCH 03/21] Port applyInjection and injection to GPU --- .../extrapolated_multigrid_F_Cycle.h | 5 ++++- .../extrapolated_multigrid_V_Cycle.h | 5 ++++- .../extrapolated_multigrid_W_Cycle.h | 5 ++++- include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/solver.h | 14 ++++++++++---- include/GMGPolar/utils.h | 8 ++++---- include/Interpolation/interpolation.h | 4 ++-- src/Interpolation/injection.cpp | 18 +++++++++--------- 8 files changed, 38 insertions(+), 23 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index a647a905..514acb49 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -47,7 +47,10 @@ void GMGPolar::extrapolated_multigri extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); // f_{l-1} - A_{l-1}* Inject(u_l) - injection(level.level_depth(), next_level.solution(), solution); + auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + injection(level.level_depth(), next_level_solution, d_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 87c916aa..5a71cdc9 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -47,7 +47,10 @@ void GMGPolar::extrapolated_multigri extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); // f_{l-1} - A_{l-1}* Inject(u_l) - injection(level.level_depth(), next_level.solution(), solution); + auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + injection(level.level_depth(), next_level_solution, d_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index 67e3a1d0..e0a59c99 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -47,7 +47,10 @@ void GMGPolar::extrapolated_multigri extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); // f_{l-1} - A_{l-1}* Inject(u_l) - injection(level.level_depth(), next_level.solution(), solution); + auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + injection(level.level_depth(), next_level_solution, d_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index 0a7999bd..b3c71d6d 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -209,7 +209,7 @@ class GMGPolar : public IGMGPolar /* Interpolation functions */ void prolongation(int current_level, HostVector result, HostConstVector x) const; void restriction(int current_level, HostVector result, HostConstVector x) const; - void injection(int current_level, HostVector result, HostConstVector x) const; + void injection(int current_level, Vector result, ConstVector x) const; void extrapolatedProlongation(int current_level, HostVector result, HostConstVector x) const; void extrapolatedRestriction(int current_level, HostVector result, HostConstVector x) const; void FMGInterpolation(int current_level, HostVector result, HostConstVector x) const; diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index eb6db03e..54d03ebe 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -28,7 +28,10 @@ void GMGPolar::solve(const BoundaryC // Inject rhs if there is a next level if (level_depth + 1 < initial_rhs_f_levels) { Level& next_level = levels_[level_depth + 1]; - injection(level_depth, next_level.rhs(), current_level.rhs()); + auto current_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + injection(level_depth, next_level_rhs, current_level_rhs); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); } // Discretize the rhs for the current level discretize_rhs_f(current_level, current_level.rhs()); @@ -343,9 +346,9 @@ void GMGPolar::solvePCG(double& init if (extrapolation_ != ExtrapolationType::NONE) { assert(number_of_levels_ > 1); Level& next_level = levels_[level.level_depth() + 1]; - injection(0, next_level.solution(), pcg_search_direction_); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + injection(0, next_level_solution, pcg_search_direction); next_level.applySystemOperator(next_level_residual, next_level_solution); applyExtrapolation(0, level_residual, next_level_residual); Kokkos::deep_copy(level.residual(), level_residual); @@ -484,7 +487,10 @@ void GMGPolar::updateResidualNorms( level.computeResidual(level.residual(), level.rhs(), level.solution()); if (extrapolation_ != ExtrapolationType::NONE) { Level& next_level = levels_[level.level_depth() + 1]; - injection(level.level_depth(), next_level.solution(), level.solution()); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + injection(level.level_depth(), next_level_solution, solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.residual(), next_level.rhs(), next_level.solution()); auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); diff --git a/include/GMGPolar/utils.h b/include/GMGPolar/utils.h index 2804e51a..ebd76486 100644 --- a/include/GMGPolar/utils.h +++ b/include/GMGPolar/utils.h @@ -30,15 +30,15 @@ void GMGPolar::restriction(int curre } template -void GMGPolar::injection(int current_level, HostVector result, - HostConstVector x) const +void GMGPolar::injection(int current_level, Vector result, + ConstVector x) const { assert(current_level < number_of_levels_ - 1 && 0 <= current_level); if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid(levels_[current_level].grid()); - PolarGrid next_grid(levels_[current_level + 1].grid()); + PolarGrid current_grid(levels_[current_level].grid()); + PolarGrid next_grid(levels_[current_level + 1].grid()); interpolation_->applyInjection(current_grid, next_grid, result, x); } diff --git a/include/Interpolation/interpolation.h b/include/Interpolation/interpolation.h index 7198458f..07e2bec1 100644 --- a/include/Interpolation/interpolation.h +++ b/include/Interpolation/interpolation.h @@ -19,8 +19,8 @@ class Interpolation explicit Interpolation(bool DirBC_Interior); /* Remark: This injection is not scaled. */ - void applyInjection(const PolarGrid& fine_grid, const PolarGrid& coarse_grid, - HostVector coarse_result, HostConstVector fine_values) const; + void applyInjection(const PolarGrid& fine_grid, const PolarGrid& coarse_grid, + Vector coarse_result, ConstVector fine_values) const; /* Bilinear interpolation operator */ void applyProlongation(const PolarGrid& coarse_grid, diff --git a/src/Interpolation/injection.cpp b/src/Interpolation/injection.cpp index 1895ee94..488c17c5 100644 --- a/src/Interpolation/injection.cpp +++ b/src/Interpolation/injection.cpp @@ -4,10 +4,10 @@ using namespace gmgpolar; /* Remark: This injection is not scaled. */ static KOKKOS_INLINE_FUNCTION void coarseNodeInjection(const int i_r_coarse, const int i_theta_coarse, - const PolarGrid& fine_grid, - const PolarGrid& coarse_grid, - HostVector& coarse_result, - HostConstVector& fine_values) + const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, + Vector& coarse_result, + ConstVector& fine_values) { const int i_r_fine = i_r_coarse * 2; const int i_theta_fine = i_theta_coarse * 2; @@ -18,9 +18,9 @@ static KOKKOS_INLINE_FUNCTION void coarseNodeInjection(const int i_r_coarse, con coarse_result[coarse_index] = fine_values[fine_index]; } -void Interpolation::applyInjection(const PolarGrid& fine_grid, - const PolarGrid& coarse_grid, HostVector coarse_result, - HostConstVector fine_values) const +void Interpolation::applyInjection(const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, Vector coarse_result, + ConstVector fine_values) const { assert(std::ssize(fine_values) == fine_grid.numberOfNodes()); assert(std::ssize(coarse_result) == coarse_grid.numberOfNodes()); @@ -31,7 +31,7 @@ void Interpolation::applyInjection(const PolarGrid& fine_grid // The For loop matches circular access pattern */ Kokkos::parallel_for( "Interpolation: Injection (Circular)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, 0}, // Starting point of the index space {coarse_grid.numberSmootherCircles(), coarse_grid.ntheta()} // Ending point of the index space ), @@ -43,7 +43,7 @@ void Interpolation::applyInjection(const PolarGrid& fine_grid /* For loop matches radial access pattern */ Kokkos::parallel_for( "Interpolation: Injection (Radial)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, coarse_grid.numberSmootherCircles()}, // Starting point of the index space {coarse_grid.ntheta(), coarse_grid.nr()} // Ending point of the index space ), From 060c23f18b4973b92657e4925d90e5469ab268de Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 13:31:25 +0200 Subject: [PATCH 04/21] Port extrapolatedRestriction to GPU --- .../extrapolated_multigrid_F_Cycle.h | 35 ++++++++++--------- .../extrapolated_multigrid_V_Cycle.h | 35 ++++++++++--------- .../extrapolated_multigrid_W_Cycle.h | 35 ++++++++++--------- include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/utils.h | 8 ++--- 5 files changed, 60 insertions(+), 55 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 514acb49..310168cd 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::extrapolated_multigrid_F_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(level_depth == 0); assert(number_of_levels_ >= 2); @@ -27,10 +27,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } @@ -38,18 +38,21 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------------------------------- */ - /* Compute the restricted extrapolated residual */ + /* Compute the restricted extrapolated h_residual */ /* -------------------------------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(residual, rhs, solution); - extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); + level.computeResidual(h_residual, h_rhs, h_solution); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + extrapolatedRestriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - injection(level.level_depth(), next_level_solution, d_solution); + injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); @@ -61,7 +64,7 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated residual */ + /* Solve A * error = restricted extrapolated h_residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -81,14 +84,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + add(h_solution, HostConstVector(h_residual)); /* ------------- */ /* Postsmoothing */ @@ -97,10 +100,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 5a71cdc9..a2abfbae 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::extrapolated_multigrid_V_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(level_depth == 0); assert(number_of_levels_ >= 2); @@ -27,10 +27,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } @@ -38,18 +38,21 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------------------------------- */ - /* Compute the restricted extrapolated residual */ + /* Compute the restricted extrapolated h_residual */ /* -------------------------------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(residual, rhs, solution); - extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); + level.computeResidual(h_residual, h_rhs, h_solution); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + extrapolatedRestriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - injection(level.level_depth(), next_level_solution, d_solution); + injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); @@ -61,7 +64,7 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated residual */ + /* Solve A * error = restricted extrapolated h_residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -75,14 +78,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + add(h_solution, HostConstVector(h_residual)); /* ------------- */ /* Postsmoothing */ @@ -91,10 +94,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index e0a59c99..b4e8173c 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::extrapolated_multigrid_W_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(level_depth == 0); assert(number_of_levels_ >= 2); @@ -27,10 +27,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } @@ -38,18 +38,21 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------------------------------- */ - /* Compute the restricted extrapolated residual */ + /* Compute the restricted extrapolated h_residual */ /* -------------------------------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(residual, rhs, solution); - extrapolatedRestriction(level.level_depth(), next_level.residual(), residual); + level.computeResidual(h_residual, h_rhs, h_solution); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + extrapolatedRestriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto d_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - injection(level.level_depth(), next_level_solution, d_solution); + injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); @@ -61,7 +64,7 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated residual */ + /* Solve A * error = restricted extrapolated h_residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -81,14 +84,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + add(h_solution, HostConstVector(h_residual)); /* ------------- */ /* Postsmoothing */ @@ -97,10 +100,10 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(solution, rhs, residual); + level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); } else { - level.smoothing(solution, rhs, residual); + level.smoothing(h_solution, h_rhs, h_residual); } } diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index b3c71d6d..da2b7b6f 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -211,7 +211,7 @@ class GMGPolar : public IGMGPolar void restriction(int current_level, HostVector result, HostConstVector x) const; void injection(int current_level, Vector result, ConstVector x) const; void extrapolatedProlongation(int current_level, HostVector result, HostConstVector x) const; - void extrapolatedRestriction(int current_level, HostVector result, HostConstVector x) const; + void extrapolatedRestriction(int current_level, Vector result, ConstVector x) const; void FMGInterpolation(int current_level, HostVector result, HostConstVector x) const; /* ------------- */ diff --git a/include/GMGPolar/utils.h b/include/GMGPolar/utils.h index ebd76486..55e80382 100644 --- a/include/GMGPolar/utils.h +++ b/include/GMGPolar/utils.h @@ -62,11 +62,9 @@ void GMGPolar::extrapolatedProlongat template void GMGPolar::extrapolatedRestriction(int current_level, - HostVector result_host, - HostConstVector x_host) const + Vector result, + ConstVector x) const { - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), result_host); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), x_host); assert(current_level < number_of_levels_ - 1 && 0 <= current_level); if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); @@ -74,8 +72,6 @@ void GMGPolar::extrapolatedRestricti PolarGrid current_grid = levels_[current_level].grid(); PolarGrid next_grid = levels_[current_level + 1].grid(); interpolation_->applyExtrapolatedRestriction(current_grid, next_grid, result, x); - - Kokkos::deep_copy(result_host, result); } template From 106efacdd7f9ae685e4b122ee8c284f87eefa6e7 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 15:22:43 +0200 Subject: [PATCH 05/21] Port extrapolatedSmoothing to GPU --- .../extrapolatedSmootherGive.h | 2 +- .../extrapolatedSmootherGive.inl | 13 +- .../extrapolatedSmootherTake.h | 2 +- .../extrapolatedSmootherTake.inl | 13 +- .../extrapolatedSmoother.h | 2 +- .../extrapolated_multigrid_F_Cycle.h | 17 +- .../extrapolated_multigrid_V_Cycle.h | 18 +- .../extrapolated_multigrid_W_Cycle.h | 18 +- include/Level/level.h | 2 +- include/Level/level.inl | 6 +- .../extrapolated_smoother.cpp | 500 +++++++++++------- tests/test_tools.h | 6 + 12 files changed, 358 insertions(+), 241 deletions(-) diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.h b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.h index c5c216cc..9d104085 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.h +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.h @@ -68,7 +68,7 @@ class ExtrapolatedSmootherGive : public ExtrapolatedSmoother // Parallel implementation using OpenMP: // Scedule every 2nd/4th line in parallel to avoid race conditions arising from the A-Give distribution. // Sceduling every 3rd line in parallel would also be possible, but is less natural for the 2 coloring. - void extrapolatedSmoothing(HostVector x, HostConstVector rhs, HostVector temp) override; + void extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) override; private: /* ------------------- */ diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl index a670b3e8..58da0f02 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl @@ -42,14 +42,10 @@ ExtrapolatedSmootherGive::ExtrapolatedSmootherGive(const PolarGr // - The system is then solved in-place in temp, and the results // are copied back to x. template -void ExtrapolatedSmootherGive::extrapolatedSmoothing(HostVector h_x, - HostConstVector h_rhs, - HostVector h_temp) +void ExtrapolatedSmootherGive::extrapolatedSmoothing(Vector x, + ConstVector rhs, + Vector temp) { - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto temp = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_temp); - assert(x.size() == rhs.size()); assert(temp.size() == rhs.size()); @@ -91,7 +87,4 @@ void ExtrapolatedSmootherGive::extrapolatedSmoothing(HostVector< applyAscOrthoWhiteRadialSection(x, rhs, temp); solveWhiteRadialSection(x, temp); - - Kokkos::deep_copy(h_x, x); - Kokkos::deep_copy(h_temp, temp); } diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.h b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.h index d8552bbe..a7964365 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.h +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.h @@ -66,7 +66,7 @@ class ExtrapolatedSmootherTake : public ExtrapolatedSmoother // Performs one full coupled extrapolated smoothing sweep: // BC -> WC -> BR -> WR // using temp as RHS workspace. - void extrapolatedSmoothing(HostVector x, HostConstVector rhs, HostVector temp) override; + void extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) override; private: /* ------------------- */ diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl index bc3e9687..1f96ec88 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl @@ -43,14 +43,10 @@ ExtrapolatedSmootherTake::ExtrapolatedSmootherTake(const PolarGr // are copied back to x. template -void ExtrapolatedSmootherTake::extrapolatedSmoothing(HostVector h_x, - HostConstVector h_rhs, - HostVector h_temp) +void ExtrapolatedSmootherTake::extrapolatedSmoothing(Vector x, + ConstVector rhs, + Vector temp) { - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto temp = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_temp); - assert(x.size() == rhs.size()); assert(temp.size() == rhs.size()); @@ -65,7 +61,4 @@ void ExtrapolatedSmootherTake::extrapolatedSmoothing(HostVector< applyAscOrthoWhiteRadialSection(x, rhs, temp); solveWhiteRadialSection(x, temp); - - Kokkos::deep_copy(h_x, x); - Kokkos::deep_copy(h_temp, temp); } diff --git a/include/ExtrapolatedSmoother/extrapolatedSmoother.h b/include/ExtrapolatedSmoother/extrapolatedSmoother.h index 38ca430f..9f1fd652 100644 --- a/include/ExtrapolatedSmoother/extrapolatedSmoother.h +++ b/include/ExtrapolatedSmoother/extrapolatedSmoother.h @@ -36,7 +36,7 @@ class ExtrapolatedSmoother } virtual ~ExtrapolatedSmoother() = default; - virtual void extrapolatedSmoothing(HostVector x, HostConstVector rhs, HostVector temp) = 0; + virtual void extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) = 0; protected: const PolarGrid& grid_; diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 310168cd..f600b8c1 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -25,9 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -45,12 +51,11 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Kokkos::deep_copy(solution, h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -100,7 +105,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index a2abfbae..c5f0d917 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -25,9 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -45,12 +51,12 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + Kokkos::deep_copy(residual, h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Kokkos::deep_copy(solution, h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -94,7 +100,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index b4e8173c..b56d39a0 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -25,9 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -45,12 +51,12 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + Kokkos::deep_copy(residual, h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Kokkos::deep_copy(solution, h_solution); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -100,7 +106,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - level.extrapolatedSmoothing(h_solution, h_rhs, h_residual); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); + level.extrapolatedSmoothing(solution, rhs, residual); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/Level/level.h b/include/Level/level.h index c7545b56..2304ed68 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -113,7 +113,7 @@ class Level // Apply Extrapolated Smoothing // void initializeExtrapolatedSmoothing(const bool DirBC_Interior, const StencilDistributionMethod stencil_distribution_method); - void extrapolatedSmoothing(HostVector x, HostConstVector rhs, HostVector temp) const; + void extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) const; private: const int level_depth_; diff --git a/include/Level/level.inl b/include/Level/level.inl index 13bb18ad..5facab3f 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -191,9 +191,9 @@ void Level::initializeExtrapolatedSm } template -void Level::extrapolatedSmoothing(HostVector x, - HostConstVector rhs, - HostVector temp) const +void Level::extrapolatedSmoothing(Vector x, + ConstVector rhs, + Vector temp) const { if (!op_extrapolated_smoother_) throw std::runtime_error("Extrapolated Smoother not initialized."); diff --git a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp index 61e4f827..c1b8900d 100644 --- a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp +++ b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp @@ -41,7 +41,7 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_DirBC_Interior) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -54,34 +54,38 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_DirBC_Interior) bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::NONE, 0); + const PolarGrid& grid = level.grid(); ExtrapolatedSmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector rhs = generate_random_sample_data(level.grid(), 69); HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - HostVector temp = generate_random_sample_data(PolarGrid(level.grid()), 8); + Vector temp = generate_random_sample_data(level.grid(), 8); - HostVector solution_Give("solution_Give", start.size()); + Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); smootherGive_operator.extrapolatedSmoothing(solution_Give, rhs, temp); - HostVector solution_Take("solution_Take", start.size()); + Vector solution_Take("solution_Take", start.size()); Kokkos::deep_copy(solution_Take, start); smootherTake_operator.extrapolatedSmoothing(solution_Take, rhs, temp); - ASSERT_EQ(solution_Give.size(), solution_Take.size()); - for (uint index = 0; index < solution_Give.size(); index++) { + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); + + ASSERT_EQ(h_solution_Give.size(), h_solution_Take.size()); + for (uint index = 0; index < h_solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-11); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-11); else - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-11); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-11); } } @@ -98,7 +102,7 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_AcossOrigin) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -111,40 +115,43 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_AcossOrigin) bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::NONE, 0); ExtrapolatedSmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector rhs = generate_random_sample_data(level.grid(), 69); HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - HostVector temp = generate_random_sample_data(PolarGrid(level.grid()), 8); + Vector temp = generate_random_sample_data(level.grid(), 8); - HostVector solution_Give("solution_Give", start.size()); + Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); smootherGive_operator.extrapolatedSmoothing(solution_Give, rhs, temp); - HostVector solution_Take("solution_Take", start.size()); + Vector solution_Take("solution_Take", start.size()); Kokkos::deep_copy(solution_Take, start); smootherTake_operator.extrapolatedSmoothing(solution_Take, rhs, temp); - ASSERT_EQ(solution_Give.size(), solution_Take.size()); - for (uint index = 0; index < solution_Give.size(); index++) { + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); + + ASSERT_EQ(h_solution_Give.size(), h_solution_Take.size()); + for (uint index = 0; index < h_solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-8); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-8); else - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-11); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-11); } } /* Test 2/2: */ /* Does the smoother converge to the DirectSolverGive solution? */ -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -157,7 +164,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -169,29 +176,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) bool cache_domain_geometry = false; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -202,10 +218,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) const int max_iterations = 10000; const double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -222,10 +238,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 300); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior();} -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -238,7 +256,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -250,31 +268,40 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) bool cache_domain_geometry = false; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - - HostVector error("error", level.grid().numberOfNodes()); - - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + + Vector error("error", level.grid().numberOfNodes()); + + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -285,10 +312,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -305,10 +332,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 600); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin();} -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.4, 0.45, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -320,7 +349,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -332,31 +361,40 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) bool cache_domain_geometry = false; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - - HostVector error("error", level.grid().numberOfNodes()); - - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + + Vector error("error", level.grid().numberOfNodes()); + + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -367,10 +405,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) const int max_iterations = 10000; double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -387,10 +425,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 200); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid();} -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.4, 0.45, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -402,7 +442,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -414,29 +454,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) bool cache_domain_geometry = false; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -447,10 +496,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > 1e-8) { + while (infinity_norm(ConstVector(error)) > 1e-8) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -467,12 +516,14 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 150); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid();} /* We now test using "Take" */ -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -485,7 +536,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -497,29 +548,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -530,10 +590,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) const int max_iterations = 10000; const double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -550,10 +610,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 300); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior();} -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -566,7 +628,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -578,29 +640,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -611,10 +682,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -631,10 +702,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 600); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin();} -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.4, 0.45, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -646,7 +719,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGr using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -658,29 +731,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGr bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -691,10 +773,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGr const int max_iterations = 10000; double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -711,10 +793,12 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGr ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 200); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid(); } -TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid) +void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.4, 0.45, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -726,7 +810,7 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid using DomainGeometryType = CzarnyGeometry; DomainGeometryType domain_geometry(Rmax, kappa_eps, delta_e); - auto grid = std::make_unique>(radii, angles); + auto tmp_grid = std::make_unique>(radii, angles); double alpha_jump = 0.678 * Rmax; using DensityProfileCoefficientsType = ZoniShiftedCoefficients; @@ -738,29 +822,38 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid bool cache_domain_geometry = true; auto levelCache = std::make_unique>( - *grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); - Level level(0, std::move(grid), std::move(levelCache), + *tmp_grid, coefficients, domain_geometry, cache_density_rpofile_coefficients, cache_domain_geometry); + Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); - - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); - for (int i_r = 0; i_r < level.grid().nr(); i_r += 2) { - for (int i_theta = 0; i_theta < level.grid().ntheta(); i_theta += 2) { - smoother_solution[level.grid().index(i_r, i_theta)] = discrete_solution[level.grid().index(i_r, i_theta)]; - } - } - - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2*i_r_half; + const int i_theta = 2 * i_theta_half; + smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; + }); + + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -771,10 +864,10 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > 1e-8) { + while (infinity_norm(ConstVector(error)) > 1e-8) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); @@ -791,5 +884,8 @@ TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 150); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); +} +TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid) +{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid(); } diff --git a/tests/test_tools.h b/tests/test_tools.h index b4371332..2be4a749 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -17,3 +17,9 @@ inline HostVector generate_random_sample_data(const PolarGrid generate_random_sample_data(const PolarGrid& grid, unsigned int seed, + double min_val = -100.0, double max_val = 100.0) { + HostVector h_x = generate_random_sample_data(PolarGrid(grid), seed, min_val, max_val); + return Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); +} From 441bc6bf7a1cd3abdfd5c6848fe5aea5d156b89d Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Mon, 8 Jun 2026 15:30:09 +0200 Subject: [PATCH 06/21] Clang format --- .../extrapolatedSmootherGive.inl | 3 +- .../extrapolatedSmootherTake.inl | 3 +- .../extrapolated_multigrid_F_Cycle.h | 28 +- .../extrapolated_multigrid_V_Cycle.h | 30 +- .../extrapolated_multigrid_W_Cycle.h | 30 +- include/GMGPolar/solver.h | 34 +- include/Interpolation/interpolation.h | 5 +- include/Level/level.inl | 3 +- .../Residual/ResidualGive/residualGive.inl | 2 +- .../Residual/ResidualTake/residualTake.inl | 2 +- include/Residual/residual.h | 2 +- src/Interpolation/injection.cpp | 3 +- src/PolarGrid/polargrid.cpp | 2 +- .../extrapolated_smoother.cpp | 309 +++++++++--------- tests/test_tools.h | 7 +- 15 files changed, 234 insertions(+), 229 deletions(-) diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl index 58da0f02..c355f861 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherGive/extrapolatedSmootherGive.inl @@ -42,8 +42,7 @@ ExtrapolatedSmootherGive::ExtrapolatedSmootherGive(const PolarGr // - The system is then solved in-place in temp, and the results // are copied back to x. template -void ExtrapolatedSmootherGive::extrapolatedSmoothing(Vector x, - ConstVector rhs, +void ExtrapolatedSmootherGive::extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) { assert(x.size() == rhs.size()); diff --git a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl index 1f96ec88..961195d2 100644 --- a/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl +++ b/include/ExtrapolatedSmoother/ExtrapolatedSmootherTake/extrapolatedSmootherTake.inl @@ -43,8 +43,7 @@ ExtrapolatedSmootherTake::ExtrapolatedSmootherTake(const PolarGr // are copied back to x. template -void ExtrapolatedSmootherTake::extrapolatedSmoothing(Vector x, - ConstVector rhs, +void ExtrapolatedSmootherTake::extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) { assert(x.size() == rhs.size()); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index f600b8c1..f5c62be4 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -25,15 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -50,15 +50,15 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + Kokkos::deep_copy(solution, h_solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) @@ -105,11 +105,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index c5f0d917..2ad196d2 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -25,15 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -50,16 +50,16 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - Kokkos::deep_copy(residual, h_residual); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + Kokkos::deep_copy(residual, h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + Kokkos::deep_copy(solution, h_solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) @@ -100,11 +100,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index b56d39a0..97575bea 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -25,15 +25,15 @@ void GMGPolar::extrapolated_multigri /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); @@ -50,16 +50,16 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - Kokkos::deep_copy(residual, h_residual); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + Kokkos::deep_copy(residual, h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + Kokkos::deep_copy(solution, h_solution); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) @@ -106,11 +106,11 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); } else { level.smoothing(h_solution, h_rhs, h_residual); diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index 54d03ebe..3ee47f14 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -28,10 +28,10 @@ void GMGPolar::solve(const BoundaryC // Inject rhs if there is a next level if (level_depth + 1 < initial_rhs_f_levels) { Level& next_level = levels_[level_depth + 1]; - auto current_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + auto current_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); injection(level_depth, next_level_rhs, current_level_rhs); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); } // Discretize the rhs for the current level discretize_rhs_f(current_level, current_level.rhs()); @@ -339,20 +339,20 @@ void GMGPolar::solvePCG(double& init while (number_of_iterations_ < max_iterations_) { // A_p = A * p - auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); - auto pcg_search_direction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), pcg_search_direction_); + auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); + auto pcg_search_direction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), pcg_search_direction_); level.applySystemOperator(level_residual, pcg_search_direction); - Kokkos::deep_copy(level.residual(), level_residual); + Kokkos::deep_copy(level.residual(), level_residual); if (extrapolation_ != ExtrapolationType::NONE) { assert(number_of_levels_ > 1); Level& next_level = levels_[level.level_depth() + 1]; - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); injection(0, next_level_solution, pcg_search_direction); next_level.applySystemOperator(next_level_residual, next_level_solution); applyExtrapolation(0, level_residual, next_level_residual); - Kokkos::deep_copy(level.residual(), level_residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(level.residual(), level_residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); } // alpha = (r^T * z) / (p^T * A*p) @@ -487,15 +487,15 @@ void GMGPolar::updateResidualNorms( level.computeResidual(level.residual(), level.rhs(), level.solution()); if (extrapolation_ != ExtrapolationType::NONE) { Level& next_level = levels_[level.level_depth() + 1]; - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.solution(), next_level_solution); next_level.computeResidual(next_level.residual(), next_level.rhs(), next_level.solution()); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); applyExtrapolation(level.level_depth(), level_residual, next_level_residual); - Kokkos::deep_copy(level.residual(), level_residual); + Kokkos::deep_copy(level.residual(), level_residual); } current_residual_norm = residualNorm(residual_norm_type_, level, level.residual()); @@ -573,7 +573,7 @@ void GMGPolar::applyExtrapolation(in Kokkos::parallel_for( "Extrapolation: Apply Extrapolation (Radial)", Kokkos::MDRangePolicy>({0, fineGrid.numberSmootherCircles()}, - {fineGrid.ntheta(), fineGrid.nr()}), + {fineGrid.ntheta(), fineGrid.nr()}), KOKKOS_LAMBDA(const int i_theta, const int i_r) { const int fine_idx = fineGrid.index(i_r, i_theta); if (i_r & 1 || i_theta & 1) { diff --git a/include/Interpolation/interpolation.h b/include/Interpolation/interpolation.h index 07e2bec1..530b481a 100644 --- a/include/Interpolation/interpolation.h +++ b/include/Interpolation/interpolation.h @@ -19,8 +19,9 @@ class Interpolation explicit Interpolation(bool DirBC_Interior); /* Remark: This injection is not scaled. */ - void applyInjection(const PolarGrid& fine_grid, const PolarGrid& coarse_grid, - Vector coarse_result, ConstVector fine_values) const; + void applyInjection(const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, Vector coarse_result, + ConstVector fine_values) const; /* Bilinear interpolation operator */ void applyProlongation(const PolarGrid& coarse_grid, diff --git a/include/Level/level.inl b/include/Level/level.inl index 5facab3f..d65342a9 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -191,8 +191,7 @@ void Level::initializeExtrapolatedSm } template -void Level::extrapolatedSmoothing(Vector x, - ConstVector rhs, +void Level::extrapolatedSmoothing(Vector x, ConstVector rhs, Vector temp) const { if (!op_extrapolated_smoother_) diff --git a/include/Residual/ResidualGive/residualGive.inl b/include/Residual/ResidualGive/residualGive.inl index 61584148..55024b5c 100644 --- a/include/Residual/ResidualGive/residualGive.inl +++ b/include/Residual/ResidualGive/residualGive.inl @@ -17,7 +17,7 @@ void ResidualGive::computeResidual(HostVector h_result, auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); applySystemOperator(result, x); diff --git a/include/Residual/ResidualTake/residualTake.inl b/include/Residual/ResidualTake/residualTake.inl index b7ddd6b9..c53c9543 100644 --- a/include/Residual/ResidualTake/residualTake.inl +++ b/include/Residual/ResidualTake/residualTake.inl @@ -17,7 +17,7 @@ void ResidualTake::computeResidual(HostVector h_result, auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); applySystemOperator(result, x); diff --git a/include/Residual/residual.h b/include/Residual/residual.h index 4c08923b..cdafc870 100644 --- a/include/Residual/residual.h +++ b/include/Residual/residual.h @@ -27,7 +27,7 @@ class Residual virtual void applySystemOperator(Vector result, ConstVector x) const = 0; virtual void computeResidual(HostVector result, HostConstVector rhs, - HostConstVector x) const = 0; + HostConstVector x) const = 0; protected: /* ------------------- */ diff --git a/src/Interpolation/injection.cpp b/src/Interpolation/injection.cpp index 488c17c5..ce569f19 100644 --- a/src/Interpolation/injection.cpp +++ b/src/Interpolation/injection.cpp @@ -6,8 +6,7 @@ using namespace gmgpolar; static KOKKOS_INLINE_FUNCTION void coarseNodeInjection(const int i_r_coarse, const int i_theta_coarse, const PolarGrid& fine_grid, const PolarGrid& coarse_grid, - Vector& coarse_result, - ConstVector& fine_values) + Vector& coarse_result, ConstVector& fine_values) { const int i_r_fine = i_r_coarse * 2; const int i_theta_fine = i_theta_coarse * 2; diff --git a/src/PolarGrid/polargrid.cpp b/src/PolarGrid/polargrid.cpp index 668c6631..c458773d 100644 --- a/src/PolarGrid/polargrid.cpp +++ b/src/PolarGrid/polargrid.cpp @@ -214,7 +214,7 @@ void PolarGrid::initializeLineSplitting(std::optional split } } else { - auto h_radius = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, radii_); + auto h_radius = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, radii_); number_smoother_circles_ = 2; /* We assume numberSmootherCircles_ >= 2 in the further implementation */ for (int i_r = 2; i_r < nr() - 2; i_r++) { /* We assume lengthRadialSmoother_ >= 3 in the further implementation */ diff --git a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp index c1b8900d..e5b4e523 100644 --- a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp +++ b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp @@ -58,13 +58,13 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_DirBC_Interior) Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::NONE, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); ExtrapolatedSmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - Vector rhs = generate_random_sample_data(level.grid(), 69); + Vector rhs = generate_random_sample_data(level.grid(), 69); HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - Vector temp = generate_random_sample_data(level.grid(), 8); + Vector temp = generate_random_sample_data(level.grid(), 8); Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); @@ -75,8 +75,8 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_DirBC_Interior) smootherTake_operator.extrapolatedSmoothing(solution_Take, rhs, temp); - auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); - auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); ASSERT_EQ(h_solution_Give.size(), h_solution_Take.size()); for (uint index = 0; index < h_solution_Give.size(); index++) { @@ -122,9 +122,9 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_AcossOrigin) ExtrapolatedSmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - Vector rhs = generate_random_sample_data(level.grid(), 69); + Vector rhs = generate_random_sample_data(level.grid(), 69); HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - Vector temp = generate_random_sample_data(level.grid(), 8); + Vector temp = generate_random_sample_data(level.grid(), 8); Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); @@ -134,8 +134,8 @@ TEST(ExtrapolatedSmootherTest, extrapolatedSmoother_AcossOrigin) Kokkos::deep_copy(solution_Take, start); smootherTake_operator.extrapolatedSmoothing(solution_Take, rhs, temp); - auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); - auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, solution_Take); ASSERT_EQ(h_solution_Give.size(), h_solution_Take.size()); for (uint index = 0; index < h_solution_Give.size(); index++) { @@ -180,7 +180,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -189,28 +189,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -241,7 +240,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() { @@ -272,7 +273,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -281,30 +282,29 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -335,7 +335,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() { @@ -365,7 +367,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -374,30 +376,29 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -428,7 +429,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherDirBC_Interior_SmallestGrid) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() { @@ -458,7 +461,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -467,28 +470,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -519,7 +521,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherAcrossOrigin_SmallestGrid) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid(); +} /* We now test using "Take" */ @@ -552,7 +556,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -561,28 +565,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -613,7 +616,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() { @@ -644,7 +649,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -653,28 +658,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -705,7 +709,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin();} +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid() { @@ -735,7 +741,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -744,28 +750,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -796,7 +801,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid(); } +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGrid(); +} void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid() { @@ -826,7 +833,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( Level level(0, std::move(tmp_grid), std::move(levelCache), ExtrapolationType::IMPLICIT_EXTRAPOLATION, 0); - const PolarGrid& grid = level.grid(); + const PolarGrid& grid = level.grid(); DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residual_op(level.grid(), level.levelCache(), DirBC_Interior); ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); @@ -835,28 +842,27 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( HostVector h_discrete_solution("discrete_solution", rhs.size()); Kokkos::deep_copy(h_discrete_solution, rhs); solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for( - "Fill smoother_solution", - Kokkos::MDRangePolicy>( // Rank of the index space - {0, 0}, // Starting point of the index space - {(grid.nr()+1)/2, (grid.ntheta()+1)/2} // Ending point of the index space - ), - // Kokkos lambda function to execute for each point in the index space - KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { - const int i_r = 2*i_r_half; - const int i_theta = 2 * i_theta_half; + Kokkos::parallel_for( + "Fill smoother_solution", + Kokkos::MDRangePolicy>( // Rank of the index space + {0, 0}, // Starting point of the index space + {(grid.nr() + 1) / 2, (grid.ntheta() + 1) / 2} // Ending point of the index space + ), + // Kokkos lambda function to execute for each point in the index space + KOKKOS_LAMBDA(const int i_r_half, const int i_theta_half) { + const int i_r = 2 * i_r_half; + const int i_theta = 2 * i_theta_half; smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; - }); + }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + error[i] = discrete_solution[i] - smoother_solution[i]; + }); Kokkos::fence(); int iterations = 0; @@ -887,5 +893,6 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } TEST(ExtrapolatedSmootherTest, ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid) -{ ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid(); +{ + ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid(); } diff --git a/tests/test_tools.h b/tests/test_tools.h index 2be4a749..f7a565a3 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -19,7 +19,8 @@ inline HostVector generate_random_sample_data(const PolarGrid generate_random_sample_data(const PolarGrid& grid, unsigned int seed, - double min_val = -100.0, double max_val = 100.0) { - HostVector h_x = generate_random_sample_data(PolarGrid(grid), seed, min_val, max_val); - return Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + double min_val = -100.0, double max_val = 100.0) +{ + HostVector h_x = generate_random_sample_data(PolarGrid(grid), seed, min_val, max_val); + return Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); } From 231b343aef825a0e104f7bb305ed2510c0361907 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 16:24:37 +0200 Subject: [PATCH 07/21] Should be KOKKOS_LAMBDA --- .../extrapolated_smoother.cpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp index e5b4e523..e2291344 100644 --- a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp +++ b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp @@ -207,7 +207,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -221,7 +221,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -302,7 +302,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -316,7 +316,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -396,7 +396,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -410,7 +410,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -488,7 +488,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -502,7 +502,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -583,7 +583,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -597,7 +597,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -676,7 +676,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -690,7 +690,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -768,7 +768,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -782,7 +782,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -860,7 +860,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); @@ -874,7 +874,7 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); From 54063011331b57403e758b60429396af8c93392b Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Mon, 8 Jun 2026 16:42:00 +0200 Subject: [PATCH 08/21] Clang formatting --- .../extrapolated_smoother.cpp | 104 ++++++++---------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp index e2291344..4e224ae7 100644 --- a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp +++ b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp @@ -207,9 +207,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -220,10 +220,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -302,9 +301,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -315,10 +314,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -396,9 +394,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -409,10 +407,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -488,9 +485,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -501,10 +498,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() while (infinity_norm(ConstVector(error)) > 1e-8) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -583,9 +579,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -596,10 +592,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -676,9 +671,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -689,10 +684,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -768,9 +762,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -781,10 +775,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri while (infinity_norm(ConstVector(error)) > precision) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { @@ -860,9 +853,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( smoother_solution[grid.index(i_r, i_theta)] = discrete_solution[grid.index(i_r, i_theta)]; }); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); int iterations = 0; @@ -873,10 +866,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( while (infinity_norm(ConstVector(error)) > 1e-8) { extrapolated_smoother_op.extrapolatedSmoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - KOKKOS_LAMBDA(uint i) { - error[i] = discrete_solution[i] - smoother_solution[i]; - }); + Kokkos::parallel_for( + "get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error[i] = discrete_solution[i] - smoother_solution[i]; }); Kokkos::fence(); iterations++; if (iterations >= max_iterations) { From 1c3629cbc94f0ac1424f53cfdbaed970dd690a04 Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Mon, 8 Jun 2026 16:49:39 +0200 Subject: [PATCH 09/21] Generalise generate_random_sample_data --- tests/test_tools.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/test_tools.h b/tests/test_tools.h index f7a565a3..c68792b6 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -6,7 +6,8 @@ using namespace gmgpolar; -inline HostVector generate_random_sample_data(const PolarGrid& grid, unsigned int seed, +template +inline Vector generate_random_sample_data(const PolarGrid& grid, unsigned int seed, double min_val = -100.0, double max_val = 100.0) { HostVector x("x", grid.numberOfNodes()); @@ -15,12 +16,6 @@ inline HostVector generate_random_sample_data(const PolarGrid generate_random_sample_data(const PolarGrid& grid, unsigned int seed, - double min_val = -100.0, double max_val = 100.0) -{ - HostVector h_x = generate_random_sample_data(PolarGrid(grid), seed, min_val, max_val); - return Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); -} From 8de3fbbc2a16e77f55cabe2201e9a889297c59fc Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 17:22:10 +0200 Subject: [PATCH 10/21] Correct transform_reduce call --- include/LinearAlgebra/Vector/vector_operations.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LinearAlgebra/Vector/vector_operations.h b/include/LinearAlgebra/Vector/vector_operations.h index 1376b4fb..5b78e4a4 100644 --- a/include/LinearAlgebra/Vector/vector_operations.h +++ b/include/LinearAlgebra/Vector/vector_operations.h @@ -136,7 +136,7 @@ T l2_norm(ConstVector x) local_max = abs_val; } }, - Kokkos::Max(scale)); + Kokkos::Max(scale)); // 2) If the largest absolute value is zero, the norm is zero if (scale == T{0}) @@ -171,7 +171,7 @@ T infinity_norm(ConstVector x) local_max = abs_value; } }, - Kokkos::Max(result)); + Kokkos::Max(result)); return result; } From 2fd34c63dee5ab7b0fd01e71a209e33850c6fe8f Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Mon, 8 Jun 2026 18:15:03 +0200 Subject: [PATCH 11/21] Copy needed in both directions due to loop and condition --- .../GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h | 2 ++ .../GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h | 2 ++ .../GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index f5c62be4..d32f7d20 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -31,6 +31,8 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); Kokkos::deep_copy(h_residual, residual); Kokkos::deep_copy(h_solution, solution); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 2ad196d2..065c316a 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -31,6 +31,8 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); Kokkos::deep_copy(h_residual, residual); Kokkos::deep_copy(h_solution, solution); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index 97575bea..e1f9c187 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -31,6 +31,8 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); Kokkos::deep_copy(h_residual, residual); Kokkos::deep_copy(h_solution, solution); From 14d5d5149cb6122782464bb22ce1a382d71d8280 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 09:48:48 +0200 Subject: [PATCH 12/21] Missing copy. Tests now passing --- .../GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index d32f7d20..2ba04796 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -53,6 +53,7 @@ void GMGPolar::extrapolated_multigri // P_ex^T (f_l - A_l*u_l) level.computeResidual(h_residual, h_rhs, h_solution); auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + Kokkos::deep_copy(residual, h_residual); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); Kokkos::deep_copy(next_level.residual(), next_level_residual); From e7c2b779a3bbe0f4b1d41465457c3d6f1c39c052 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 10:40:28 +0200 Subject: [PATCH 13/21] Port smoothing function to GPU. Tests passing --- .../extrapolated_multigrid_F_Cycle.h | 18 +- .../extrapolated_multigrid_V_Cycle.h | 18 +- .../extrapolated_multigrid_W_Cycle.h | 18 +- .../MultigridMethods/multigrid_F_Cycle.h | 41 ++- .../MultigridMethods/multigrid_V_Cycle.h | 41 ++- .../MultigridMethods/multigrid_W_Cycle.h | 41 ++- include/Level/level.h | 2 +- include/Level/level.inl | 4 +- include/Smoother/SmootherGive/smootherGive.h | 2 +- .../Smoother/SmootherGive/smootherGive.inl | 11 +- include/Smoother/SmootherTake/smootherTake.h | 2 +- .../Smoother/SmootherTake/smootherTake.inl | 11 +- include/Smoother/smoother.h | 2 +- tests/Smoother/smoother.cpp | 294 ++++++++++-------- 14 files changed, 274 insertions(+), 231 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 2ba04796..6be7f8e6 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -31,16 +31,14 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -106,18 +104,18 @@ void GMGPolar::extrapolated_multigri /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += std::chrono::duration(end_MGC_postSmoothing - start_MGC_postSmoothing).count(); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 065c316a..903fea62 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -31,16 +31,14 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -100,18 +98,18 @@ void GMGPolar::extrapolated_multigri /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += std::chrono::duration(end_MGC_postSmoothing - start_MGC_postSmoothing).count(); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index e1f9c187..49cc1f7d 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -31,16 +31,14 @@ void GMGPolar::extrapolated_multigri for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -106,18 +104,18 @@ void GMGPolar::extrapolated_multigri /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); + Kokkos::deep_copy(residual, h_residual); + Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); level.extrapolatedSmoothing(solution, rhs, residual); - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); } else { - level.smoothing(h_solution, h_rhs, h_residual); + level.smoothing(solution, rhs, residual); } } + Kokkos::deep_copy(h_residual, residual); + Kokkos::deep_copy(h_solution, solution); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += std::chrono::duration(end_MGC_postSmoothing - start_MGC_postSmoothing).count(); diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index bd6493ef..10ead335 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::multigrid_F_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(0 <= level_depth && level_depth < number_of_levels_); @@ -15,17 +15,17 @@ void GMGPolar::multigrid_F_Cycle(int if (level_depth == number_of_levels_ - 1) { /* ---------------------------------------------------- */ - /* Coarsest level: solve A * x = rhs using DirectSolver */ + /* Coarsest level: solve A * x = h_rhs using DirectSolver */ /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy rhs in solution */ - Kokkos::deep_copy(solution, rhs); + /* Step 1: Copy h_rhs in h_solution */ + Kokkos::deep_copy(h_solution, h_rhs); - /* Step 2: Solve for the solution in place */ + /* Step 2: Solve for the h_solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(solution); + coarsest_level.directSolveInPlace(h_solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,30 +42,35 @@ void GMGPolar::multigrid_F_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the residual */ + /* Compute the h_residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(residual, rhs, solution); + level.computeResidual(h_residual, h_rhs, h_solution); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the residual */ + /* Restrict the h_residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), residual); + restriction(level.level_depth(), next_level.residual(), h_residual); /* ------------------------------------- */ - /* Solve A * error = restricted residual */ + /* Solve A * error = restricted h_residual */ /* ------------------------------------- */ /* Set starting error to zero. */ @@ -84,14 +89,16 @@ void GMGPolar::multigrid_F_Cycle(int /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - prolongation(next_level.level_depth(), residual, next_level.error_correction()); + prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ @@ -101,6 +108,8 @@ void GMGPolar::multigrid_F_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index 0bd95f1e..08d4eb31 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::multigrid_V_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(0 <= level_depth && level_depth < number_of_levels_); @@ -15,17 +15,17 @@ void GMGPolar::multigrid_V_Cycle(int if (level_depth == number_of_levels_ - 1) { /* ---------------------------------------------------- */ - /* Coarsest level: solve A * x = rhs using DirectSolver */ + /* Coarsest level: solve A * x = h_rhs using DirectSolver */ /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy rhs in solution */ - Kokkos::deep_copy(solution, rhs); + /* Step 1: Copy h_rhs in h_solution */ + Kokkos::deep_copy(h_solution, h_rhs); - /* Step 2: Solve for the solution in place */ + /* Step 2: Solve for the h_solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(solution); + coarsest_level.directSolveInPlace(h_solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,30 +42,35 @@ void GMGPolar::multigrid_V_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the residual */ + /* Compute the h_residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(residual, rhs, solution); + level.computeResidual(h_residual, h_rhs, h_solution); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the residual */ + /* Restrict the h_residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), residual); + restriction(level.level_depth(), next_level.residual(), h_residual); /* ------------------------------------- */ - /* Solve A * error = restricted residual */ + /* Solve A * error = restricted h_residual */ /* ------------------------------------- */ /* Set starting error to zero. */ @@ -78,14 +83,16 @@ void GMGPolar::multigrid_V_Cycle(int /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - prolongation(next_level.level_depth(), residual, next_level.error_correction()); + prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ @@ -95,6 +102,8 @@ void GMGPolar::multigrid_V_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index 6c11283f..7cf92778 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -2,9 +2,9 @@ template void GMGPolar::multigrid_W_Cycle(int level_depth, - HostVector solution, - HostConstVector rhs, - HostVector residual) + HostVector h_solution, + HostConstVector h_rhs, + HostVector h_residual) { assert(0 <= level_depth && level_depth < number_of_levels_); @@ -15,17 +15,17 @@ void GMGPolar::multigrid_W_Cycle(int if (level_depth == number_of_levels_ - 1) { /* ---------------------------------------------------- */ - /* Coarsest level: solve A * x = rhs using DirectSolver */ + /* Coarsest level: solve A * x = h_rhs using DirectSolver */ /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy rhs in solution */ - Kokkos::deep_copy(solution, rhs); + /* Step 1: Copy h_rhs in h_solution */ + Kokkos::deep_copy(h_solution, h_rhs); - /* Step 2: Solve for the solution in place */ + /* Step 2: Solve for the h_solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(solution); + coarsest_level.directSolveInPlace(h_solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,30 +42,35 @@ void GMGPolar::multigrid_W_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the residual */ + /* Compute the h_residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(residual, rhs, solution); + level.computeResidual(h_residual, h_rhs, h_solution); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the residual */ + /* Restrict the h_residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), residual); + restriction(level.level_depth(), next_level.residual(), h_residual); /* ------------------------------------- */ - /* Solve A * error = restricted residual */ + /* Solve A * error = restricted h_residual */ /* ------------------------------------- */ /* Set starting error to zero. */ @@ -84,14 +89,16 @@ void GMGPolar::multigrid_W_Cycle(int /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - prolongation(next_level.level_depth(), residual, next_level.error_correction()); + prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(solution, HostConstVector(residual)); + Kokkos::deep_copy(solution, h_solution); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ @@ -101,6 +108,8 @@ void GMGPolar::multigrid_W_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } + Kokkos::deep_copy(h_solution, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += diff --git a/include/Level/level.h b/include/Level/level.h index 2304ed68..16362bff 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -107,7 +107,7 @@ class Level // --------------- // // Apply Smoothing // void initializeSmoothing(const bool DirBC_Interior, const StencilDistributionMethod stencil_distribution_method); - void smoothing(HostVector x, HostConstVector rhs, HostVector temp) const; + void smoothing(Vector x, ConstVector rhs, Vector temp) const; // ---------------------------- // // Apply Extrapolated Smoothing // diff --git a/include/Level/level.inl b/include/Level/level.inl index d65342a9..a2ec87d9 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -164,8 +164,8 @@ void Level::initializeSmoothing( } template -void Level::smoothing(HostVector x, HostConstVector rhs, - HostVector temp) const +void Level::smoothing(Vector x, ConstVector rhs, + Vector temp) const { if (!op_smoother_) throw std::runtime_error("Smoother not initialized."); diff --git a/include/Smoother/SmootherGive/smootherGive.h b/include/Smoother/SmootherGive/smootherGive.h index 6237a14c..20ed82a0 100644 --- a/include/Smoother/SmootherGive/smootherGive.h +++ b/include/Smoother/SmootherGive/smootherGive.h @@ -61,7 +61,7 @@ class SmootherGive : public Smoother // Parallel implementation using OpenMP: // Scedule every 2nd/4th line in parallel to avoid race conditions arising from the A-Give distribution. // Sceduling every 3rd line in parallel would also be possible, but is less natural for the 2 coloring. - void smoothing(HostVector x, HostConstVector rhs, HostVector temp) final; + void smoothing(Vector x, ConstVector rhs, Vector temp) final; private: /* ------------------- */ diff --git a/include/Smoother/SmootherGive/smootherGive.inl b/include/Smoother/SmootherGive/smootherGive.inl index 6747cc95..76b718a8 100644 --- a/include/Smoother/SmootherGive/smootherGive.inl +++ b/include/Smoother/SmootherGive/smootherGive.inl @@ -41,13 +41,9 @@ SmootherGive::SmootherGive(const PolarGrid& // - The system is then solved in-place in temp, and the results // are copied back to x. template -void SmootherGive::smoothing(HostVector h_x, HostConstVector h_rhs, - HostVector h_temp) +void SmootherGive::smoothing(Vector x, ConstVector rhs, + Vector temp) { - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto temp = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_temp); - assert(x.size() == rhs.size()); assert(temp.size() == rhs.size()); @@ -64,7 +60,4 @@ void SmootherGive::smoothing(HostVector h_x, HostConstVe applyAscOrthoWhiteRadialSection(x, rhs, temp); solveWhiteRadialSection(x, temp); - - Kokkos::deep_copy(h_x, x); - Kokkos::deep_copy(h_temp, temp); } diff --git a/include/Smoother/SmootherTake/smootherTake.h b/include/Smoother/SmootherTake/smootherTake.h index 47ae4c1b..3321ae65 100644 --- a/include/Smoother/SmootherTake/smootherTake.h +++ b/include/Smoother/SmootherTake/smootherTake.h @@ -61,7 +61,7 @@ class SmootherTake : public Smoother // Performs one full coupled smoothing sweep: // BC -> WC -> BR -> WR // using temp as RHS workspace. - void smoothing(HostVector x, HostConstVector rhs, HostVector temp) final; + void smoothing(Vector x, ConstVector rhs, Vector temp) final; private: /* ------------------- */ diff --git a/include/Smoother/SmootherTake/smootherTake.inl b/include/Smoother/SmootherTake/smootherTake.inl index 349a2bf1..dcc99eaa 100644 --- a/include/Smoother/SmootherTake/smootherTake.inl +++ b/include/Smoother/SmootherTake/smootherTake.inl @@ -41,13 +41,9 @@ SmootherTake::SmootherTake(const PolarGrid& // - The system is then solved in-place in temp, and the results // are copied back to x. template -void SmootherTake::smoothing(HostVector h_x, HostConstVector h_rhs, - HostVector h_temp) +void SmootherTake::smoothing(Vector x, ConstVector rhs, + Vector temp) { - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto temp = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_temp); - assert(x.size() == rhs.size()); assert(temp.size() == rhs.size()); @@ -62,7 +58,4 @@ void SmootherTake::smoothing(HostVector h_x, HostConstVe applyAscOrthoWhiteRadialSection(x, rhs, temp); solveWhiteRadialSection(x, temp); - - Kokkos::deep_copy(h_x, x); - Kokkos::deep_copy(h_temp, temp); } diff --git a/include/Smoother/smoother.h b/include/Smoother/smoother.h index 41e2e017..092df381 100644 --- a/include/Smoother/smoother.h +++ b/include/Smoother/smoother.h @@ -36,7 +36,7 @@ class Smoother KOKKOS_DEFAULTED_FUNCTION Smoother(const Smoother&) = default; virtual ~Smoother() = default; - virtual void smoothing(HostVector x, HostConstVector rhs, HostVector temp) = 0; + virtual void smoothing(Vector x, ConstVector rhs, Vector temp) = 0; protected: const PolarGrid grid_; diff --git a/tests/Smoother/smoother.cpp b/tests/Smoother/smoother.cpp index 28f015ea..5e674caf 100644 --- a/tests/Smoother/smoother.cpp +++ b/tests/Smoother/smoother.cpp @@ -27,7 +27,7 @@ using namespace gmgpolar; /* Test 1/2: */ /* Does the Take and Give Implementation match up? */ -TEST(SmootherTest, smoother_DirBC_Interior) +void SmootherTest_smoother_DirBC_Interior() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -61,30 +61,35 @@ TEST(SmootherTest, smoother_DirBC_Interior) SmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); - HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - HostVector temp = generate_random_sample_data(PolarGrid(level.grid()), 8); + Vector rhs = generate_random_sample_data(level.grid(), 69); + Vector start = generate_random_sample_data(level.grid(), 24); + Vector temp = generate_random_sample_data(level.grid(), 8); - HostVector solution_Give("solution_Give", start.size()); + Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); smootherGive_operator.smoothing(solution_Give, rhs, temp); - HostVector solution_Take("solution_Take", start.size()); + Vector solution_Take("solution_Take", start.size()); Kokkos::deep_copy(solution_Take, start); smootherTake_operator.smoothing(solution_Take, rhs, temp); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Take); + ASSERT_EQ(solution_Give.size(), solution_Take.size()); - for (uint index = 0; index < solution_Give.size(); index++) { + for (uint index = 0; index < h_solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-11); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-11); else - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-11); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-11); } } +TEST(SmootherTest, smoother_DirBC_Interior) +{ SmootherTest_smoother_DirBC_Interior();} -TEST(SmootherTest, smoother_AcrossOrigin) +void SmootherTest_smoother_AcrossOrigin() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -118,33 +123,38 @@ TEST(SmootherTest, smoother_AcrossOrigin) SmootherGive smootherGive_operator(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smootherTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); - HostVector start = generate_random_sample_data(PolarGrid(level.grid()), 24); - HostVector temp = generate_random_sample_data(PolarGrid(level.grid()), 8); + Vector rhs = generate_random_sample_data(level.grid(), 69); + Vector start = generate_random_sample_data(level.grid(), 24); + Vector temp = generate_random_sample_data(level.grid(), 8); - HostVector solution_Give("solution_Give", start.size()); + Vector solution_Give("solution_Give", start.size()); Kokkos::deep_copy(solution_Give, start); smootherGive_operator.smoothing(solution_Give, rhs, temp); - HostVector solution_Take("solution_Take", start.size()); + Vector solution_Take("solution_Take", start.size()); Kokkos::deep_copy(solution_Take, start); smootherTake_operator.smoothing(solution_Take, rhs, temp); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Take); + ASSERT_EQ(solution_Give.size(), solution_Take.size()); for (uint index = 0; index < solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-8); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-8); else - ASSERT_NEAR(solution_Give[index], solution_Take[index], 1e-10); + ASSERT_NEAR(h_solution_Give[index], h_solution_Take[index], 1e-10); } } +TEST(SmootherTest, smoother_AcrossOrigin) +{ SmootherTest_smoother_AcrossOrigin(); } /* Test 2/2: */ /* Does the smoother converge to the directSolver solution? */ -TEST(SmootherTest, SmootherDirBC_Interior) +void SmootherTest_SmootherDirBC_Interior() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -176,17 +186,18 @@ TEST(SmootherTest, SmootherDirBC_Interior) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -196,11 +207,11 @@ TEST(SmootherTest, SmootherDirBC_Interior) const int max_iterations = 10000; const double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -216,10 +227,12 @@ TEST(SmootherTest, SmootherDirBC_Interior) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 300); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherDirBC_Interior) +{SmootherTest_SmootherDirBC_Interior(); } -TEST(SmootherTest, SmootherAcrossOrigin) +void SmootherTest_SmootherAcrossOrigin() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -251,17 +264,18 @@ TEST(SmootherTest, SmootherAcrossOrigin) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -271,11 +285,11 @@ TEST(SmootherTest, SmootherAcrossOrigin) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -291,10 +305,14 @@ TEST(SmootherTest, SmootherAcrossOrigin) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 600); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); +} +TEST(SmootherTest, SmootherAcrossOrigin) +{ + SmootherTest_SmootherAcrossOrigin(); } -TEST(SmootherTest, SmootherDirBC_Interior_SmallestGrid) +void SmootherTest_SmootherDirBC_Interior_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -325,17 +343,18 @@ TEST(SmootherTest, SmootherDirBC_Interior_SmallestGrid) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -345,11 +364,11 @@ TEST(SmootherTest, SmootherDirBC_Interior_SmallestGrid) const int max_iterations = 10000; double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -365,10 +384,12 @@ TEST(SmootherTest, SmootherDirBC_Interior_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 30); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherDirBC_Interior_SmallestGrid) +{SmootherTest_SmootherDirBC_Interior_SmallestGrid(); } -TEST(SmootherTest, SmootherAcrossOrigin_SmallestGrid) +void SmootherTest_SmootherAcrossOrigin_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -399,17 +420,18 @@ TEST(SmootherTest, SmootherAcrossOrigin_SmallestGrid) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -419,11 +441,11 @@ TEST(SmootherTest, SmootherAcrossOrigin_SmallestGrid) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > 1e-8) { + while (infinity_norm(ConstVector(error)) > 1e-8) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -439,12 +461,14 @@ TEST(SmootherTest, SmootherAcrossOrigin_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 80); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherAcrossOrigin_SmallestGrid) +{ SmootherTest_SmootherAcrossOrigin_SmallestGrid(); } /* Using "Take" */ -TEST(SmootherTest, SmootherTakeDirBC_Interior) +void SmootherTest_SmootherTakeDirBC_Interior() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -476,17 +500,18 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -496,11 +521,11 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior) const int max_iterations = 10000; const double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -516,10 +541,12 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 300); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherTakeDirBC_Interior) +{ SmootherTest_SmootherTakeDirBC_Interior(); } -TEST(SmootherTest, SmootherTakeAcrossOrigin) +void SmootherTest_SmootherTakeAcrossOrigin() { std::vector radii = {1e-5, 0.2, 0.25, 0.5, 0.8, 0.9, 0.95, 1.2, 1.3}; std::vector angles = { @@ -551,17 +578,18 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -571,11 +599,11 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -591,10 +619,12 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 600); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherTakeAcrossOrigin) +{SmootherTest_SmootherTakeAcrossOrigin(); } -TEST(SmootherTest, SmootherTakeDirBC_Interior_SmallestGrid) +void SmootherTest_SmootherTakeDirBC_Interior_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -625,17 +655,18 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior_SmallestGrid) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -645,11 +676,11 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior_SmallestGrid) const int max_iterations = 10000; double precision = 1e-12; - while (infinity_norm(HostConstVector(error)) > precision) { + while (infinity_norm(ConstVector(error)) > precision) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -665,10 +696,12 @@ TEST(SmootherTest, SmootherTakeDirBC_Interior_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 30); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherTakeDirBC_Interior_SmallestGrid) +{ SmootherTest_SmootherTakeDirBC_Interior_SmallestGrid(); } -TEST(SmootherTest, SmootherTakeAcrossOrigin_SmallestGrid) +void SmootherTest_SmootherTakeAcrossOrigin_SmallestGrid() { std::vector radii = {1e-5, 0.2, 0.9, 1.2, 1.3}; std::vector angles = {0, M_PI / 8, M_PI, M_PI + M_PI / 8, M_PI + M_PI}; @@ -699,17 +732,18 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin_SmallestGrid) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(discrete_solution, rhs); - solver_op.solveInPlace(discrete_solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(h_discrete_solution, rhs); + solver_op.solveInPlace(h_discrete_solution); + auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); - HostVector temp("temp", level.grid().numberOfNodes()); - HostVector error("error", level.grid().numberOfNodes()); - HostVector smoother_solution = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector temp("temp", level.grid().numberOfNodes()); + Vector error("error", level.grid().numberOfNodes()); + Vector smoother_solution = generate_random_sample_data(level.grid(), 69); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -719,11 +753,11 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin_SmallestGrid) const int max_iterations = 10000; const double precision = 1e-8; - while (infinity_norm(HostConstVector(error)) > 1e-8) { + while (infinity_norm(ConstVector(error)) > 1e-8) { smoother_op.smoothing(smoother_solution, rhs, temp); - Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), - [&](uint i) { + Kokkos::parallel_for("get error", Kokkos::RangePolicy(0, error.size()), + KOKKOS_LAMBDA(uint i) { error(i) = discrete_solution(i) - smoother_solution(i); }); Kokkos::fence(); @@ -739,5 +773,7 @@ TEST(SmootherTest, SmootherTakeAcrossOrigin_SmallestGrid) ASSERT_TRUE(!max_iterations_reached); ASSERT_LT(iterations, 80); - ASSERT_NEAR(infinity_norm(HostConstVector(error)), 0.0, precision); + ASSERT_NEAR(infinity_norm(ConstVector(error)), 0.0, precision); } +TEST(SmootherTest, SmootherTakeAcrossOrigin_SmallestGrid) +{ SmootherTest_SmootherTakeAcrossOrigin_SmallestGrid(); } From 33d6fd5dbb50dbf0a05fc0a12234d1e93f941996 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 15:05:23 +0200 Subject: [PATCH 14/21] Port computeResidual to GPU. Tests passing --- .../extrapolated_multigrid_F_Cycle.h | 27 +- .../extrapolated_multigrid_V_Cycle.h | 27 +- .../extrapolated_multigrid_W_Cycle.h | 27 +- .../MultigridMethods/multigrid_F_Cycle.h | 6 +- .../MultigridMethods/multigrid_V_Cycle.h | 6 +- .../MultigridMethods/multigrid_W_Cycle.h | 6 +- include/GMGPolar/solver.h | 17 +- include/Level/level.h | 2 +- include/Level/level.inl | 6 +- include/Residual/ResidualGive/residualGive.h | 2 +- .../Residual/ResidualGive/residualGive.inl | 12 +- include/Residual/ResidualTake/residualTake.h | 2 +- .../Residual/ResidualTake/residualTake.inl | 12 +- include/Residual/residual.h | 4 +- tests/DirectSolver/directSolver.cpp | 340 +++++++++--------- tests/Residual/residual.cpp | 30 +- 16 files changed, 267 insertions(+), 259 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 6be7f8e6..636d250d 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -28,6 +28,10 @@ void GMGPolar::extrapolated_multigri auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -37,8 +41,6 @@ void GMGPolar::extrapolated_multigri level.smoothing(solution, rhs, residual); } } - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -49,22 +51,20 @@ void GMGPolar::extrapolated_multigri auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - Kokkos::deep_copy(residual, h_residual); + level.computeResidual(residual, rhs, solution); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); - next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); + next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level.residual(), 4.0 / 3.0, HostConstVector(next_level.error_correction()), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); + Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -97,15 +97,14 @@ void GMGPolar::extrapolated_multigri /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(h_solution, HostConstVector(h_residual)); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 903fea62..43a3f6c5 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -28,6 +28,10 @@ void GMGPolar::extrapolated_multigri auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -37,8 +41,6 @@ void GMGPolar::extrapolated_multigri level.smoothing(solution, rhs, residual); } } - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -49,22 +51,20 @@ void GMGPolar::extrapolated_multigri auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - Kokkos::deep_copy(residual, h_residual); + level.computeResidual(residual, rhs, solution); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); - next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); + next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level.residual(), 4.0 / 3.0, HostConstVector(next_level.error_correction()), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); + Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -91,15 +91,14 @@ void GMGPolar::extrapolated_multigri /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(h_solution, HostConstVector(h_residual)); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index 49cc1f7d..b84a6f5c 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -28,6 +28,10 @@ void GMGPolar::extrapolated_multigri auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -37,8 +41,6 @@ void GMGPolar::extrapolated_multigri level.smoothing(solution, rhs, residual); } } - Kokkos::deep_copy(h_residual, residual); - Kokkos::deep_copy(h_solution, solution); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -49,22 +51,20 @@ void GMGPolar::extrapolated_multigri auto start_MGC_residual = std::chrono::high_resolution_clock::now(); // P_ex^T (f_l - A_l*u_l) - level.computeResidual(h_residual, h_rhs, h_solution); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - Kokkos::deep_copy(residual, h_residual); + level.computeResidual(residual, rhs, solution); extrapolatedRestriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); // f_{l-1} - A_{l-1}* Inject(u_l) - Kokkos::deep_copy(solution, h_solution); - auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); injection(level.level_depth(), next_level_solution, solution); - Kokkos::deep_copy(next_level.solution(), next_level_solution); - next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level.solution()); + next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level.residual(), 4.0 / 3.0, HostConstVector(next_level.error_correction()), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); + Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + Kokkos::deep_copy(residual, h_residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -97,15 +97,14 @@ void GMGPolar::extrapolated_multigri /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - add(h_solution, HostConstVector(h_residual)); + Kokkos::deep_copy(residual, h_residual); + add(solution, ConstVector(residual)); /* ------------- */ /* Postsmoothing */ /* ------------- */ auto start_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); - Kokkos::deep_copy(residual, h_residual); - Kokkos::deep_copy(solution, h_solution); for (int i = 0; i < post_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { level.extrapolatedSmoothing(solution, rhs, residual); diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index 10ead335..89762c62 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -48,8 +48,6 @@ void GMGPolar::multigrid_F_Cycle(int for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -59,7 +57,8 @@ void GMGPolar::multigrid_F_Cycle(int /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(h_residual, h_rhs, h_solution); + level.computeResidual(residual, rhs, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -96,7 +95,6 @@ void GMGPolar::multigrid_F_Cycle(int /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(solution, h_solution); Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index 08d4eb31..f106f397 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -48,8 +48,6 @@ void GMGPolar::multigrid_V_Cycle(int for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -59,7 +57,8 @@ void GMGPolar::multigrid_V_Cycle(int /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(h_residual, h_rhs, h_solution); + level.computeResidual(residual, rhs, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -90,7 +89,6 @@ void GMGPolar::multigrid_V_Cycle(int /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(solution, h_solution); Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index 7cf92778..f0a7c56e 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -48,8 +48,6 @@ void GMGPolar::multigrid_W_Cycle(int for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); @@ -59,7 +57,8 @@ void GMGPolar::multigrid_W_Cycle(int /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); - level.computeResidual(h_residual, h_rhs, h_solution); + level.computeResidual(residual, rhs, solution); + Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -96,7 +95,6 @@ void GMGPolar::multigrid_W_Cycle(int /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(solution, h_solution); Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index 3ee47f14..9a3120c8 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -484,19 +484,22 @@ void GMGPolar::updateResidualNorms( Level& level, int iteration, double& initial_residual_norm, double& current_residual_norm, double& current_relative_residual_norm) { - level.computeResidual(level.residual(), level.rhs(), level.solution()); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.rhs()); + level.computeResidual(residual, rhs, solution); if (extrapolation_ != ExtrapolationType::NONE) { Level& next_level = levels_[level.level_depth() + 1]; - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); injection(level.level_depth(), next_level_solution, solution); + next_level.computeResidual(next_level_residual, next_level_rhs, next_level_solution); + applyExtrapolation(level.level_depth(), residual, next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - next_level.computeResidual(next_level.residual(), next_level.rhs(), next_level.solution()); - auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); - auto level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); - applyExtrapolation(level.level_depth(), level_residual, next_level_residual); - Kokkos::deep_copy(level.residual(), level_residual); } + Kokkos::deep_copy(level.residual(), residual); + Kokkos::deep_copy(level.solution(), solution); current_residual_norm = residualNorm(residual_norm_type_, level, level.residual()); residual_norms_.push_back(current_residual_norm); diff --git a/include/Level/level.h b/include/Level/level.h index 16362bff..5d7ee582 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -95,7 +95,7 @@ class Level // -------------- // // Apply Residual // void initializeResidual(const bool DirBC_Interior, const StencilDistributionMethod stencil_distribution_method); - void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const; + void computeResidual(Vector result, ConstVector rhs, ConstVector x) const; void applySystemOperator(Vector result, ConstVector x) const; // ------------------- // diff --git a/include/Level/level.inl b/include/Level/level.inl index a2ec87d9..0c0d5549 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -105,9 +105,9 @@ void Level::initializeResidual( } template -void Level::computeResidual(HostVector result, - HostConstVector rhs, - HostConstVector x) const +void Level::computeResidual(Vector result, + ConstVector rhs, + ConstVector x) const { if (!op_residual_) throw std::runtime_error("Residual not initialized."); diff --git a/include/Residual/ResidualGive/residualGive.h b/include/Residual/ResidualGive/residualGive.h index e90f2657..781307c3 100644 --- a/include/Residual/ResidualGive/residualGive.h +++ b/include/Residual/ResidualGive/residualGive.h @@ -14,7 +14,7 @@ class ResidualGive : public Residual ~ResidualGive() override = default; void applySystemOperator(Vector result, ConstVector x) const final; - void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const final; + void computeResidual(Vector result, ConstVector rhs, ConstVector x) const final; }; #include "residualGive.inl" diff --git a/include/Residual/ResidualGive/residualGive.inl b/include/Residual/ResidualGive/residualGive.inl index 55024b5c..fa4f5fc0 100644 --- a/include/Residual/ResidualGive/residualGive.inl +++ b/include/Residual/ResidualGive/residualGive.inl @@ -10,14 +10,10 @@ ResidualGive::ResidualGive(const PolarGrid& /* ------------------ */ /* result = rhs - A*x */ template -void ResidualGive::computeResidual(HostVector h_result, HostConstVector h_rhs, - HostConstVector h_x) const +void ResidualGive::computeResidual(Vector result, ConstVector rhs, + ConstVector x) const { - assert(h_result.size() == h_x.size()); - - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + assert(result.size() == x.size()); applySystemOperator(result, x); @@ -29,6 +25,4 @@ void ResidualGive::computeResidual(HostVector h_result, KOKKOS_LAMBDA(const int i) { result[i] = rhs[i] - result[i]; }); Kokkos::fence(); - - Kokkos::deep_copy(h_result, result); } diff --git a/include/Residual/ResidualTake/residualTake.h b/include/Residual/ResidualTake/residualTake.h index e7c372d6..403310ce 100644 --- a/include/Residual/ResidualTake/residualTake.h +++ b/include/Residual/ResidualTake/residualTake.h @@ -15,7 +15,7 @@ class ResidualTake : public Residual KOKKOS_DEFAULTED_FUNCTION ~ResidualTake() override = default; void applySystemOperator(Vector result, ConstVector x) const final; - void computeResidual(HostVector result, HostConstVector rhs, HostConstVector x) const final; + void computeResidual(Vector result, ConstVector rhs, ConstVector x) const final; }; #include "residualTake.inl" diff --git a/include/Residual/ResidualTake/residualTake.inl b/include/Residual/ResidualTake/residualTake.inl index c53c9543..cf9996dd 100644 --- a/include/Residual/ResidualTake/residualTake.inl +++ b/include/Residual/ResidualTake/residualTake.inl @@ -10,14 +10,10 @@ ResidualTake::ResidualTake(const PolarGrid& /* ------------------ */ /* result = rhs - A*x */ template -void ResidualTake::computeResidual(HostVector h_result, HostConstVector h_rhs, - HostConstVector h_x) const +void ResidualTake::computeResidual(Vector result, ConstVector rhs, + ConstVector x) const { - assert(h_result.size() == h_x.size()); - - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_result); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_x); + assert(result.size() == x.size()); applySystemOperator(result, x); @@ -29,6 +25,4 @@ void ResidualTake::computeResidual(HostVector h_result, KOKKOS_LAMBDA(const int i) { result[i] = rhs[i] - result[i]; }); Kokkos::fence(); - - Kokkos::deep_copy(h_result, result); } diff --git a/include/Residual/residual.h b/include/Residual/residual.h index cdafc870..b2815606 100644 --- a/include/Residual/residual.h +++ b/include/Residual/residual.h @@ -26,8 +26,8 @@ class Residual virtual ~Residual() = default; virtual void applySystemOperator(Vector result, ConstVector x) const = 0; - virtual void computeResidual(HostVector result, HostConstVector rhs, - HostConstVector x) const = 0; + virtual void computeResidual(Vector result, ConstVector rhs, + ConstVector x) const = 0; protected: /* ------------------- */ diff --git a/tests/DirectSolver/directSolver.cpp b/tests/DirectSolver/directSolver.cpp index 34464e1b..37700d7b 100644 --- a/tests/DirectSolver/directSolver.cpp +++ b/tests/DirectSolver/directSolver.cpp @@ -171,17 +171,18 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverDirBC_Interior_CircularGeome DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeometry) @@ -212,17 +213,18 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeometr DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* --------- */ @@ -259,17 +261,18 @@ TEST(DirectSolverTest_ShafranovGeometry, DirectSolverDirBC_Interior_ShafranovGeo DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-12); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovGeometry) @@ -302,17 +305,18 @@ TEST(DirectSolverTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovGeome DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* ------ */ @@ -349,17 +353,18 @@ TEST(DirectSolverTest_CzarnyGeometry, DirectSolverDirBC_Interior_CzarnyGeometry) DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-12); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometry) @@ -392,17 +397,18 @@ TEST(DirectSolverTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometry) DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* ------ */ @@ -437,17 +443,18 @@ TEST(DirectSolverTest_CulhamGeometry, DirectSolverDirBC_Interior_CulhamGeometry) DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometry) @@ -478,17 +485,18 @@ TEST(DirectSolverTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometry) DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* We adjust the PolarGrid to increase the precision */ @@ -531,17 +539,18 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision_ DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-9); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-10); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-10); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-9); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-10); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-10); } TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision2_CircularGeometry) @@ -572,17 +581,18 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision2 DirectSolverGive solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } /* Same test now using Take */ @@ -614,17 +624,18 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverDirBC_Interior_CircularG DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeometry) @@ -655,17 +666,18 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeo DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* --------- */ @@ -702,17 +714,18 @@ TEST(DirectSolverTakeTest_ShafranovGeometry, DirectSolverDirBC_Interior_Shafrano DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-11); } TEST(DirectSolverTakeTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovGeometry) @@ -745,17 +758,18 @@ TEST(DirectSolverTakeTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovG DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* ------ */ @@ -792,17 +806,18 @@ TEST(DirectSolverTakeTest_CzarnyGeometry, DirectSolverDirBC_Interior_CzarnyGeome DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-12); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-12); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-12); } TEST(DirectSolverTakeTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometry) @@ -835,17 +850,18 @@ TEST(DirectSolverTakeTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometr DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-8); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } /* ------ */ @@ -880,17 +896,18 @@ TEST(DirectSolverTakeTest_CulhamGeometry, DirectSolverDirBC_Interior_CulhamGeome DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-11); } TEST(DirectSolverTakeTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometry) @@ -921,17 +938,18 @@ TEST(DirectSolverTakeTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometr DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-7); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-8); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-7); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-8); } TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision_CircularGeometry) @@ -972,17 +990,18 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecis DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-10); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-10); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-10); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-10); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-10); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-10); } TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision2_CircularGeometry) @@ -1013,15 +1032,16 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecis DirectSolverTake solver_op(level.grid(), level.levelCache(), DirBC_Interior); ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); - HostConstVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector solution("sol", rhs.size()); - Kokkos::deep_copy(solution, rhs); - solver_op.solveInPlace(solution); + ConstVector rhs = generate_random_sample_data(level.grid(), 42); + HostVector h_solution("sol", rhs.size()); + Kokkos::deep_copy(h_solution, rhs); + solver_op.solveInPlace(h_solution); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); - HostVector residuum("residuum", level.grid().numberOfNodes()); + Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); - ASSERT_NEAR(l1_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(l2_norm(HostConstVector(residuum)), 0.0, 1e-11); - ASSERT_NEAR(infinity_norm(HostConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l1_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(l2_norm(ConstVector(residuum)), 0.0, 1e-11); + ASSERT_NEAR(infinity_norm(ConstVector(residuum)), 0.0, 1e-11); } diff --git a/tests/Residual/residual.cpp b/tests/Residual/residual.cpp index c74dc5d7..0c902c86 100644 --- a/tests/Residual/residual.cpp +++ b/tests/Residual/residual.cpp @@ -55,23 +55,26 @@ TEST(OperatorATest, applyA_DirBC_Interior) ResidualGive residualGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residualTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector x = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector x = generate_random_sample_data(level.grid(), 42); + Vector rhs = generate_random_sample_data(level.grid(), 69); - HostVector result_Give("result_Give", level.grid().numberOfNodes()); + Vector result_Give("result_Give", level.grid().numberOfNodes()); residualGive_operator.computeResidual(result_Give, rhs, x); - HostVector result_Take("result_Take", level.grid().numberOfNodes()); + Vector result_Take("result_Take", level.grid().numberOfNodes()); residualTake_operator.computeResidual(result_Take, rhs, x); + auto h_result_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, result_Give); + auto h_result_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, result_Take); + ASSERT_EQ(result_Give.size(), result_Take.size()); for (uint index = 0; index < result_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(result_Give[index], result_Take[index], 1e-8); + ASSERT_NEAR(h_result_Give[index], h_result_Take[index], 1e-8); else - ASSERT_NEAR(result_Give[index], result_Take[index], 1e-11); + ASSERT_NEAR(h_result_Give[index], h_result_Take[index], 1e-11); } } @@ -107,22 +110,25 @@ TEST(OperatorATest, applyA_AcrossOrigin) ResidualGive residualGive_operator(level.grid(), level.levelCache(), DirBC_Interior); ResidualTake residualTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector x = generate_random_sample_data(PolarGrid(level.grid()), 42); - HostVector rhs = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector x = generate_random_sample_data(level.grid(), 42); + Vector rhs = generate_random_sample_data(level.grid(), 69); - HostVector result_Give("result_Give", level.grid().numberOfNodes()); + Vector result_Give("result_Give", level.grid().numberOfNodes()); residualGive_operator.computeResidual(result_Give, rhs, x); - HostVector result_Take("result_Take", level.grid().numberOfNodes()); + Vector result_Take("result_Take", level.grid().numberOfNodes()); residualTake_operator.computeResidual(result_Take, rhs, x); + auto h_result_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, result_Give); + auto h_result_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, result_Take); + ASSERT_EQ(result_Give.size(), result_Take.size()); for (uint index = 0; index < result_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(result_Give[index], result_Take[index], 1e-8); + ASSERT_NEAR(h_result_Give[index], h_result_Take[index], 1e-8); else - ASSERT_NEAR(result_Give[index], result_Take[index], 1e-11); + ASSERT_NEAR(h_result_Give[index], h_result_Take[index], 1e-11); } } From 639c25232d52700d3a9d0899c383572833bb9203 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 16:33:09 +0200 Subject: [PATCH 15/21] Port applyRestriction and restriction to GPU. Tests passing --- .../MultigridMethods/multigrid_F_Cycle.h | 6 ++++-- .../MultigridMethods/multigrid_V_Cycle.h | 14 +++++++------ .../MultigridMethods/multigrid_W_Cycle.h | 12 ++++++----- include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/solver.h | 6 +++++- include/GMGPolar/utils.h | 20 +++++++++---------- include/Interpolation/interpolation.h | 6 +++--- src/Interpolation/restriction.cpp | 18 ++++++++--------- tests/Interpolation/restriction.cpp | 17 ++++++++++------ 9 files changed, 58 insertions(+), 43 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index 89762c62..d463c117 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -45,6 +45,7 @@ void GMGPolar::multigrid_F_Cycle(int auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } @@ -58,7 +59,6 @@ void GMGPolar::multigrid_F_Cycle(int auto start_MGC_residual = std::chrono::high_resolution_clock::now(); level.computeResidual(residual, rhs, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -66,7 +66,8 @@ void GMGPolar::multigrid_F_Cycle(int /* --------------------- */ /* Restrict the h_residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), h_residual); + restriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); /* ------------------------------------- */ /* Solve A * error = restricted h_residual */ @@ -90,6 +91,7 @@ void GMGPolar::multigrid_F_Cycle(int /* -------------------------- */ // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. + Kokkos::deep_copy(h_residual, residual); prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index f106f397..ff92976b 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -45,6 +45,7 @@ void GMGPolar::multigrid_V_Cycle(int auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } @@ -53,23 +54,23 @@ void GMGPolar::multigrid_V_Cycle(int t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the h_residual */ + /* Compute the residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); level.computeResidual(residual, rhs, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the h_residual */ + /* Restrict the residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), h_residual); + restriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); /* ------------------------------------- */ - /* Solve A * error = restricted h_residual */ + /* Solve A * error = restricted residual */ /* ------------------------------------- */ /* Set starting error to zero. */ @@ -82,8 +83,9 @@ void GMGPolar::multigrid_V_Cycle(int /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. + Kokkos::deep_copy(residual, residual); prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index f0a7c56e..fd462a69 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -45,6 +45,7 @@ void GMGPolar::multigrid_W_Cycle(int auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const + auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } @@ -53,23 +54,23 @@ void GMGPolar::multigrid_W_Cycle(int t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the h_residual */ + /* Compute the residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); level.computeResidual(residual, rhs, solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the h_residual */ + /* Restrict the residual */ /* --------------------- */ - restriction(level.level_depth(), next_level.residual(), h_residual); + restriction(level.level_depth(), next_level_residual, residual); + Kokkos::deep_copy(next_level.residual(), next_level_residual); /* ------------------------------------- */ - /* Solve A * error = restricted h_residual */ + /* Solve A * error = restricted residual */ /* ------------------------------------- */ /* Set starting error to zero. */ @@ -90,6 +91,7 @@ void GMGPolar::multigrid_W_Cycle(int /* -------------------------- */ // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. + Kokkos::deep_copy(h_residual, residual); prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); /* ----------------------------------- */ diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index da2b7b6f..8a406ab3 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -208,7 +208,7 @@ class GMGPolar : public IGMGPolar /* ----------------------- */ /* Interpolation functions */ void prolongation(int current_level, HostVector result, HostConstVector x) const; - void restriction(int current_level, HostVector result, HostConstVector x) const; + void restriction(int current_level, Vector result, ConstVector x) const; void injection(int current_level, Vector result, ConstVector x) const; void extrapolatedProlongation(int current_level, HostVector result, HostConstVector x) const; void extrapolatedRestriction(int current_level, Vector result, ConstVector x) const; diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index 9a3120c8..c07d11fd 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -602,7 +602,11 @@ void GMGPolar::initRhsHierarchy(Host for (int level_depth = 0; level_depth < number_of_levels_ - 1; ++level_depth) { Level& current_level = levels_[level_depth]; Level& next_level = levels_[level_depth + 1]; - restriction(level_depth, next_level.rhs(), current_level.rhs()); + auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); + auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); + restriction(level_depth, next_level_rhs, rhs); + Kokkos::deep_copy(current_level.rhs(), rhs); + Kokkos::deep_copy(next_level.rhs(), next_level_rhs); } } diff --git a/include/GMGPolar/utils.h b/include/GMGPolar/utils.h index 55e80382..9061f287 100644 --- a/include/GMGPolar/utils.h +++ b/include/GMGPolar/utils.h @@ -17,15 +17,15 @@ void GMGPolar::prolongation(int curr } template -void GMGPolar::restriction(int current_level, HostVector result, - HostConstVector x) const +void GMGPolar::restriction(int current_level, Vector result, + ConstVector x) const { assert(current_level < number_of_levels_ - 1 && 0 <= current_level); if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid(levels_[current_level].grid()); - PolarGrid next_grid(levels_[current_level + 1].grid()); + const PolarGrid& current_grid = levels_[current_level].grid(); + const PolarGrid& next_grid = levels_[current_level + 1].grid(); interpolation_->applyRestriction(current_grid, next_grid, result, x); } @@ -37,8 +37,8 @@ void GMGPolar::injection(int current if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid(levels_[current_level].grid()); - PolarGrid next_grid(levels_[current_level + 1].grid()); + const PolarGrid& current_grid = levels_[current_level].grid(); + const PolarGrid& next_grid = levels_[current_level + 1].grid(); interpolation_->applyInjection(current_grid, next_grid, result, x); } @@ -53,8 +53,8 @@ void GMGPolar::extrapolatedProlongat if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid = levels_[current_level].grid(); - PolarGrid previous_grid = levels_[current_level - 1].grid(); + const PolarGrid& current_grid = levels_[current_level].grid(); + const PolarGrid& previous_grid = levels_[current_level - 1].grid(); interpolation_->applyExtrapolatedProlongation(current_grid, previous_grid, result, x); Kokkos::deep_copy(result_host, result); @@ -69,8 +69,8 @@ void GMGPolar::extrapolatedRestricti if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid = levels_[current_level].grid(); - PolarGrid next_grid = levels_[current_level + 1].grid(); + const PolarGrid& current_grid = levels_[current_level].grid(); + const PolarGrid& next_grid = levels_[current_level + 1].grid(); interpolation_->applyExtrapolatedRestriction(current_grid, next_grid, result, x); } diff --git a/include/Interpolation/interpolation.h b/include/Interpolation/interpolation.h index 530b481a..fb470116 100644 --- a/include/Interpolation/interpolation.h +++ b/include/Interpolation/interpolation.h @@ -33,9 +33,9 @@ class Interpolation ConstVector coarse_values) const; /* Scaled full weighting (FW) restriction operator. */ - void applyRestriction(const PolarGrid& fine_grid, - const PolarGrid& coarse_grid, HostVector coarse_result, - HostConstVector fine_values) const; + void applyRestriction(const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, Vector coarse_result, + ConstVector fine_values) const; void applyExtrapolatedRestriction(const PolarGrid& fine_grid, const PolarGrid& coarse_grid, Vector coarse_result, diff --git a/src/Interpolation/restriction.cpp b/src/Interpolation/restriction.cpp index 98d1d739..409e3d98 100644 --- a/src/Interpolation/restriction.cpp +++ b/src/Interpolation/restriction.cpp @@ -24,10 +24,10 @@ using namespace gmgpolar; */ static KOKKOS_INLINE_FUNCTION void coarseNodeRestriction(const int i_r_coarse, const int i_theta_coarse, - const PolarGrid& fine_grid, - const PolarGrid& coarse_grid, - HostVector& coarse_result, - HostConstVector& fine_values) + const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, + Vector& coarse_result, + ConstVector& fine_values) { const int i_r = i_r_coarse * 2; const int i_theta = i_theta_coarse * 2; @@ -69,9 +69,9 @@ static KOKKOS_INLINE_FUNCTION void coarseNodeRestriction(const int i_r_coarse, c coarse_result[coarse_grid.index(i_r_coarse, i_theta_coarse)] = value; } -void Interpolation::applyRestriction(const PolarGrid& fine_grid, - const PolarGrid& coarse_grid, HostVector coarse_result, - HostConstVector fine_values) const +void Interpolation::applyRestriction(const PolarGrid& fine_grid, + const PolarGrid& coarse_grid, Vector coarse_result, + ConstVector fine_values) const { assert(std::ssize(fine_values) == fine_grid.numberOfNodes()); assert(std::ssize(coarse_result) == coarse_grid.numberOfNodes()); @@ -82,7 +82,7 @@ void Interpolation::applyRestriction(const PolarGrid& fine_gr // The For loop matches circular access pattern */ Kokkos::parallel_for( "Interpolation: Restriction (Circular)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, 0}, // Starting point of the index space {coarse_grid.numberSmootherCircles(), coarse_grid.ntheta()} // Ending point of the index space ), @@ -94,7 +94,7 @@ void Interpolation::applyRestriction(const PolarGrid& fine_gr /* For loop matches radial access pattern */ Kokkos::parallel_for( "Interpolation: Restriction (Radial)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, coarse_grid.numberSmootherCircles()}, // Starting point of the index space {coarse_grid.ntheta(), coarse_grid.nr()} // Ending point of the index space ), diff --git a/tests/Interpolation/restriction.cpp b/tests/Interpolation/restriction.cpp index 29821ff1..8bcaf97a 100644 --- a/tests/Interpolation/restriction.cpp +++ b/tests/Interpolation/restriction.cpp @@ -57,21 +57,26 @@ TEST(RestrictionTest, RestrictionMatchesStencil) std::vector fine_angles = { 0, M_PI / 16, M_PI / 8, M_PI / 2, M_PI, M_PI + M_PI / 16, M_PI + M_PI / 8, M_PI + M_PI / 2, 2 * M_PI}; - PolarGrid fine_grid(fine_radii, fine_angles); - PolarGrid coarse_grid = coarseningGrid(fine_grid); + PolarGrid fine_grid(fine_radii, fine_angles); + PolarGrid coarse_grid = coarseningGrid(fine_grid); Interpolation I(/*DirBC*/ true); - HostVector fine_values = generate_random_sample_data(fine_grid, 5678, 0.0, 1.0); - HostVector coarse_result("coarse_result", coarse_grid.numberOfNodes()); + Vector fine_values = generate_random_sample_data(fine_grid, 5678, 0.0, 1.0); + Vector coarse_result("coarse_result", coarse_grid.numberOfNodes()); I.applyRestriction(fine_grid, coarse_grid, coarse_result, fine_values); + PolarGrid h_fine_grid(fine_grid); + PolarGrid h_coarse_grid(coarse_grid); + auto h_fine_values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, fine_values); + auto h_coarse_result = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, coarse_result); + for (int i_r_coarse = 0; i_r_coarse < coarse_grid.nr(); ++i_r_coarse) { for (int i_theta_coarse = 0; i_theta_coarse < coarse_grid.ntheta(); ++i_theta_coarse) { double expected = - expected_restriction_value(fine_grid, coarse_grid, fine_values, i_r_coarse, i_theta_coarse); - double got = coarse_result[coarse_grid.index(i_r_coarse, i_theta_coarse)]; + expected_restriction_value(h_fine_grid, h_coarse_grid, h_fine_values, i_r_coarse, i_theta_coarse); + double got = h_coarse_result[h_coarse_grid.index(i_r_coarse, i_theta_coarse)]; ASSERT_NEAR(expected, got, 1e-10) << "Mismatch at (" << i_r_coarse << ", " << i_theta_coarse << ")"; } } From ae9b80fe438d2f0bdee6939f7cbbdf2e1ab77716 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 17:45:43 +0200 Subject: [PATCH 16/21] Put Level.rhs() on GPU. Tests passing --- .../extrapolated_multigrid_F_Cycle.h | 4 +- .../extrapolated_multigrid_V_Cycle.h | 4 +- .../extrapolated_multigrid_W_Cycle.h | 4 +- include/GMGPolar/solver.h | 57 +++++++++---------- include/Level/level.h | 6 +- include/Level/level.inl | 4 +- 6 files changed, 36 insertions(+), 43 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 636d250d..384272ad 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { @@ -56,13 +55,12 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); + next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); Kokkos::deep_copy(next_level.solution(), next_level_solution); Kokkos::deep_copy(h_residual, residual); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 43a3f6c5..d76e0b6f 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { @@ -56,14 +55,13 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); + next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index b84a6f5c..e9045c43 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { @@ -56,14 +55,13 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level_rhs, next_level_solution); + next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); Kokkos::deep_copy(residual, h_residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index c07d11fd..51b42a22 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -13,10 +13,8 @@ void GMGPolar::solve(const BoundaryC /* ------------------------------------- */ /* Build rhs_f on Level 0 (finest Level) */ /* ------------------------------------- */ - HostVector rhs_f_host = levels_[0].rhs(); - auto rhs_f = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), rhs_f_host); + Vector rhs_f = levels_[0].rhs(); build_rhs_f(levels_[0], rhs_f, boundary_conditions, source_term); - Kokkos::deep_copy(rhs_f_host, rhs_f); /* ---------------- */ /* Discretize rhs_f */ @@ -28,13 +26,12 @@ void GMGPolar::solve(const BoundaryC // Inject rhs if there is a next level if (level_depth + 1 < initial_rhs_f_levels) { Level& next_level = levels_[level_depth + 1]; - auto current_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); - injection(level_depth, next_level_rhs, current_level_rhs); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + injection(level_depth, next_level.rhs(), current_level.rhs()); } // Discretize the rhs for the current level - discretize_rhs_f(current_level, current_level.rhs()); + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, current_level.rhs()); + discretize_rhs_f(current_level, h_rhs); + Kokkos::deep_copy(current_level.rhs(), h_rhs); } auto end_setup_rhs = std::chrono::high_resolution_clock::now(); @@ -321,7 +318,9 @@ void GMGPolar::solvePCG(double& init // z = M^{-1} * r (preconditioned residual) if (PCG_FMG_) { - initRhsHierarchy(level.rhs()); + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); + initRhsHierarchy(h_rhs); + Kokkos::deep_copy(level.rhs(), h_rhs); fullMultigridApproximation(PCG_FMG_cycle_, PCG_FMG_iterations_); } else { @@ -334,7 +333,8 @@ void GMGPolar::solvePCG(double& init Kokkos::deep_copy(pcg_search_direction_, level.solution()); // r^T * z - double r_z = dot_product(HostConstVector(level.rhs()), HostConstVector(level.solution())); + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); + double r_z = dot_product(HostConstVector(h_rhs), HostConstVector(level.solution())); while (number_of_iterations_ < max_iterations_) { @@ -363,14 +363,15 @@ void GMGPolar::solvePCG(double& init linear_combination(pcg_solution_, 1.0, HostConstVector(pcg_search_direction_), alpha); // r -= alpha * A*p - linear_combination(level.rhs(), 1.0, HostConstVector(level.residual()), -alpha); + Kokkos::deep_copy(h_rhs, level.rhs()); + linear_combination(h_rhs, 1.0, HostConstVector(level.residual()), -alpha); /* ---------------------------- */ /* Compute convergence criteria */ /* ---------------------------- */ auto start_check_convergence = std::chrono::high_resolution_clock::now(); - current_residual_norm = residualNorm(residual_norm_type_, level, level.rhs()); + current_residual_norm = residualNorm(residual_norm_type_, level, h_rhs); residual_norms_.push_back(current_residual_norm); current_relative_residual_norm = current_residual_norm / initial_residual_norm; @@ -402,17 +403,17 @@ void GMGPolar::solvePCG(double& init // z = M^{-1} * r (preconditioned residual) if (PCG_FMG_) { - initRhsHierarchy(level.rhs()); + initRhsHierarchy(h_rhs); fullMultigridApproximation(PCG_FMG_cycle_, PCG_FMG_iterations_); } else { // z = I^{-1} * r (no preconditioning) - Kokkos::deep_copy(level.solution(), level.rhs()); + Kokkos::deep_copy(level.solution(), h_rhs); } applyMultigridIterations(level, PCG_MG_cycle_, PCG_MG_iterations_); // r^T * z - double r_z_new = dot_product(HostConstVector(level.rhs()), HostConstVector(level.solution())); + double r_z_new = dot_product(HostConstVector(h_rhs), HostConstVector(level.solution())); // beta = (current r^T * z) / (previous r^T * z) double beta = r_z_new / r_z; // r_z = r^T * z for next iteration @@ -435,16 +436,17 @@ template ::applyMultigridIterations( Level& level, MultigridCycleType cycle, int iterations) { + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); for (int i = 0; i < iterations; i++) { switch (cycle) { case MultigridCycleType::V_CYCLE: - multigrid_V_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + multigrid_V_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; case MultigridCycleType::W_CYCLE: - multigrid_W_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + multigrid_W_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; case MultigridCycleType::F_CYCLE: - multigrid_F_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + multigrid_F_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; default: std::cerr << "Error: Unknown multigrid cycle type!" << std::endl; @@ -457,16 +459,17 @@ template ::applyExtrapolatedMultigridIterations( Level& level, MultigridCycleType cycle, int iterations) { + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); for (int i = 0; i < iterations; i++) { switch (cycle) { case MultigridCycleType::V_CYCLE: - extrapolated_multigrid_V_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + extrapolated_multigrid_V_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; case MultigridCycleType::W_CYCLE: - extrapolated_multigrid_W_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + extrapolated_multigrid_W_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; case MultigridCycleType::F_CYCLE: - extrapolated_multigrid_F_Cycle(level.level_depth(), level.solution(), level.rhs(), level.residual()); + extrapolated_multigrid_F_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; default: std::cerr << "Error: Unknown multigrid cycle type!" << std::endl; @@ -486,8 +489,7 @@ void GMGPolar::updateResidualNorms( { auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.solution()); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.residual()); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), level.rhs()); - level.computeResidual(residual, rhs, solution); + level.computeResidual(residual, level.rhs(), solution); if (extrapolation_ != ExtrapolationType::NONE) { Level& next_level = levels_[level.level_depth() + 1]; auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); @@ -505,7 +507,8 @@ void GMGPolar::updateResidualNorms( residual_norms_.push_back(current_residual_norm); if (number_of_iterations_ == 0) { - initial_residual_norm = !FMG_ ? current_residual_norm : residualNorm(residual_norm_type_, level, level.rhs()); + auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); + initial_residual_norm = !FMG_ ? current_residual_norm : residualNorm(residual_norm_type_, level, h_rhs); } current_relative_residual_norm = current_residual_norm / initial_residual_norm; @@ -602,11 +605,7 @@ void GMGPolar::initRhsHierarchy(Host for (int level_depth = 0; level_depth < number_of_levels_ - 1; ++level_depth) { Level& current_level = levels_[level_depth]; Level& next_level = levels_[level_depth + 1]; - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), current_level.rhs()); - auto next_level_rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.rhs()); - restriction(level_depth, next_level_rhs, rhs); - Kokkos::deep_copy(current_level.rhs(), rhs); - Kokkos::deep_copy(next_level.rhs(), next_level_rhs); + restriction(level_depth, next_level.rhs(), current_level.rhs()); } } diff --git a/include/Level/level.h b/include/Level/level.h index 5d7ee582..4b0d7c41 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -83,8 +83,8 @@ class Level const PolarGrid& grid() const; const LevelCacheType& levelCache() const; - HostVector rhs(); - HostConstVector rhs() const; + Vector rhs(); + ConstVector rhs() const; HostVector solution(); HostConstVector solution() const; HostVector residual(); @@ -125,7 +125,7 @@ class Level std::unique_ptr> op_smoother_; std::unique_ptr> op_extrapolated_smoother_; - HostVector rhs_; + Vector rhs_; HostVector solution_; HostVector residual_; HostVector error_correction_; diff --git a/include/Level/level.inl b/include/Level/level.inl index 0c0d5549..a2375d24 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -41,13 +41,13 @@ Level::levelCache() const } template -HostVector Level::rhs() +Vector Level::rhs() { return rhs_; } template -HostConstVector Level::rhs() const +ConstVector Level::rhs() const { return rhs_; } From 671d8c2a093097e8e637fdf6b328acaec29b2b12 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Tue, 9 Jun 2026 18:24:04 +0200 Subject: [PATCH 17/21] Put extrapolatedProlongation on GPU. Tests passing --- .../MultigridMethods/extrapolated_multigrid_F_Cycle.h | 9 ++++----- .../MultigridMethods/extrapolated_multigrid_V_Cycle.h | 11 +++++------ .../MultigridMethods/extrapolated_multigrid_W_Cycle.h | 11 +++++------ include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/utils.h | 7 +------ 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 384272ad..121a4c01 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -62,13 +62,12 @@ void GMGPolar::extrapolated_multigri -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated h_residual */ + /* Solve A * error = restricted extrapolated residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -88,14 +87,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); + Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index d76e0b6f..853077f0 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -45,7 +45,7 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------------------------------- */ - /* Compute the restricted extrapolated h_residual */ + /* Compute the restricted extrapolated residual */ /* -------------------------------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); @@ -62,13 +62,12 @@ void GMGPolar::extrapolated_multigri -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - Kokkos::deep_copy(h_residual, residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated h_residual */ + /* Solve A * error = restricted extrapolated residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -82,14 +81,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); + Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index e9045c43..15568976 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -45,7 +45,7 @@ void GMGPolar::extrapolated_multigri t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------------------------------- */ - /* Compute the restricted extrapolated h_residual */ + /* Compute the restricted extrapolated residual */ /* -------------------------------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); @@ -62,13 +62,12 @@ void GMGPolar::extrapolated_multigri -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); - Kokkos::deep_copy(residual, h_residual); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* -------------------------------------------------- */ - /* Solve A * error = restricted extrapolated h_residual */ + /* Solve A * error = restricted extrapolated residual */ /* -------------------------------------------------- */ // Note: We deliberately use the non-extrapolated multigrid cycle here. @@ -88,14 +87,14 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - extrapolatedProlongation(next_level.level_depth(), h_residual, next_level.error_correction()); + Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); + extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index 8a406ab3..af6d28fc 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -210,7 +210,7 @@ class GMGPolar : public IGMGPolar void prolongation(int current_level, HostVector result, HostConstVector x) const; void restriction(int current_level, Vector result, ConstVector x) const; void injection(int current_level, Vector result, ConstVector x) const; - void extrapolatedProlongation(int current_level, HostVector result, HostConstVector x) const; + void extrapolatedProlongation(int current_level, Vector result, ConstVector x) const; void extrapolatedRestriction(int current_level, Vector result, ConstVector x) const; void FMGInterpolation(int current_level, HostVector result, HostConstVector x) const; diff --git a/include/GMGPolar/utils.h b/include/GMGPolar/utils.h index 9061f287..e0c54de0 100644 --- a/include/GMGPolar/utils.h +++ b/include/GMGPolar/utils.h @@ -44,11 +44,8 @@ void GMGPolar::injection(int current template void GMGPolar::extrapolatedProlongation( - int current_level, HostVector result_host, HostConstVector x_host) const + int current_level, Vector result, ConstVector x) const { - auto result = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), result_host); - auto x = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), x_host); - assert(current_level < number_of_levels_ && 1 <= current_level); if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); @@ -56,8 +53,6 @@ void GMGPolar::extrapolatedProlongat const PolarGrid& current_grid = levels_[current_level].grid(); const PolarGrid& previous_grid = levels_[current_level - 1].grid(); interpolation_->applyExtrapolatedProlongation(current_grid, previous_grid, result, x); - - Kokkos::deep_copy(result_host, result); } template From c1e54f42d7aac24d88078fde06f7cd03424ec87e Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Wed, 10 Jun 2026 10:06:09 +0200 Subject: [PATCH 18/21] Put level.error_correction on GPU. Tests passing --- .../extrapolated_multigrid_F_Cycle.h | 14 +++++++------- .../extrapolated_multigrid_V_Cycle.h | 12 ++++++------ .../extrapolated_multigrid_W_Cycle.h | 14 +++++++------- .../MultigridMethods/multigrid_F_Cycle.h | 18 ++++++++++-------- .../MultigridMethods/multigrid_V_Cycle.h | 10 ++++++---- .../MultigridMethods/multigrid_W_Cycle.h | 12 +++++++----- include/Level/level.h | 6 +++--- include/Level/level.inl | 4 ++-- 8 files changed, 48 insertions(+), 42 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h index 121a4c01..78f05d34 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_F_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -55,10 +54,10 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); + next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level.error_correction()), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -75,12 +74,13 @@ void GMGPolar::extrapolated_multigri assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_F_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, next_level.error_correction()); + multigrid_F_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_V_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + multigrid_V_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); } @@ -89,8 +89,8 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); - extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h index 853077f0..a97212f2 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_V_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -55,10 +54,10 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); + next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level.error_correction()), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -75,7 +74,8 @@ void GMGPolar::extrapolated_multigri assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_V_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, next_level.error_correction()); + multigrid_V_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* -------------------------- */ @@ -83,8 +83,8 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); - extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index 15568976..2aa571b2 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -30,7 +30,6 @@ void GMGPolar::extrapolated_multigri auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); - auto next_level_error_correction = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.error_correction()); for (int i = 0; i < pre_smoothing_steps_; i++) { if (level.level_depth() == 0 && !full_grid_smoothing_) { @@ -55,10 +54,10 @@ void GMGPolar::extrapolated_multigri // f_{l-1} - A_{l-1}* Inject(u_l) injection(level.level_depth(), next_level_solution, solution); - next_level.computeResidual(next_level_error_correction, next_level.rhs(), next_level_solution); + next_level.computeResidual(next_level.error_correction(), next_level.rhs(), next_level_solution); // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) - linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level_error_correction), + linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level.error_correction()), -1.0 / 3.0); Kokkos::deep_copy(next_level.residual(), next_level_residual); Kokkos::deep_copy(next_level.solution(), next_level_solution); @@ -75,12 +74,13 @@ void GMGPolar::extrapolated_multigri assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); + multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); } @@ -89,8 +89,8 @@ void GMGPolar::extrapolated_multigri /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(next_level_error_correction, next_level.error_correction()); - extrapolatedProlongation(next_level.level_depth(), residual, next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index d463c117..10f26096 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -54,7 +54,7 @@ void GMGPolar::multigrid_F_Cycle(int t_avg_MGC_preSmoothing_ += std::chrono::duration(end_MGC_preSmoothing - start_MGC_preSmoothing).count(); /* -------------------- */ - /* Compute the h_residual */ + /* Compute the residual */ /* -------------------- */ auto start_MGC_residual = std::chrono::high_resolution_clock::now(); @@ -64,40 +64,42 @@ void GMGPolar::multigrid_F_Cycle(int t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); /* --------------------- */ - /* Restrict the h_residual */ + /* Restrict the residual */ /* --------------------- */ restriction(level.level_depth(), next_level_residual, residual); Kokkos::deep_copy(next_level.residual(), next_level_residual); /* ------------------------------------- */ - /* Solve A * error = restricted h_residual */ + /* Solve A * error = restricted residual */ /* ------------------------------------- */ /* Set starting error to zero. */ assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_F_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); + multigrid_F_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_V_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + multigrid_V_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); } /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. Kokkos::deep_copy(h_residual, residual); - prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); + prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + Kokkos::deep_copy(residual, h_residual); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index ff92976b..64463b5f 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -77,7 +77,8 @@ void GMGPolar::multigrid_V_Cycle(int assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_V_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); + multigrid_V_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* -------------------------- */ @@ -85,13 +86,14 @@ void GMGPolar::multigrid_V_Cycle(int /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(residual, residual); - prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); + Kokkos::deep_copy(h_residual, residual); + prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + Kokkos::deep_copy(residual, h_residual); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index fd462a69..dea2ae12 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -77,27 +77,29 @@ void GMGPolar::multigrid_W_Cycle(int assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); + multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level.residual(), + multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), next_level.solution()); } /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ - // Use 'h_residual' instead of 'level.error_correction()' as a temporary buffer. + // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. Kokkos::deep_copy(h_residual, residual); - prolongation(next_level.level_depth(), h_residual, next_level.error_correction()); + prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); + Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); + Kokkos::deep_copy(residual, h_residual); /* ----------------------------------- */ /* Compute the corrected approximation */ /* ----------------------------------- */ - Kokkos::deep_copy(residual, h_residual); add(solution, ConstVector(residual)); /* ------------- */ diff --git a/include/Level/level.h b/include/Level/level.h index 4b0d7c41..de626246 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -89,8 +89,8 @@ class Level HostConstVector solution() const; HostVector residual(); HostConstVector residual() const; - HostVector error_correction(); - HostConstVector error_correction() const; + Vector error_correction(); + ConstVector error_correction() const; // -------------- // // Apply Residual // @@ -128,7 +128,7 @@ class Level Vector rhs_; HostVector solution_; HostVector residual_; - HostVector error_correction_; + Vector error_correction_; }; template diff --git a/include/Level/level.inl b/include/Level/level.inl index a2375d24..3060afc0 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -77,13 +77,13 @@ HostConstVector Level::resid } template -HostVector Level::error_correction() +Vector Level::error_correction() { return error_correction_; } template -HostConstVector Level::error_correction() const +ConstVector Level::error_correction() const { return error_correction_; } From 6e193d28ce4f2a5f13cdce9f46f98cf79cea994f Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Wed, 10 Jun 2026 10:36:34 +0200 Subject: [PATCH 19/21] Port applyProlongation and prolongation to GPU. Tests passing --- .../MultigridMethods/multigrid_F_Cycle.h | 4 +--- .../MultigridMethods/multigrid_V_Cycle.h | 4 +--- .../MultigridMethods/multigrid_W_Cycle.h | 4 +--- include/GMGPolar/gmgpolar.h | 2 +- include/GMGPolar/utils.h | 8 ++++---- include/Interpolation/interpolation.h | 6 +++--- src/Interpolation/prolongation.cpp | 18 +++++++++--------- tests/Interpolation/prolongation.cpp | 18 ++++++++++++------ 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index 10f26096..e6e95fcd 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -92,10 +92,8 @@ void GMGPolar::multigrid_F_Cycle(int /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(h_residual, residual); - prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); - Kokkos::deep_copy(residual, h_residual); + prolongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index 64463b5f..c67cd6b5 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -86,10 +86,8 @@ void GMGPolar::multigrid_V_Cycle(int /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(h_residual, residual); - prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); - Kokkos::deep_copy(residual, h_residual); + prolongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index dea2ae12..2e8951bd 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -92,10 +92,8 @@ void GMGPolar::multigrid_W_Cycle(int /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(h_residual, residual); - prolongation(next_level.level_depth(), h_residual, h_next_level_error_correction); Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); - Kokkos::deep_copy(residual, h_residual); + prolongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ /* Compute the corrected approximation */ diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index af6d28fc..f247ee63 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -207,7 +207,7 @@ class GMGPolar : public IGMGPolar /* ----------------------- */ /* Interpolation functions */ - void prolongation(int current_level, HostVector result, HostConstVector x) const; + void prolongation(int current_level, Vector result, ConstVector x) const; void restriction(int current_level, Vector result, ConstVector x) const; void injection(int current_level, Vector result, ConstVector x) const; void extrapolatedProlongation(int current_level, Vector result, ConstVector x) const; diff --git a/include/GMGPolar/utils.h b/include/GMGPolar/utils.h index e0c54de0..b7a8250c 100644 --- a/include/GMGPolar/utils.h +++ b/include/GMGPolar/utils.h @@ -4,15 +4,15 @@ /* Interpolation */ /* ---------------------------------------------------------------------- */ template -void GMGPolar::prolongation(int current_level, HostVector result, - HostConstVector x) const +void GMGPolar::prolongation(int current_level, Vector result, + ConstVector x) const { assert(current_level < number_of_levels_ && 1 <= current_level); if (!interpolation_) throw std::runtime_error("Interpolation not initialized."); - PolarGrid current_grid(levels_[current_level].grid()); - PolarGrid previous_grid(levels_[current_level - 1].grid()); + const PolarGrid& current_grid = levels_[current_level].grid(); + const PolarGrid& previous_grid = levels_[current_level - 1].grid(); interpolation_->applyProlongation(current_grid, previous_grid, result, x); } diff --git a/include/Interpolation/interpolation.h b/include/Interpolation/interpolation.h index fb470116..786dc4d5 100644 --- a/include/Interpolation/interpolation.h +++ b/include/Interpolation/interpolation.h @@ -24,9 +24,9 @@ class Interpolation ConstVector fine_values) const; /* Bilinear interpolation operator */ - void applyProlongation(const PolarGrid& coarse_grid, - const PolarGrid& fine_grid, HostVector fine_result, - HostConstVector coarse_values) const; + void applyProlongation(const PolarGrid& coarse_grid, + const PolarGrid& fine_grid, Vector fine_result, + ConstVector coarse_values) const; void applyExtrapolatedProlongation(const PolarGrid& coarse_grid, const PolarGrid& fine_grid, Vector fine_result, diff --git a/src/Interpolation/prolongation.cpp b/src/Interpolation/prolongation.cpp index b630a60c..c6a6846b 100644 --- a/src/Interpolation/prolongation.cpp +++ b/src/Interpolation/prolongation.cpp @@ -53,10 +53,10 @@ using namespace gmgpolar; */ static KOKKOS_INLINE_FUNCTION void fineNodeProlongation(const int i_r, const int i_theta, - const PolarGrid& coarse_grid, - const PolarGrid& fine_grid, - HostVector& fine_result, - HostConstVector& coarse_values) + const PolarGrid& coarse_grid, + const PolarGrid& fine_grid, + Vector& fine_result, + ConstVector& coarse_values) { const int i_r_coarse = i_r / 2; const int i_theta_coarse = i_theta / 2; @@ -109,9 +109,9 @@ static KOKKOS_INLINE_FUNCTION void fineNodeProlongation(const int i_r, const int } } -void Interpolation::applyProlongation(const PolarGrid& coarse_grid, - const PolarGrid& fine_grid, HostVector fine_result, - HostConstVector coarse_values) const +void Interpolation::applyProlongation(const PolarGrid& coarse_grid, + const PolarGrid& fine_grid, Vector fine_result, + ConstVector coarse_values) const { assert(std::ssize(coarse_values) == coarse_grid.numberOfNodes()); assert(std::ssize(fine_result) == fine_grid.numberOfNodes()); @@ -122,7 +122,7 @@ void Interpolation::applyProlongation(const PolarGrid& coarse // The For loop matches circular access pattern */ Kokkos::parallel_for( "Interpolation: Prolongation (Circular)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, 0}, // Starting point of the index space {fine_grid.numberSmootherCircles(), fine_grid.ntheta()} // Ending point of the index space ), @@ -134,7 +134,7 @@ void Interpolation::applyProlongation(const PolarGrid& coarse /* For loop matches radial access pattern */ Kokkos::parallel_for( "Interpolation: Prolongation (Radial)", - Kokkos::MDRangePolicy>( // Rank of the index space + Kokkos::MDRangePolicy>( // Rank of the index space {0, fine_grid.numberSmootherCircles()}, // Starting point of the index space {fine_grid.ntheta(), fine_grid.nr()} // Ending point of the index space ), diff --git a/tests/Interpolation/prolongation.cpp b/tests/Interpolation/prolongation.cpp index a9018f1b..5b10f186 100644 --- a/tests/Interpolation/prolongation.cpp +++ b/tests/Interpolation/prolongation.cpp @@ -61,20 +61,26 @@ TEST(ProlongationTest, ProlongationMatchesStencil) std::vector fine_angles = { 0, M_PI / 16, M_PI / 8, M_PI / 2, M_PI, M_PI + M_PI / 16, M_PI + M_PI / 8, M_PI + M_PI / 2, 2 * M_PI}; - PolarGrid fine_grid(fine_radii, fine_angles); - PolarGrid coarse_grid = coarseningGrid(fine_grid); + PolarGrid fine_grid(fine_radii, fine_angles); + PolarGrid coarse_grid = coarseningGrid(fine_grid); Interpolation I(/*DirBC*/ true); - HostVector coarse_values = generate_random_sample_data(coarse_grid, 1234); - HostVector fine_result("fine_result", fine_grid.numberOfNodes()); + Vector coarse_values = generate_random_sample_data(coarse_grid, 1234); + Vector fine_result("fine_result", fine_grid.numberOfNodes()); I.applyProlongation(coarse_grid, fine_grid, fine_result, coarse_values); + PolarGrid h_fine_grid(fine_grid); + PolarGrid h_coarse_grid(coarse_grid); + + auto h_coarse_values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, coarse_values); + auto h_fine_result = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, fine_result); + for (int i_r = 0; i_r < fine_grid.nr(); ++i_r) { for (int i_theta = 0; i_theta < fine_grid.ntheta(); ++i_theta) { - double expected = expected_value(coarse_grid, fine_grid, coarse_values, i_r, i_theta); - double got = fine_result[fine_grid.index(i_r, i_theta)]; + double expected = expected_value(h_coarse_grid, h_fine_grid, h_coarse_values, i_r, i_theta); + double got = h_fine_result[h_fine_grid.index(i_r, i_theta)]; ASSERT_NEAR(expected, got, 1e-10) << "Mismatch at (" << i_r << ", " << i_theta << ")"; } } From adb30edae4d7fbc845332e0878b717b4f732b410 Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Wed, 10 Jun 2026 13:21:47 +0200 Subject: [PATCH 20/21] Port solveInPlace to GPU. Tests passing --- .../DirectSolverGive/directSolverGive.h | 2 +- .../DirectSolverGive/directSolverGive.inl | 5 +- .../DirectSolverTake/directSolverTake.h | 2 +- .../DirectSolverTake/directSolverTake.inl | 5 +- include/DirectSolver/directSolver.h | 2 +- .../MultigridMethods/multigrid_F_Cycle.h | 6 +- .../MultigridMethods/multigrid_V_Cycle.h | 12 +- .../MultigridMethods/multigrid_W_Cycle.h | 12 +- include/GMGPolar/solver.h | 4 +- include/Level/level.h | 2 +- include/Level/level.inl | 2 +- tests/DirectSolver/directSolver.cpp | 162 ++++++++---------- .../extrapolated_smoother.cpp | 56 +++--- tests/Smoother/smoother.cpp | 56 +++--- 14 files changed, 147 insertions(+), 181 deletions(-) diff --git a/include/DirectSolver/DirectSolverGive/directSolverGive.h b/include/DirectSolver/DirectSolverGive/directSolverGive.h index a21063ce..458fc977 100644 --- a/include/DirectSolver/DirectSolverGive/directSolverGive.h +++ b/include/DirectSolver/DirectSolverGive/directSolverGive.h @@ -13,7 +13,7 @@ class DirectSolverGive : public DirectSolver bool DirBC_Interior); // Note: The rhs (right-hand side) vector gets overwritten during the solution process. - void solveInPlace(HostVector solution) override; + void solveInPlace(Vector solution) override; private: #ifdef GMGPOLAR_USE_MUMPS diff --git a/include/DirectSolver/DirectSolverGive/directSolverGive.inl b/include/DirectSolver/DirectSolverGive/directSolverGive.inl index 05f09d13..b9d856b3 100644 --- a/include/DirectSolver/DirectSolverGive/directSolverGive.inl +++ b/include/DirectSolver/DirectSolverGive/directSolverGive.inl @@ -14,9 +14,8 @@ DirectSolverGive::DirectSolverGive(const PolarGrid -void DirectSolverGive::solveInPlace(HostVector h_solution) +void DirectSolverGive::solveInPlace(Vector solution) { - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); // Adjusts the right-hand side vector to account for symmetry corrections. // This transforms the system matrixA * solution = rhs into the equivalent system: // symmetric_DBc(matrixA) * solution = rhs - applySymmetryShift(rhs). @@ -25,6 +24,4 @@ void DirectSolverGive::solveInPlace(HostVector h_solutio applySymmetryShift(solution); // Solves the adjusted system symmetric(matrixA) * solution = rhs using the MUMPS solver. system_solver_.solveInPlace(solution); - - Kokkos::deep_copy(h_solution, solution); } diff --git a/include/DirectSolver/DirectSolverTake/directSolverTake.h b/include/DirectSolver/DirectSolverTake/directSolverTake.h index 60042499..ffc2301a 100644 --- a/include/DirectSolver/DirectSolverTake/directSolverTake.h +++ b/include/DirectSolver/DirectSolverTake/directSolverTake.h @@ -13,7 +13,7 @@ class DirectSolverTake : public DirectSolver bool DirBC_Interior); // Note: The rhs (right-hand side) vector gets overwritten during the solution process. - void solveInPlace(HostVector solution) override; + void solveInPlace(Vector solution) override; private: #ifdef GMGPOLAR_USE_MUMPS diff --git a/include/DirectSolver/DirectSolverTake/directSolverTake.inl b/include/DirectSolver/DirectSolverTake/directSolverTake.inl index 9bdea7e9..144ad98f 100644 --- a/include/DirectSolver/DirectSolverTake/directSolverTake.inl +++ b/include/DirectSolver/DirectSolverTake/directSolverTake.inl @@ -14,9 +14,8 @@ DirectSolverTake::DirectSolverTake(const PolarGrid -void DirectSolverTake::solveInPlace(HostVector h_solution) +void DirectSolverTake::solveInPlace(Vector solution) { - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); // Adjusts the right-hand side vector to account for symmetry corrections. // This transforms the system matrixA * solution = rhs into the equivalent system: // symmetric_DBc(matrixA) * solution = rhs - applySymmetryShift(rhs). @@ -25,6 +24,4 @@ void DirectSolverTake::solveInPlace(HostVector h_solutio applySymmetryShift(solution); // Solves the adjusted system symmetric(matrixA) * solution = rhs using the MUMPS solver. system_solver_.solveInPlace(solution); - - Kokkos::deep_copy(h_solution, solution); } diff --git a/include/DirectSolver/directSolver.h b/include/DirectSolver/directSolver.h index 881dd6bf..1dc9e392 100644 --- a/include/DirectSolver/directSolver.h +++ b/include/DirectSolver/directSolver.h @@ -37,7 +37,7 @@ class DirectSolver virtual ~DirectSolver() = default; // Note: The rhs (right-hand side) vector gets overwritten during the solution process. - virtual void solveInPlace(HostVector solution) = 0; + virtual void solveInPlace(Vector solution) = 0; protected: const PolarGrid& grid_; diff --git a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h index e6e95fcd..72ccc7ce 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_F_Cycle.h @@ -6,6 +6,7 @@ void GMGPolar::multigrid_F_Cycle(int HostConstVector h_rhs, HostVector h_residual) { + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); assert(0 <= level_depth && level_depth < number_of_levels_); std::chrono::high_resolution_clock::time_point start_MGC; @@ -25,7 +26,7 @@ void GMGPolar::multigrid_F_Cycle(int /* Step 2: Solve for the h_solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(h_solution); + coarsest_level.directSolveInPlace(solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,7 +43,6 @@ void GMGPolar::multigrid_F_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); @@ -108,7 +108,6 @@ void GMGPolar::multigrid_F_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); @@ -120,4 +119,5 @@ void GMGPolar::multigrid_F_Cycle(int auto end_MGC = std::chrono::high_resolution_clock::now(); t_avg_MGC_total_ += std::chrono::duration(end_MGC - start_MGC).count(); } + Kokkos::deep_copy(h_solution, solution); } diff --git a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h index c67cd6b5..9d845429 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_V_Cycle.h @@ -6,6 +6,7 @@ void GMGPolar::multigrid_V_Cycle(int HostConstVector h_rhs, HostVector h_residual) { + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); assert(0 <= level_depth && level_depth < number_of_levels_); std::chrono::high_resolution_clock::time_point start_MGC; @@ -19,13 +20,13 @@ void GMGPolar::multigrid_V_Cycle(int /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy h_rhs in h_solution */ - Kokkos::deep_copy(h_solution, h_rhs); + /* Step 1: Copy h_rhs in solution */ + Kokkos::deep_copy(solution, h_rhs); - /* Step 2: Solve for the h_solution in place */ + /* Step 2: Solve for the solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(h_solution); + coarsest_level.directSolveInPlace(solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,7 +43,6 @@ void GMGPolar::multigrid_V_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); @@ -102,7 +102,6 @@ void GMGPolar::multigrid_V_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); @@ -114,4 +113,5 @@ void GMGPolar::multigrid_V_Cycle(int auto end_MGC = std::chrono::high_resolution_clock::now(); t_avg_MGC_total_ += std::chrono::duration(end_MGC - start_MGC).count(); } + Kokkos::deep_copy(h_solution, solution); } diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index 2e8951bd..4d6affb0 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -6,6 +6,7 @@ void GMGPolar::multigrid_W_Cycle(int HostConstVector h_rhs, HostVector h_residual) { + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); assert(0 <= level_depth && level_depth < number_of_levels_); std::chrono::high_resolution_clock::time_point start_MGC; @@ -19,13 +20,13 @@ void GMGPolar::multigrid_W_Cycle(int /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy h_rhs in h_solution */ - Kokkos::deep_copy(h_solution, h_rhs); + /* Step 1: Copy h_rhs in solution */ + Kokkos::deep_copy(solution, h_rhs); - /* Step 2: Solve for the h_solution in place */ + /* Step 2: Solve for the solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); - coarsest_level.directSolveInPlace(h_solution); + coarsest_level.directSolveInPlace(solution); auto end_MGC_directSolver = std::chrono::high_resolution_clock::now(); t_avg_MGC_directSolver_ += std::chrono::duration(end_MGC_directSolver - start_MGC_directSolver).count(); @@ -42,7 +43,6 @@ void GMGPolar::multigrid_W_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); @@ -108,7 +108,6 @@ void GMGPolar::multigrid_W_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_solution, solution); Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); @@ -120,4 +119,5 @@ void GMGPolar::multigrid_W_Cycle(int auto end_MGC = std::chrono::high_resolution_clock::now(); t_avg_MGC_total_ += std::chrono::duration(end_MGC - start_MGC).count(); } + Kokkos::deep_copy(h_solution, solution); } diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index 51b42a22..bdefc3be 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -207,7 +207,9 @@ void GMGPolar::fullMultigridApproxim // Solve directly on the coarsest level Kokkos::deep_copy(coarsest_level.solution(), coarsest_level.rhs()); - coarsest_level.directSolveInPlace(coarsest_level.solution()); + auto coarsest_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), coarsest_level.solution()); + coarsest_level.directSolveInPlace(coarsest_level_solution); + Kokkos::deep_copy(coarsest_level.solution(), coarsest_level_solution); // Prolongate the solution from the coarsest level up to the finest, while applying Multigrid Cycles on each level for (int depth = coarsest_depth; depth > 0; --depth) { diff --git a/include/Level/level.h b/include/Level/level.h index de626246..dd2b7db9 100644 --- a/include/Level/level.h +++ b/include/Level/level.h @@ -102,7 +102,7 @@ class Level // Solve coarse System // void initializeDirectSolver(const bool DirBC_Interior, const StencilDistributionMethod stencil_distribution_method); // Note: The rhs (right-hand side) vector gets overwritten by the solution. - void directSolveInPlace(HostVector x) const; + void directSolveInPlace(Vector x) const; // --------------- // // Apply Smoothing // diff --git a/include/Level/level.inl b/include/Level/level.inl index 3060afc0..3ac1f3f7 100644 --- a/include/Level/level.inl +++ b/include/Level/level.inl @@ -140,7 +140,7 @@ void Level::initializeDirectSolver( } template -void Level::directSolveInPlace(HostVector x) const +void Level::directSolveInPlace(Vector x) const { if (!op_directSolver_) throw std::runtime_error("Coarse Solver not initialized."); diff --git a/tests/DirectSolver/directSolver.cpp b/tests/DirectSolver/directSolver.cpp index 37700d7b..4ebf8744 100644 --- a/tests/DirectSolver/directSolver.cpp +++ b/tests/DirectSolver/directSolver.cpp @@ -71,20 +71,23 @@ TEST(DirectSolverTest, directSolver_DirBC_Interior) DirectSolverTake directSolverGive_operator(level.grid(), level.levelCache(), DirBC_Interior); DirectSolverGive directSolverTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector solution_Give = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector solution_Give = generate_random_sample_data(level.grid(), 69); directSolverGive_operator.solveInPlace(solution_Give); - HostVector solution_Take = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector solution_Take = generate_random_sample_data(level.grid(), 69); directSolverTake_operator.solveInPlace(solution_Take); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Take); + ASSERT_EQ(solution_Give.size(), solution_Take.size()); for (uint index = 0; index < solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give(index), solution_Take(index), 1e-11); + ASSERT_NEAR(h_solution_Give(index), h_solution_Take(index), 1e-11); else - ASSERT_NEAR(solution_Give(index), solution_Take(index), 1e-11); + ASSERT_NEAR(h_solution_Give(index), h_solution_Take(index), 1e-11); } } @@ -120,20 +123,23 @@ TEST(DirectSolverTest, directSolver_AcrossOrigin) DirectSolverGive directSolverGive_operator(level.grid(), level.levelCache(), DirBC_Interior); DirectSolverTake directSolverTake_operator(level.grid(), level.levelCache(), DirBC_Interior); - HostVector solution_Give = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector solution_Give = generate_random_sample_data(level.grid(), 69); directSolverGive_operator.solveInPlace(solution_Give); - HostVector solution_Take = generate_random_sample_data(PolarGrid(level.grid()), 69); + Vector solution_Take = generate_random_sample_data(level.grid(), 69); directSolverTake_operator.solveInPlace(solution_Take); + auto h_solution_Give = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Give); + auto h_solution_Take = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), solution_Take); + ASSERT_EQ(solution_Give.size(), solution_Take.size()); for (uint index = 0; index < solution_Give.size(); index++) { int i_r, i_theta; level.grid().multiIndex(index, i_r, i_theta); if (i_r == 0 && !DirBC_Interior) - ASSERT_NEAR(solution_Give(index), solution_Take(index), 1e-8); + ASSERT_NEAR(h_solution_Give(index), h_solution_Take(index), 1e-8); else - ASSERT_NEAR(solution_Give(index), solution_Take(index), 1e-8); + ASSERT_NEAR(h_solution_Give(index), h_solution_Take(index), 1e-8); } } @@ -172,10 +178,9 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverDirBC_Interior_CircularGeome ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -214,10 +219,9 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeometr ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -262,10 +266,9 @@ TEST(DirectSolverTest_ShafranovGeometry, DirectSolverDirBC_Interior_ShafranovGeo ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -306,10 +309,9 @@ TEST(DirectSolverTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovGeome ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -354,10 +356,9 @@ TEST(DirectSolverTest_CzarnyGeometry, DirectSolverDirBC_Interior_CzarnyGeometry) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -398,10 +399,9 @@ TEST(DirectSolverTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometry) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -444,10 +444,9 @@ TEST(DirectSolverTest_CulhamGeometry, DirectSolverDirBC_Interior_CulhamGeometry) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -486,10 +485,9 @@ TEST(DirectSolverTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometry) ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -540,10 +538,9 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision_ ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -582,10 +579,9 @@ TEST(DirectSolverTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecision2 ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -625,10 +621,9 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverDirBC_Interior_CircularG ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -667,10 +662,9 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOrigin_CircularGeo ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -715,10 +709,9 @@ TEST(DirectSolverTakeTest_ShafranovGeometry, DirectSolverDirBC_Interior_Shafrano ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -759,10 +752,9 @@ TEST(DirectSolverTakeTest_ShafranovGeometry, DirectSolverAcrossOrigin_ShafranovG ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -807,10 +799,9 @@ TEST(DirectSolverTakeTest_CzarnyGeometry, DirectSolverDirBC_Interior_CzarnyGeome ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -851,10 +842,9 @@ TEST(DirectSolverTakeTest_CzarnyGeometry, DirectSolverAcrossOrigin_CzarnyGeometr ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -897,10 +887,9 @@ TEST(DirectSolverTakeTest_CulhamGeometry, DirectSolverDirBC_Interior_CulhamGeome ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -939,10 +928,9 @@ TEST(DirectSolverTakeTest_CulhamGeometry, DirectSolverAcrossOrigin_CulhamGeometr ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -991,10 +979,9 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecis ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); @@ -1033,10 +1020,9 @@ TEST(DirectSolverTakeTest_CircularGeometry, DirectSolverAcrossOriginHigherPrecis ResidualGive residual_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_solution("sol", rhs.size()); - Kokkos::deep_copy(h_solution, rhs); - solver_op.solveInPlace(h_solution); - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); + Vector solution("sol", rhs.size()); + Kokkos::deep_copy(solution, rhs); + solver_op.solveInPlace(solution); Vector residuum("residuum", level.grid().numberOfNodes()); residual_op.computeResidual(residuum, rhs, solution); diff --git a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp index 4e224ae7..3644d0db 100644 --- a/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp +++ b/tests/ExtrapolatedSmoother/extrapolated_smoother.cpp @@ -186,10 +186,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior() ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -278,10 +277,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin() ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); @@ -371,10 +369,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherDirBC_Interior_SmallestGrid() ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); @@ -464,10 +461,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherAcrossOrigin_SmallestGrid() ExtrapolatedSmootherGive extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -558,10 +554,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior() ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -650,10 +645,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin() ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -741,10 +735,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeDirBC_Interior_SmallestGri ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -832,10 +825,9 @@ void ExtrapolatedSmootherTest_ExtrapolatedSmootherTakeAcrossOrigin_SmallestGrid( ExtrapolatedSmootherTake extrapolated_smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); diff --git a/tests/Smoother/smoother.cpp b/tests/Smoother/smoother.cpp index 5e674caf..e66a6499 100644 --- a/tests/Smoother/smoother.cpp +++ b/tests/Smoother/smoother.cpp @@ -187,10 +187,9 @@ void SmootherTest_SmootherDirBC_Interior() SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -265,10 +264,9 @@ void SmootherTest_SmootherAcrossOrigin() SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -344,10 +342,9 @@ void SmootherTest_SmootherDirBC_Interior_SmallestGrid() SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -421,10 +418,9 @@ void SmootherTest_SmootherAcrossOrigin_SmallestGrid() SmootherGive smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -501,10 +497,9 @@ void SmootherTest_SmootherTakeDirBC_Interior() SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -579,10 +574,9 @@ void SmootherTest_SmootherTakeAcrossOrigin() SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -656,10 +650,9 @@ void SmootherTest_SmootherTakeDirBC_Interior_SmallestGrid() SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); @@ -733,10 +726,9 @@ void SmootherTest_SmootherTakeAcrossOrigin_SmallestGrid() SmootherTake smoother_op(level.grid(), level.levelCache(), DirBC_Interior); ConstVector rhs = generate_random_sample_data(level.grid(), 42); - HostVector h_discrete_solution("discrete_solution", rhs.size()); - Kokkos::deep_copy(h_discrete_solution, rhs); - solver_op.solveInPlace(h_discrete_solution); - auto discrete_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_discrete_solution); + Vector discrete_solution("discrete_solution", rhs.size()); + Kokkos::deep_copy(discrete_solution, rhs); + solver_op.solveInPlace(discrete_solution); Vector temp("temp", level.grid().numberOfNodes()); Vector error("error", level.grid().numberOfNodes()); From c03b2373eb42697b5885d294ce0cd0bf26a7a2ca Mon Sep 17 00:00:00 2001 From: BOURNE Emily EPFL Date: Wed, 10 Jun 2026 15:43:34 +0200 Subject: [PATCH 21/21] Port multigrid_W_Cycle to GPU. Tests not passing --- .../extrapolated_multigrid_W_Cycle.h | 14 ++++----- .../MultigridMethods/multigrid_W_Cycle.h | 31 ++++++++----------- include/GMGPolar/gmgpolar.h | 4 +-- include/GMGPolar/solver.h | 6 +++- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h index 2aa571b2..249e6d7d 100644 --- a/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/extrapolated_multigrid_W_Cycle.h @@ -59,8 +59,6 @@ void GMGPolar::extrapolated_multigri // res_ex = 4/3 * P_ex^T (f_l - A_l*u_l) - 1/3 * (f_{l-1} - A_{l-1}* Inject(u_l)) linear_combination(next_level_residual, 4.0 / 3.0, ConstVector(next_level.error_correction()), -1.0 / 3.0); - Kokkos::deep_copy(next_level.residual(), next_level_residual); - Kokkos::deep_copy(next_level.solution(), next_level_solution); auto end_MGC_residual = std::chrono::high_resolution_clock::now(); t_avg_MGC_residual_ += std::chrono::duration(end_MGC_residual - start_MGC_residual).count(); @@ -74,22 +72,22 @@ void GMGPolar::extrapolated_multigri assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); - multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), - next_level.solution()); + multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level_residual, + next_level_solution); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), - next_level.solution()); + multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level_residual, + next_level_solution); } + Kokkos::deep_copy(next_level.residual(), next_level_residual); + Kokkos::deep_copy(next_level.solution(), next_level_solution); /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); extrapolatedProlongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ diff --git a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h index 4d6affb0..db9dc5a4 100644 --- a/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h +++ b/include/GMGPolar/MultigridMethods/multigrid_W_Cycle.h @@ -2,11 +2,10 @@ template void GMGPolar::multigrid_W_Cycle(int level_depth, - HostVector h_solution, - HostConstVector h_rhs, - HostVector h_residual) + Vector solution, + ConstVector rhs, + Vector residual) { - auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_solution); assert(0 <= level_depth && level_depth < number_of_levels_); std::chrono::high_resolution_clock::time_point start_MGC; @@ -16,12 +15,12 @@ void GMGPolar::multigrid_W_Cycle(int if (level_depth == number_of_levels_ - 1) { /* ---------------------------------------------------- */ - /* Coarsest level: solve A * x = h_rhs using DirectSolver */ + /* Coarsest level: solve A * x = rhs using DirectSolver */ /* ---------------------------------------------------- */ Level& coarsest_level = levels_[level_depth]; - /* Step 1: Copy h_rhs in solution */ - Kokkos::deep_copy(solution, h_rhs); + /* Step 1: Copy rhs in solution */ + Kokkos::deep_copy(solution, rhs); /* Step 2: Solve for the solution in place */ auto start_MGC_directSolver = std::chrono::high_resolution_clock::now(); @@ -43,8 +42,6 @@ void GMGPolar::multigrid_W_Cycle(int /* ------------ */ auto start_MGC_preSmoothing = std::chrono::high_resolution_clock::now(); - auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_residual); - auto rhs = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), h_rhs); // const auto next_level_residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.residual()); for (int i = 0; i < pre_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); @@ -67,7 +64,6 @@ void GMGPolar::multigrid_W_Cycle(int /* Restrict the residual */ /* --------------------- */ restriction(level.level_depth(), next_level_residual, residual); - Kokkos::deep_copy(next_level.residual(), next_level_residual); /* ------------------------------------- */ /* Solve A * error = restricted residual */ @@ -77,22 +73,23 @@ void GMGPolar::multigrid_W_Cycle(int assign(next_level.error_correction(), 0.0); /* Solve for the error by recursively calling the multigrid cycle. */ - auto h_next_level_error_correction = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), next_level.error_correction()); - multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), - next_level.solution()); + auto next_level_solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace(), next_level.solution()); + multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level_residual, + next_level_solution); /* Don't do a second recursion on the coarsest level since the DirectSolver is exact. */ if (next_level.level_depth() != number_of_levels_ - 1) { - multigrid_W_Cycle(next_level.level_depth(), h_next_level_error_correction, next_level.residual(), - next_level.solution()); + multigrid_W_Cycle(next_level.level_depth(), next_level.error_correction(), next_level_residual, + next_level_solution); } + Kokkos::deep_copy(next_level.solution(), next_level_solution); + Kokkos::deep_copy(next_level.residual(), next_level_residual); /* -------------------------- */ /* Interpolate the correction */ /* -------------------------- */ // Use 'residual' instead of 'level.error_correction()' as a temporary buffer. // Note: 'level.error_correction()' has size 0 at level depth = 0. - Kokkos::deep_copy(next_level.error_correction(), h_next_level_error_correction); prolongation(next_level.level_depth(), residual, next_level.error_correction()); /* ----------------------------------- */ @@ -108,7 +105,6 @@ void GMGPolar::multigrid_W_Cycle(int for (int i = 0; i < post_smoothing_steps_; i++) { level.smoothing(solution, rhs, residual); } - Kokkos::deep_copy(h_residual, residual); auto end_MGC_postSmoothing = std::chrono::high_resolution_clock::now(); t_avg_MGC_postSmoothing_ += @@ -119,5 +115,4 @@ void GMGPolar::multigrid_W_Cycle(int auto end_MGC = std::chrono::high_resolution_clock::now(); t_avg_MGC_total_ += std::chrono::duration(end_MGC - start_MGC).count(); } - Kokkos::deep_copy(h_solution, solution); } diff --git a/include/GMGPolar/gmgpolar.h b/include/GMGPolar/gmgpolar.h index f247ee63..aa5af61a 100644 --- a/include/GMGPolar/gmgpolar.h +++ b/include/GMGPolar/gmgpolar.h @@ -194,8 +194,8 @@ class GMGPolar : public IGMGPolar /* Multigrid Functions */ void multigrid_V_Cycle(int level_depth, HostVector solution, HostConstVector rhs, HostVector residual); - void multigrid_W_Cycle(int level_depth, HostVector solution, HostConstVector rhs, - HostVector residual); + void multigrid_W_Cycle(int level_depth, Vector solution, ConstVector rhs, + Vector residual); void multigrid_F_Cycle(int level_depth, HostVector solution, HostConstVector rhs, HostVector residual); void extrapolated_multigrid_V_Cycle(int level_depth, HostVector solution, HostConstVector rhs, diff --git a/include/GMGPolar/solver.h b/include/GMGPolar/solver.h index bdefc3be..37cbe35f 100644 --- a/include/GMGPolar/solver.h +++ b/include/GMGPolar/solver.h @@ -439,13 +439,17 @@ void GMGPolar::applyMultigridIterati Level& level, MultigridCycleType cycle, int iterations) { auto h_rhs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, level.rhs()); + auto residual = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace{}, level.residual()); + auto solution = Kokkos::create_mirror_view_and_copy(DefaultMemorySpace{}, level.solution()); for (int i = 0; i < iterations; i++) { switch (cycle) { case MultigridCycleType::V_CYCLE: multigrid_V_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); break; case MultigridCycleType::W_CYCLE: - multigrid_W_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual()); + multigrid_W_Cycle(level.level_depth(), solution, level.rhs(), residual); + Kokkos::deep_copy(level.residual(), residual); + Kokkos::deep_copy(level.solution(), solution); break; case MultigridCycleType::F_CYCLE: multigrid_F_Cycle(level.level_depth(), level.solution(), h_rhs, level.residual());