From 677dfacdcddacb36bee86441eaee4031a62efff9 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Thu, 7 Aug 2025 15:31:25 +0200 Subject: [PATCH 01/12] WIP gamg coarsening --- include/OGL/Preconditioner.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index 2bd3d5f1..a5d11c2b 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -372,6 +372,7 @@ class Preconditioner { auto maxLevels = d.lookupOrDefault("maxLevels", label(20)); auto minRowsC = d.lookupOrDefault("minCoarseRows", label(64000)); auto smoother = d.lookupOrDefault("smoother", word("Jacobi")); + auto coarsening = d.lookupOrDefault("coarsening", word("GAMG")); auto coarseSolver = d.lookupOrDefault("coarseSolver", word("Jacobi")); auto maxIterS = d.lookupOrDefault("maxIterSmoother", label(1)); @@ -387,13 +388,13 @@ class Preconditioner { "\n\tSmoother: " + smoother + "\n\trelaxationFactor: " + std::to_string(relaxFac) + "\n\tmaxIterSmoother: " + std::to_string(maxIterS) + + "\n\tcoarsening: " + coarsening + "\n\tcoarseSolver: " + coarseSolver + "\n\tmaxIterCoarse: " + std::to_string(maxIterCoarseS) + "\n\tinnerSolverNorm: " + std::to_string(solveNorm) + "\n\tcycle: " + cycleName + " type: " + type; MLOG_0(verbose_, msg) - std::shared_ptr bjfac{}; if (smoother == "Jacobi") { @@ -420,6 +421,11 @@ class Preconditioner { << abort(FatalError); } + std::shared_ptr coarseningWeight; + if (coarsening=="GAMG"){ + coarseningWeight=gkomatrix; + } + auto single_it = it::build().with_max_iters(1u); auto coarse_solve_it = gko::stop::Iteration::build().with_max_iters( static_cast(maxIterCoarseS)); From ba7f67a746d769dc8cf7ef6e614c298b02ad5c2d Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Fri, 15 Aug 2025 16:57:16 +0200 Subject: [PATCH 02/12] wip gamg weights --- CMakeLists.txt | 2 +- include/OGL/Preconditioner.hpp | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b81b769..86f8d3b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ to turn off this check") endif() set(GINKGO_CHECKOUT_VERSION - "ogl_0600_gko190" + "ogl_0600_gko110" CACHE STRING "Use specific version of ginkgo") if(OGL_DEVEL_TOOLS) diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index a5d11c2b..6640b167 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -421,9 +421,28 @@ class Preconditioner { << abort(FatalError); } - std::shared_ptr coarseningWeight; + std::shared_ptr> coarseningWeight; if (coarsening=="GAMG"){ - coarseningWeight=gkomatrix; + + auto& fvmesh = db_.template lookupObjectRef("fvSchemes"); + // weights[facei] -> column + auto weights = mag + ( + cmptMultiply + ( + fvmesh.Sf().primitiveField() + /sqrt(fvmesh.magSf().primitiveField()), + vector(1, 1.01, 1.02) + ) + ); + + // here ldu adressing is needed + // 1. create row, cols, vals vector + // 2. fill with diagonals i=j=row=col + // 3. fill with off-diagonals values from weights and row, cols from ldu + + + coarseningWeight=nullptr; } auto single_it = it::build().with_max_iters(1u); @@ -481,7 +500,10 @@ class Preconditioner { .with_pre_smoother(smoother_gen) .with_post_uses_pre(true) .with_mg_level( - pgm::build().with_deterministic(false).on( + pgm::build() + .with_deterministic(false) + .with_local_weight_mtx(coarseningWeight) + .on( device_exec)) .with_coarsest_solver(coarsest_solver) .with_criteria(single_it) @@ -525,6 +547,7 @@ class Preconditioner { gko::solver::Multigrid::build() .with_max_levels(maxLevels) .with_mg_level(gko::multigrid::Pgm::build() + .with_local_weight_mtx(coarseningWeight) .with_deterministic(true)) .with_min_coarse_rows(minRowsC) .with_coarsest_solver(coarsest_solver) From 42b16faca64683f751c7f48225bd9123169a6a3b Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Fri, 15 Aug 2025 16:58:26 +0200 Subject: [PATCH 03/12] format --- include/OGL/Preconditioner.hpp | 56 ++++++++++++++++------------------ 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index 6640b167..91022068 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -421,29 +421,25 @@ class Preconditioner { << abort(FatalError); } - std::shared_ptr> coarseningWeight; - if (coarsening=="GAMG"){ - - auto& fvmesh = db_.template lookupObjectRef("fvSchemes"); - // weights[facei] -> column - auto weights = mag - ( - cmptMultiply - ( - fvmesh.Sf().primitiveField() - /sqrt(fvmesh.magSf().primitiveField()), - vector(1, 1.01, 1.02) - ) - ); - - // here ldu adressing is needed - // 1. create row, cols, vals vector - // 2. fill with diagonals i=j=row=col - // 3. fill with off-diagonals values from weights and row, cols from ldu - - - coarseningWeight=nullptr; - } + std::shared_ptr> coarseningWeight; + if (coarsening == "GAMG") { + auto &fvmesh = + db_.template lookupObjectRef("fvSchemes"); + // weights[facei] -> column + auto weights = + mag(cmptMultiply(fvmesh.Sf().primitiveField() / + sqrt(fvmesh.magSf().primitiveField()), + vector(1, 1.01, 1.02))); + + // here ldu adressing is needed + // 1. create row, cols, vals vector + // 2. fill with diagonals i=j=row=col + // 3. fill with off-diagonals values from weights and row, cols + // from ldu + + + coarseningWeight = nullptr; + } auto single_it = it::build().with_max_iters(1u); auto coarse_solve_it = gko::stop::Iteration::build().with_max_iters( @@ -501,10 +497,9 @@ class Preconditioner { .with_post_uses_pre(true) .with_mg_level( pgm::build() - .with_deterministic(false) - .with_local_weight_mtx(coarseningWeight) - .on( - device_exec)) + .with_deterministic(false) + .with_local_weight_mtx(coarseningWeight) + .on(device_exec)) .with_coarsest_solver(coarsest_solver) .with_criteria(single_it) .on(device_exec); @@ -546,9 +541,10 @@ class Preconditioner { auto ret = gko::share( gko::solver::Multigrid::build() .with_max_levels(maxLevels) - .with_mg_level(gko::multigrid::Pgm::build() - .with_local_weight_mtx(coarseningWeight) - .with_deterministic(true)) + .with_mg_level( + gko::multigrid::Pgm::build() + .with_local_weight_mtx(coarseningWeight) + .with_deterministic(true)) .with_min_coarse_rows(minRowsC) .with_coarsest_solver(coarsest_solver) .with_criteria(it::build().with_max_iters(2u)) From 868b5f6258c545ff5fe717e64b9f9755e7cfefac Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Mon, 25 Aug 2025 11:34:35 +0200 Subject: [PATCH 04/12] wip pass exec handler --- include/OGL/Preconditioner.hpp | 35 ++++++++++++++++++++++++++++++---- include/OGL/lduLduBase.hpp | 6 +++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index 91022068..ce86f354 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -160,8 +160,9 @@ class Preconditioner { std::shared_ptr init_preconditioner_impl( const word name, const dictionary &d, std::shared_ptr gkomatrix, - std::shared_ptr device_exec) const + const ExecutorHandler &exec_handler) const { + auto device_exec = exec_handler.get_device_exec(); bool skip_sorting = d.lookupOrDefault("skipSorting", true); bool multi_level_schwarz = d.lookupOrDefault("multiLevelSchwarz", false); @@ -431,6 +432,23 @@ class Preconditioner { sqrt(fvmesh.magSf().primitiveField()), vector(1, 1.01, 1.02))); + // const std::shared_ptr + // weight_matrix_wrapper + // {std::make_shared( + // exec_handler, db_, matrix.diag().size(), + // matrix.upper().size(), matrix.symmetric(), + // matrix.diag().begin(), matrix.upper().begin(), + // matrix.lower().begin(), matrix.lduAddr(), interfaceBouCoeffs, + // interfaceIntCoeffs, interfaces, solverControls, fieldName, + // verbose_) + // }; + + + // std::shared_ptr dist_weight_mtx = + // create_distributed(&exec_handler, repartitioner, + // weigh_matrix_wrapper, "Csr" true, + // verbose_); + // here ldu adressing is needed // 1. create row, cols, vals vector // 2. fill with diagonals i=j=row=col @@ -571,10 +589,19 @@ class Preconditioner { return {}; } + class PreconditionerWrapper { + + virtual std::shared_ptr create() { + + } + + }; + std::shared_ptr init_preconditioner( std::shared_ptr gkomatrix, - std::shared_ptr device_exec) const + const ExecutorHandler &exec_handler) const { + auto device_exec = exec_handler.get_device_exec(); const word precond_store_name = sys_matrix_name_ + "Cached_preconditinoner"; const fileName path = precond_store_name; @@ -655,7 +682,7 @@ class Preconditioner { set_next_caching(sys_matrix_name_, db_, caching_period); auto generated_precond = - init_preconditioner_impl(name, d, gkomatrix, device_exec); + init_preconditioner_impl(name, d, gkomatrix, exec_handler); auto precond_ptr = prev_precond.get_ptr(); precond_ptr = generated_precond; @@ -667,7 +694,7 @@ class Preconditioner { cache = get_next_caching(sys_matrix_name_, db_); auto generated_precond = - init_preconditioner_impl(name, d, gkomatrix, device_exec); + init_preconditioner_impl(name, d, gkomatrix, exec_handler); auto po = new DevicePersistentBase(IOobject(path, db_), generated_precond); diff --git a/include/OGL/lduLduBase.hpp b/include/OGL/lduLduBase.hpp index e584adbe..a5c750be 100644 --- a/include/OGL/lduLduBase.hpp +++ b/include/OGL/lduLduBase.hpp @@ -268,9 +268,9 @@ class lduLduBase : public OGL_Info, dist_b.get_vector()->scale(dense_scaling.get());) } - TIME_WITH_FIELDNAME(verbose_, init_precond, this->fieldName(), - auto precond = this->init_preconditioner( - dist_A_v, exec_handler_.get_device_exec());) + TIME_WITH_FIELDNAME( + verbose_, init_precond, this->fieldName(), + auto precond = this->init_preconditioner(dist_A_v, exec_handler_);) bool active = repartitioner->get_repart_size() != 0; bool export_system( From f5ee3a14e83a2c03ba8435398d47c93283bc59f8 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Tue, 26 Aug 2025 08:46:00 +0200 Subject: [PATCH 05/12] wip move preconditioner to separate implementation files --- include/OGL/Preconditioner.hpp | 41 +++------------- include/OGL/Preconditioner/Jacobi.hpp | 47 +++++++++++++++++++ .../Preconditioner/PreconditionerWrapper.hpp | 15 ++++++ include/OGL/Preconditioner/Schwarz.hpp | 38 +++++++++++++++ 4 files changed, 106 insertions(+), 35 deletions(-) create mode 100644 include/OGL/Preconditioner/Jacobi.hpp create mode 100644 include/OGL/Preconditioner/PreconditionerWrapper.hpp create mode 100644 include/OGL/Preconditioner/Schwarz.hpp diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index ce86f354..cb4d60b9 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -8,11 +8,15 @@ #include "OGL/DevicePersistent/Base.hpp" #include "OGL/MatrixWrapper/Distributed.hpp" +#include "OGL/Preconditioner/Jacobi.hpp" +#include "OGL/Preconditioner/Schwarz.hpp" #include "fvCFD.H" #include "regIOobject.H" namespace Foam { + + class Preconditioner { using mtx = gko::matrix::Csr; using bj = gko::preconditioner::Jacobi; @@ -128,34 +132,6 @@ class Preconditioner { } } - template - std::shared_ptr wrap_schwarz( - std::shared_ptr gkomatrix, - std::shared_ptr device_exec, - std::unique_ptr precond) const - { - auto local = gko::as(gkomatrix)->get_local(); - return gko::share( - ras::build() - .with_generated_local_solver(precond->generate(local)) - .on(device_exec) - ->generate( - gko::as(gkomatrix)->get_dist_mtx())); - } - - template - std::shared_ptr wrap_schwarz( - std::shared_ptr gkomatrix, - std::shared_ptr device_exec, - std::unique_ptr precond, - std::shared_ptr factorization) const - { - return gko::share( - ras::build() - .with_generated_local_solver(precond->generate(factorization)) - .on(device_exec) - ->generate(gkomatrix)); - } std::shared_ptr init_preconditioner_impl( const word name, const dictionary &d, @@ -589,13 +565,6 @@ class Preconditioner { return {}; } - class PreconditionerWrapper { - - virtual std::shared_ptr create() { - - } - - }; std::shared_ptr init_preconditioner( std::shared_ptr gkomatrix, @@ -705,4 +674,6 @@ class Preconditioner { return generated_precond; } }; + + } // namespace Foam diff --git a/include/OGL/Preconditioner/Jacobi.hpp b/include/OGL/Preconditioner/Jacobi.hpp new file mode 100644 index 00000000..4e1dbd97 --- /dev/null +++ b/include/OGL/Preconditioner/Jacobi.hpp @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2025 OGL authors +// +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "PreconditionerWrapper.hpp" +#include "OGL/Preconditioner/Schwarz.hpp" + +class BJ : public PreconditionerWrapper { + using dbj = gko::preconditioner::Jacobi; + using fbj = gko::preconditioner::Jacobi; + + const label verbose_; + bool skip_sorting_; + label max_block_size_; + word precision_; + + +public: + BJ(const dictionary &d, label verbose) + : verbose_(verbose), + skip_sorting_(d.lookupOrDefault("skipSorting", true)), + max_block_size_(d.lookupOrDefault("maxBlockSize", label(1))), + precision_(d.lookupOrDefault("precision", word("double"))) + { + word msg = "Generate (Block)-Jacobi preconditioner:" + + "\n\tprecision: " precision + + "\n\tmaxBlockSize " + std::to_string(max_block_size); + MLOG_0(verbose_, msg) + } + + virtual std::shared_ptr create_local() + { + // auto pre_factory = + // dbj::build() + // .with_skip_sorting(skip_sorting) + // .with_max_block_size( + // static_cast(max_block_size)) + // .on(device_exec); + // auto gkodistmatrix = + // gko::as(gkomatrix)->get_dist_matrix(); + // return wrap_schwarz(gkomatrix, device_exec, + // std::move(pre_factory)); + } + + +}; diff --git a/include/OGL/Preconditioner/PreconditionerWrapper.hpp b/include/OGL/Preconditioner/PreconditionerWrapper.hpp new file mode 100644 index 00000000..0e92f5ef --- /dev/null +++ b/include/OGL/Preconditioner/PreconditionerWrapper.hpp @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 OGL authors +// +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include + +class PreconditionerWrapper { + + /* @brief instantiate a local preconditioner and return LinOp Ptr */ + virtual std::shared_ptr create_local(); + + /* @brief instantiate a local preconditioner and return LinOp Ptr */ + virtual std::shared_ptr create_multilevel(); +}; diff --git a/include/OGL/Preconditioner/Schwarz.hpp b/include/OGL/Preconditioner/Schwarz.hpp new file mode 100644 index 00000000..fc552c91 --- /dev/null +++ b/include/OGL/Preconditioner/Schwarz.hpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 OGL authors +// +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include + +namespace Foam { + template + std::shared_ptr wrap_schwarz( + std::shared_ptr gkomatrix, + std::shared_ptr device_exec, + std::unique_ptr precond) const + { + auto local = gko::as(gkomatrix)->get_local(); + return gko::share( + ras::build() + .with_generated_local_solver(precond->generate(local)) + .on(device_exec) + ->generate( + gko::as(gkomatrix)->get_dist_mtx())); + } + + template + std::shared_ptr wrap_schwarz( + std::shared_ptr gkomatrix, + std::shared_ptr device_exec, + std::unique_ptr precond, + std::shared_ptr factorization) const + { + return gko::share( + ras::build() + .with_generated_local_solver(precond->generate(factorization)) + .on(device_exec) + ->generate(gkomatrix)); + } + + } From b8c01acf02d7604f1b8c05aa2a6e92c551a0a0e2 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Tue, 26 Aug 2025 10:07:28 +0200 Subject: [PATCH 06/12] wip move preconditioner to separate implementation files --- include/OGL/Preconditioner.hpp | 122 +--------------- include/OGL/Preconditioner/Jacobi.hpp | 66 ++++++--- .../Preconditioner/PreconditionerWrapper.hpp | 21 ++- include/OGL/Preconditioner/Schwarz.hpp | 138 ++++++++++++++---- 4 files changed, 177 insertions(+), 170 deletions(-) diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index cb4d60b9..a5ef6b58 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -56,82 +56,6 @@ class Preconditioner { verbose_(verbose) {} - template - std::shared_ptr wrap_multi_level_schwarz( - std::shared_ptr gkomatrix, - std::shared_ptr device_exec, - std::shared_ptr precond, const dictionary &d, - label local_rows) const - { - using pgm = gko::multigrid::Pgm; - using fc = gko::multigrid::FixedCoarsening; - using solver = gko::solver::Cg; - - auto selCoarseRows = d.lookupOrDefault("selCoarseRows", label(5)); - auto fixedCoarsening = - d.lookupOrDefault("fixedCoarsening", false); - auto coarseWeight = d.lookupOrDefault("coarseWeight", scalar(0.01)); - auto solveNormC = - d.lookupOrDefault("reductionCoarseSolver", label(1e-6)); - auto maxIterCoarse = d.lookupOrDefault("maxIterCoarse", label(50)); - - word msg = "Generate multi level schwarz:\n\tfixedCoarsening " + - std::to_string(fixedCoarsening) + "\n\tselCoarseRows " + - std::to_string(selCoarseRows) + "\n\trelTolCoarse " + - std::to_string(solveNormC) + "\n\tmaxIterCoarse " + - std::to_string(maxIterCoarse) + "\n\tcoarseWeigth" + - std::to_string(coarseWeight); - MLOG_0(verbose_, msg) - - auto pre_factory = ras::build().with_local_solver( - bj::build().with_skip_sorting(true).with_max_block_size(1u).on( - device_exec)); - - auto coarse_solver = gko::share( - solver::build() - .with_preconditioner(pre_factory) - .with_criteria( - gko::stop::Iteration::build().with_max_iters(maxIterCoarse), - gko::stop::ResidualNorm::build() - .with_reduction_factor(solveNormC)) - .on(device_exec)); - - if (fixedCoarsening) { - auto n_rows = local_rows / selCoarseRows; - auto sel_rows = - gko::array