@@ -849,6 +849,146 @@ void Multigrid::generate()
849
849
}
850
850
851
851
852
+ void Multigrid::update_matrix_value (std::shared_ptr<const LinOp> new_matrix)
853
+ {
854
+ this ->set_system_matrix (new_matrix);
855
+ // generate coarse matrix until reaching max_level or min_coarse_rows
856
+ auto num_rows = this ->get_system_matrix ()->get_size ()[0 ];
857
+ size_type level = 0 ;
858
+ auto matrix = this ->get_system_matrix ();
859
+ auto exec = this ->get_executor ();
860
+ // clean all smoother
861
+ pre_smoother_list_.clear ();
862
+ mid_smoother_list_.clear ();
863
+ post_smoother_list_.clear ();
864
+ // Always generate smoother with size = level.
865
+ for (int i = 0 ; i < mg_level_list_.size (); i++) {
866
+ auto mg_level = mg_level_list_.at (i);
867
+ as<UpdateMatrixValue>(mg_level)->update_matrix_value (matrix);
868
+ matrix = mg_level->get_coarse_op ();
869
+ run<gko::multigrid::EnableMultigridLevel, float , double ,
870
+ std::complex<float >, std::complex<double >>(
871
+ mg_level,
872
+ [this ](auto mg_level, auto index , auto matrix) {
873
+ using value_type =
874
+ typename std::decay_t <decltype (*mg_level)>::value_type;
875
+ handle_list<value_type>(
876
+ index , matrix, parameters_.pre_smoother , pre_smoother_list_,
877
+ parameters_.smoother_iters , parameters_.smoother_relax );
878
+ if (parameters_.mid_case ==
879
+ multigrid::mid_smooth_type::standalone) {
880
+ handle_list<value_type>(
881
+ index , matrix, parameters_.mid_smoother ,
882
+ mid_smoother_list_, parameters_.smoother_iters ,
883
+ parameters_.smoother_relax );
884
+ }
885
+ if (!parameters_.post_uses_pre ) {
886
+ handle_list<value_type>(
887
+ index , matrix, parameters_.post_smoother ,
888
+ post_smoother_list_, parameters_.smoother_iters ,
889
+ parameters_.smoother_relax );
890
+ }
891
+ },
892
+ i, mg_level->get_fine_op ());
893
+ }
894
+ if (parameters_.post_uses_pre ) {
895
+ post_smoother_list_ = pre_smoother_list_;
896
+ }
897
+ auto last_mg_level = mg_level_list_.back ();
898
+
899
+ // generate coarsest solver
900
+ run<gko::multigrid::EnableMultigridLevel, float , double ,
901
+ std::complex<float >, std::complex<double >>(
902
+ last_mg_level,
903
+ [this ](auto mg_level, auto level, auto matrix) {
904
+ using value_type =
905
+ typename std::decay_t <decltype (*mg_level)>::value_type;
906
+ auto exec = this ->get_executor ();
907
+ // default coarse grid solver, direct LU
908
+ // TODO: maybe remove fixed index type
909
+ auto gen_default_solver = [&]() -> std::unique_ptr<LinOp> {
910
+ // TODO: unify when dpcpp supports direct solver
911
+ #if GINKGO_BUILD_MPI
912
+ if (gko::detail::is_distributed (matrix.get ())) {
913
+ using absolute_value_type = remove_complex<value_type>;
914
+ using experimental::distributed::Matrix;
915
+ return run<Matrix<value_type, int32, int32>,
916
+ Matrix<value_type, int32, int64>,
917
+ Matrix<value_type, int64,
918
+ int64>>(matrix, [exec](auto matrix) {
919
+ using Mtx = typename decltype (matrix)::element_type;
920
+ return solver::Gmres<value_type>::build ()
921
+ .with_criteria (
922
+ stop::Iteration::build ().with_max_iters (
923
+ matrix->get_size ()[0 ]),
924
+ stop::ResidualNorm<value_type>::build ()
925
+ .with_reduction_factor (
926
+ std::numeric_limits<
927
+ absolute_value_type>::epsilon () *
928
+ absolute_value_type{10 }))
929
+ .with_krylov_dim (
930
+ std::min (size_type (100 ), matrix->get_size ()[0 ]))
931
+ .with_preconditioner (
932
+ experimental::distributed::preconditioner::
933
+ Schwarz<value_type,
934
+ typename Mtx::local_index_type,
935
+ typename Mtx::global_index_type>::
936
+ build ()
937
+ .with_local_solver (
938
+ preconditioner::Jacobi<
939
+ value_type>::build ()
940
+ .with_max_block_size (1u )))
941
+ .on (exec)
942
+ ->generate (matrix);
943
+ });
944
+ }
945
+ #endif
946
+ if (dynamic_cast <const DpcppExecutor*>(exec.get ())) {
947
+ using absolute_value_type = remove_complex<value_type>;
948
+ return solver::Gmres<value_type>::build ()
949
+ .with_criteria (
950
+ stop::Iteration::build ().with_max_iters (
951
+ matrix->get_size ()[0 ]),
952
+ stop::ResidualNorm<value_type>::build ()
953
+ .with_reduction_factor (
954
+ std::numeric_limits<
955
+ absolute_value_type>::epsilon () *
956
+ absolute_value_type{10 }))
957
+ .with_krylov_dim (
958
+ std::min (size_type (100 ), matrix->get_size ()[0 ]))
959
+ .with_preconditioner (
960
+ preconditioner::Jacobi<value_type>::build ()
961
+ .with_max_block_size (1u ))
962
+ .on (exec)
963
+ ->generate (matrix);
964
+ } else {
965
+ return experimental::solver::Direct<value_type,
966
+ int32>::build ()
967
+ .with_factorization (
968
+ experimental::factorization::Lu<value_type,
969
+ int32>::build ())
970
+ .on (exec)
971
+ ->generate (matrix);
972
+ }
973
+ };
974
+ if (parameters_.coarsest_solver .size () == 0 ) {
975
+ coarsest_solver_ = gen_default_solver ();
976
+ } else {
977
+ auto temp_index = solver_selector_ (level, matrix.get ());
978
+ GKO_ENSURE_IN_BOUNDS (temp_index,
979
+ parameters_.coarsest_solver .size ());
980
+ auto solver = parameters_.coarsest_solver .at (temp_index);
981
+ if (solver == nullptr ) {
982
+ coarsest_solver_ = gen_default_solver ();
983
+ } else {
984
+ coarsest_solver_ = solver->generate (matrix);
985
+ }
986
+ }
987
+ },
988
+ mg_level_list_.size (), matrix);
989
+ }
990
+
991
+
852
992
void Multigrid::apply_impl (const LinOp* b, LinOp* x) const
853
993
{
854
994
this ->apply_with_initial_guess_impl (b, x,
0 commit comments