103 bool converged =
false;
107 const auto n_rows = matrix.m();
108 const auto n_cols = matrix.n();
122 control.sinkhorn_knopp_parameters.max_iterations);
127 case MatrixScaling::AdditionalData::ScalingAlgorithm::
128 l1_linf_symmetry_preserving:
130 if (
control.l1linf_parameters.start_inf_norm_steps > 0 &&
133 matrix,
control.l1linf_parameters.start_inf_norm_steps);
134 if (
control.l1linf_parameters.l1_norm_steps > 0 && !converged)
137 control.l1linf_parameters.l1_norm_steps);
138 if (
control.l1linf_parameters.end_inf_norm_steps > 0 &&
141 matrix,
control.l1linf_parameters.end_inf_norm_steps);
151#ifdef DEAL_II_WITH_TRILINOS
152 std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix> ||
154#ifdef DEAL_II_WITH_PETSC
155 std::is_same_v<Matrix, PETScWrappers::MPI::SparseMatrix> ||
166 if (matrix.n() == matrix.m())
171 matrix.get_mpi_communicator(), matrix.n());
185 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
193 matrix.get_mpi_communicator());
198 matrix.get_mpi_communicator());
206 control.sinkhorn_knopp_parameters.max_iterations);
211 case MatrixScaling::AdditionalData::ScalingAlgorithm::
212 l1_linf_symmetry_preserving:
214 if (
control.l1linf_parameters.start_inf_norm_steps > 0 &&
217 matrix,
control.l1linf_parameters.start_inf_norm_steps);
218 if (
control.l1linf_parameters.l1_norm_steps > 0 && !converged)
221 control.l1linf_parameters.l1_norm_steps);
222 if (
control.l1linf_parameters.end_inf_norm_steps > 0 &&
225 matrix,
control.l1linf_parameters.end_inf_norm_steps);
597 using Number =
typename Matrix::value_type;
602 for (
unsigned int i = 0; i < nsteps; i++)
607 for (
unsigned int row = 0; row < matrix.m(); ++row)
609 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
611 row_norms[row] +=
std::abs(it->value());
612 col_norms[it->column()] +=
std::abs(it->value());
621 for (
unsigned int row = 0; row < matrix.m(); ++row)
623 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
628 col_norms[it->column()]));
632 for (
unsigned int col = 0; col < matrix.n(); ++col)
639#ifdef DEAL_II_WITH_TRILINOS
640 std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix> ||
642#ifdef DEAL_II_WITH_PETSC
643 std::is_same_v<Matrix, PETScWrappers::MPI::SparseMatrix> ||
649 std::map<types::global_dof_index, double>
650 partial_column_norms;
652 for (
unsigned int i = 0; i < nsteps; i++)
656 partial_column_norms.clear();
660 auto local_row_idx =
partitioner.global_to_local(row);
661 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
663 local_row_norms[local_row_idx] +=
std::abs(it->value());
664 partial_column_norms[it->column()] +=
std::abs(it->value());
668 std::map<
unsigned int,
669 std::vector<std::pair<types::global_dof_index, double>>>
681 for (
const auto &[sender_rank, pairs] : received_data)
683 for (
const auto &[global_col, contribution] : pairs)
685 unsigned int local_idx =
687 local_col_norms[local_idx] += contribution;
694 matrix.get_mpi_communicator()))
698 for (
unsigned int i = 0; i < local_row_norms.
size(); ++i)
700 for (
unsigned int i = 0; i < local_col_norms.
size(); ++i)
704 std::map<
unsigned int,
705 std::vector<std::pair<types::global_dof_index, double>>>
712 auto received_column_norms =
716 std::map<types::global_dof_index, double> ghost_column_norms_lookup;
717 for (
const auto &[sender_rank, pairs] : received_column_norms)
719 for (
const auto &[col_id, norm_val] : pairs)
721 ghost_column_norms_lookup[col_id] = norm_val;
728 auto local_row_idx =
partitioner.global_to_local(row);
729 auto row_size = matrix.row_length(row);
730 std::vector<double> values(row_size);
731 std::vector<types::global_dof_index> columns(row_size);
732 unsigned int idx = 0;
733 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
737 unsigned int local_col_idx =
739 columns[idx] = it->column();
741 it->value() /
std::sqrt(local_col_norms[local_col_idx] *
742 local_row_norms[local_row_idx]);
748 ghost_column_norms_lookup[it->column()];
749 columns[idx] = it->column();
752 std::sqrt(col_norms * local_row_norms[local_row_idx]);
756 matrix.set(row, columns, values);
757 if constexpr (std::is_same_v<Matrix,
761#ifdef DEAL_II_WITH_TRILINOS
762 if constexpr (std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix>)
778 using Number =
typename Matrix::value_type;
783 for (
unsigned int i = 0; i < nsteps; i++)
788 for (
unsigned int row = 0; row < matrix.m(); ++row)
790 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
794 col_norms[it->column()] =
805 for (
unsigned int row = 0; row < matrix.m(); ++row)
807 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
812 col_norms[it->column()]));
816 for (
unsigned int col = 0; col < matrix.n(); ++col)
823#ifdef DEAL_II_WITH_TRILINOS
824 std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix> ||
826#ifdef DEAL_II_WITH_PETSC
827 std::is_same_v<Matrix, PETScWrappers::MPI::SparseMatrix> ||
833 std::map<types::global_dof_index, double>
834 partial_column_norms;
836 for (
unsigned int i = 0; i < nsteps; i++)
840 partial_column_norms.clear();
844 auto local_row_idx =
partitioner.global_to_local(row);
845 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
847 local_row_norms[local_row_idx] =
848 std::max(local_row_norms[local_row_idx],
850 partial_column_norms[it->column()] =
851 std::max(partial_column_norms[it->column()],
856 std::map<
unsigned int,
857 std::vector<std::pair<types::global_dof_index, double>>>
869 for (
const auto &[sender_rank, pairs] : received_data)
871 for (
const auto &[global_col, contribution] : pairs)
873 unsigned int local_idx =
875 local_col_norms[local_idx] =
876 std::max(local_col_norms[local_idx], contribution);
883 matrix.get_mpi_communicator()))
886 for (
unsigned int i = 0; i < local_row_norms.
size(); ++i)
888 for (
unsigned int i = 0; i < local_col_norms.
size(); ++i)
892 std::map<
unsigned int,
893 std::vector<std::pair<types::global_dof_index, double>>>
900 auto received_column_norms =
904 std::map<types::global_dof_index, double> ghost_column_norms_lookup;
905 for (
const auto &[sender_rank, pairs] : received_column_norms)
907 for (
const auto &[col_id, norm_val] : pairs)
909 ghost_column_norms_lookup[col_id] = norm_val;
916 auto local_row_idx =
partitioner.global_to_local(row);
917 auto row_size = matrix.row_length(row);
918 std::vector<double> values(row_size);
919 std::vector<types::global_dof_index> columns(row_size);
920 unsigned int idx = 0;
921 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
925 unsigned int local_col_idx =
927 columns[idx] = it->column();
929 it->value() /
std::sqrt(local_col_norms[local_col_idx] *
930 local_row_norms[local_row_idx]);
936 ghost_column_norms_lookup[it->column()];
937 columns[idx] = it->column();
940 std::sqrt(col_norms * local_row_norms[local_row_idx]);
944 matrix.set(row, columns, values);
945 if constexpr (std::is_same_v<Matrix,
949#ifdef DEAL_II_WITH_TRILINOS
950 if constexpr (std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix>)
966 using Number =
typename Matrix::value_type;
971 switch (
control.sinkhorn_knopp_parameters.norm_type)
977 for (
unsigned int row = 0; row < matrix.m(); ++row)
978 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
979 row_norms[row] +=
std::abs(it->value());
981 for (
unsigned int i = 0; i < nsteps; i++)
985 for (
unsigned int row = 0; row < matrix.m(); ++row)
987 for (
auto it = matrix.begin(row); it != matrix.end(row);
992 it->value() / row_norms[row]);
993 col_norms[it->column()] +=
std::abs(it->value());
1004 for (
unsigned int row = 0; row < matrix.m(); ++row)
1006 for (
auto it = matrix.begin(row); it != matrix.end(row);
1011 it->value() / col_norms[it->column()]);
1012 row_norms[row] +=
std::abs(it->value());
1015 for (
unsigned int col = 0; col < matrix.n(); ++col)
1031 for (
unsigned int row = 0; row < matrix.m(); ++row)
1032 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
1036 for (
unsigned int i = 0; i < nsteps; i++)
1040 for (
unsigned int row = 0; row < matrix.m(); ++row)
1042 for (
auto it = matrix.begin(row); it != matrix.end(row);
1047 it->value() / row_norms[row]);
1048 col_norms[it->column()] =
1061 for (
unsigned int row = 0; row < matrix.m(); ++row)
1063 for (
auto it = matrix.begin(row); it != matrix.end(row);
1068 it->value() / col_norms[it->column()]);
1073 for (
unsigned int col = 0; col < matrix.n(); ++col)
1090#ifdef DEAL_II_WITH_TRILINOS
1091 std::is_same_v<Matrix, TrilinosWrappers::SparseMatrix> ||
1093#ifdef DEAL_II_WITH_PETSC
1094 std::is_same_v<Matrix, PETScWrappers::MPI::SparseMatrix> ||
1100 std::map<types::global_dof_index, double>
1101 partial_column_norms;
1103 switch (
control.sinkhorn_knopp_parameters.norm_type)
1108 local_row_norms = 0;
1111 auto local_row_idx =
partitioner.global_to_local(row);
1112 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
1113 local_row_norms[local_row_idx] +=
std::abs(it->value());
1116 for (
unsigned int i = 0; i < nsteps; i++)
1119 local_col_norms = 0;
1120 partial_column_norms.clear();
1124 auto local_row_idx =
partitioner.global_to_local(row);
1125 auto row_size = matrix.row_length(row);
1126 std::vector<double> values(row_size);
1127 std::vector<types::global_dof_index> columns(row_size);
1128 unsigned int idx = 0;
1129 for (
auto it = matrix.begin(row); it != matrix.end(row);
1132 partial_column_norms[it->column()] +=
std::abs(
1133 it->value() / local_row_norms[local_row_idx]);
1134 columns[idx] = it->column();
1136 it->value() / local_row_norms[local_row_idx];
1139 matrix.set(row, columns, values);
1140 if constexpr (std::is_same_v<
1146 local_row_norms[local_row_idx];
1148#ifdef DEAL_II_WITH_TRILINOS
1149 if constexpr (std::is_same_v<Matrix,
1157 std::vector<std::pair<types::global_dof_index, double>>>
1164 auto received_data =
1169 for (
const auto &[sender_rank, pairs] : received_data)
1171 for (
const auto &[global_col, contribution] : pairs)
1173 unsigned int local_idx =
1175 local_col_norms[local_idx] += contribution;
1182 matrix.get_mpi_communicator()))
1186 local_row_norms = 0;
1191 std::vector<std::pair<types::global_dof_index, double>>>
1198 auto received_column_norms =
1202 std::map<types::global_dof_index, double>
1203 ghost_column_norms_lookup;
1204 for (
const auto &[sender_rank, pairs] : received_column_norms)
1206 for (
const auto &[col_id, norm_val] : pairs)
1208 ghost_column_norms_lookup[col_id] = norm_val;
1214 auto local_row_idx =
partitioner.global_to_local(row);
1215 auto row_size = matrix.row_length(row);
1216 std::vector<double> values(row_size);
1217 std::vector<types::global_dof_index> columns(row_size);
1218 unsigned int idx = 0;
1219 for (
auto it = matrix.begin(row); it != matrix.end(row);
1224 unsigned int local_col_idx =
1227 local_row_norms[local_row_idx] +=
std::abs(
1228 it->value() / local_col_norms[local_col_idx]);
1230 columns[idx] = it->column();
1232 it->value() / local_col_norms[local_col_idx];
1238 ghost_column_norms_lookup[it->column()];
1240 local_row_norms[local_row_idx] +=
1243 columns[idx] = it->column();
1244 values[idx] = it->value() / col_norms;
1248 matrix.set(row, columns, values);
1249 if constexpr (std::is_same_v<
1254#ifdef DEAL_II_WITH_TRILINOS
1255 if constexpr (std::is_same_v<Matrix,
1259 for (
unsigned int i = 0; i < local_col_norms.
size(); ++i)
1264 matrix.get_mpi_communicator()))
1273 local_row_norms = 0;
1276 auto local_row_idx =
partitioner.global_to_local(row);
1277 for (
auto it = matrix.begin(row); it != matrix.end(row); ++it)
1278 local_row_norms[local_row_idx] =
1279 std::max(local_row_norms[local_row_idx],
1283 for (
unsigned int i = 0; i < nsteps; i++)
1286 local_col_norms = 0;
1287 partial_column_norms.clear();
1291 auto local_row_idx =
partitioner.global_to_local(row);
1292 auto row_size = matrix.row_length(row);
1293 std::vector<double> values(row_size);
1294 std::vector<types::global_dof_index> columns(row_size);
1295 unsigned int idx = 0;
1296 for (
auto it = matrix.begin(row); it != matrix.end(row);
1299 partial_column_norms[it->column()] =
1300 std::max(partial_column_norms[it->column()],
1302 local_row_norms[local_row_idx]));
1303 columns[idx] = it->column();
1305 it->value() / local_row_norms[local_row_idx];
1308 matrix.set(row, columns, values);
1309 if constexpr (std::is_same_v<
1315 local_row_norms[local_row_idx];
1317#ifdef DEAL_II_WITH_TRILINOS
1318 if constexpr (std::is_same_v<Matrix,
1326 std::vector<std::pair<types::global_dof_index, double>>>
1333 auto received_data =
1338 for (
const auto &[sender_rank, pairs] : received_data)
1340 for (
const auto &[global_col, contribution] : pairs)
1342 unsigned int local_idx =
1344 local_col_norms[local_idx] =
1345 std::max(local_col_norms[local_idx], contribution);
1352 matrix.get_mpi_communicator()))
1356 local_row_norms = 0;
1361 std::vector<std::pair<types::global_dof_index, double>>>
1368 auto received_column_norms =
1372 std::map<types::global_dof_index, double>
1373 ghost_column_norms_lookup;
1374 for (
const auto &[sender_rank, pairs] : received_column_norms)
1376 for (
const auto &[col_id, norm_val] : pairs)
1378 ghost_column_norms_lookup[col_id] = norm_val;
1384 auto local_row_idx =
partitioner.global_to_local(row);
1385 auto row_size = matrix.row_length(row);
1386 std::vector<double> values(row_size);
1387 std::vector<types::global_dof_index> columns(row_size);
1388 unsigned int idx = 0;
1389 for (
auto it = matrix.begin(row); it != matrix.end(row);
1394 unsigned int local_col_idx =
1397 local_row_norms[local_row_idx] =
1398 std::max(local_row_norms[local_row_idx],
1401 local_col_norms[local_col_idx]));
1403 columns[idx] = it->column();
1405 it->value() / local_col_norms[local_col_idx];
1411 ghost_column_norms_lookup[it->column()];
1413 local_row_norms[local_row_idx] =
1414 std::max(local_row_norms[local_row_idx],
1415 std::abs(it->value() / col_norms));
1417 columns[idx] = it->column();
1418 values[idx] = it->value() / col_norms;
1422 matrix.set(row, columns, values);
1423 if constexpr (std::is_same_v<
1428#ifdef DEAL_II_WITH_TRILINOS
1429 if constexpr (std::is_same_v<Matrix,
1433 for (
unsigned int i = 0; i < local_col_norms.
size(); ++i)
1439 matrix.get_mpi_communicator()))