13 #if !defined(KRATOS_SPARSE_MATRIX_MULTIPLICATION_UTILITY_H_INCLUDED )
14 #define KRATOS_SPARSE_MATRIX_MULTIPLICATION_UTILITY_H_INCLUDED
26 #include "amgcl/value_type/interface.hpp"
104 template <
class T,
class Enable =
void>
106 typedef typename T::value_type
type;
116 template <
class AMatrix,
class BMatrix,
class CMatrix>
124 const int nt = omp_get_max_threads();
143 template <
class AMatrix,
class BMatrix,
class CMatrix>
157 if ((nrows == 0) || (
ncols == 0))
161 const IndexType* index1_a =
A.index1_data().begin();
162 const IndexType* index2_a =
A.index2_data().begin();
163 const double* values_a =
A.value_data().begin();
164 const IndexType* index1_b =
B.index1_data().begin();
165 const IndexType* index2_b =
B.index2_data().begin();
166 const double* values_b =
B.value_data().begin();
174 for (
int i_fill = 0; i_fill < static_cast<int>(
ncols); ++i_fill)
178 for(
int ia = 0; ia < static_cast<int>(nrows); ++ia) {
179 const IndexType row_begin_a = index1_a[ia];
180 const IndexType row_end_a = index1_a[ia+1];
183 for(
IndexType ja = row_begin_a; ja < row_end_a; ++ja) {
185 const IndexType row_begin_b = index1_b[ca];
186 const IndexType row_end_b = index1_b[ca+1];
188 for(
IndexType jb = row_begin_b; jb < row_end_b; ++jb) {
196 c_ptr[ia + 1] = C_cols;
201 std::partial_sum(c_ptr, c_ptr + nrows + 1, c_ptr);
202 const SizeType nonzero_values = c_ptr[nrows];
204 ValueType* aux_val_c =
new ValueType[nonzero_values];
209 for (
int i_fill = 0; i_fill < static_cast<int>(
ncols); ++i_fill)
213 for(
int ia = 0; ia < static_cast<int>(nrows); ++ia) {
214 const IndexType row_begin_a = index1_a[ia];
215 const IndexType row_end_a = index1_a[ia+1];
220 for(
IndexType ja = row_begin_a; ja < row_end_a; ++ja) {
222 const ValueType va = values_a[ja];
224 const IndexType row_begin_b = index1_b[ca];
225 const IndexType row_end_b = index1_b[ca+1];
227 for(
IndexType jb = row_begin_b; jb < row_end_b; ++jb) {
229 const ValueType vb = values_b[jb];
233 aux_index2_c[row_end] = cb;
234 aux_val_c[row_end] = va * vb;
237 aux_val_c[
marker[cb]] += va * vb;
252 delete[] aux_index2_c;
263 template <
class AMatrix,
class BMatrix,
class CMatrix>
277 if ((nrows == 0) || (
ncols == 0))
281 const IndexType* index1_a =
A.index1_data().begin();
282 const IndexType* index2_a =
A.index2_data().begin();
283 const double* values_a =
A.value_data().begin();
284 const IndexType* index1_b =
B.index1_data().begin();
285 const IndexType* index2_b =
B.index2_data().begin();
286 const double* values_b =
B.value_data().begin();
295 for(
int i = 0; i < static_cast<int>(nrows); ++
i) {
302 row_width += index1_b[a_col + 1] - index1_b[a_col];
304 my_max =
std::max(my_max, row_width);
308 max_row_width =
std::max(max_row_width, my_max);
312 const int nthreads = omp_get_max_threads();
314 const int nthreads = 1;
317 std::vector< std::vector<IndexType> > tmp_col(nthreads);
318 std::vector< std::vector<ValueType> > tmp_val(nthreads);
320 for(
int i = 0;
i < nthreads; ++
i) {
321 tmp_col[
i].resize(3 * max_row_width);
322 tmp_val[
i].resize(2 * max_row_width);
332 const int tid = omp_get_thread_num();
340 for(
int i = 0; i < static_cast<int>(nrows); ++
i) {
344 c_ptr[
i+1] = ProdRowWidth( index2_a + row_beg, index2_a + row_end, index1_b, index2_b, t_col, t_col + max_row_width, t_col + 2 * max_row_width );
349 std::partial_sum(c_ptr, c_ptr + nrows + 1, c_ptr);
350 const SizeType nonzero_values = c_ptr[nrows];
352 ValueType* aux_val_c =
new ValueType[nonzero_values];
357 const int tid = omp_get_thread_num();
363 ValueType *t_val = tmp_val[tid].data();
366 for(
int i = 0; i < static_cast<int>(nrows); ++
i) {
370 ProdRow(index2_a + row_beg, index2_a + row_end, values_a + row_beg,
371 index1_b, index2_b, values_b, aux_index2_c + c_ptr[
i], aux_val_c + c_ptr[
i], t_col, t_val, t_col + max_row_width, t_val + max_row_width );
380 delete[] aux_index2_c;
389 template <
class AMatrix,
class BMatrix>
393 const double Factor = 1.0
404 if ((nrows == 0) || (
ncols == 0))
407 KRATOS_ERROR_IF_NOT(nrows ==
B.size1()) <<
"The second matrix has a wrong number of rows" << std::endl;
411 const IndexType* index1_a =
A.index1_data().begin();
412 const IndexType* index2_a =
A.index2_data().begin();
413 const double* values_a =
A.value_data().begin();
414 const IndexType* index1_b =
B.index1_data().begin();
415 const IndexType* index2_b =
B.index2_data().begin();
416 const double* values_b =
B.value_data().begin();
424 for(
int ia = 0; ia < static_cast<int>(nrows); ++ia) {
427 for (
int i = 0; i < static_cast<int>(
ncols); ++
i)
434 const IndexType row_begin_a = index1_a[ia];
435 const IndexType row_end_a = index1_a[ia+1];
436 for(
IndexType ja = row_begin_a; ja < row_end_a; ++ja) {
443 const IndexType row_begin_b = index1_b[ia];
444 const IndexType row_end_b = index1_b[ia+1];
445 for(
IndexType jb = row_begin_b; jb < row_end_b; ++jb) {
452 new_a_ptr[ia + 1] = new_A_cols;
457 std::partial_sum(new_a_ptr, new_a_ptr + nrows + 1, new_a_ptr);
458 const SizeType nonzero_values = new_a_ptr[nrows];
460 ValueType* aux_val_new_a =
new ValueType[nonzero_values];
465 for(
int ia = 0; ia < static_cast<int>(nrows); ++ia) {
468 for (
int i = 0; i < static_cast<int>(
ncols); ++
i)
476 const IndexType row_begin_a = index1_a[ia];
477 const IndexType row_end_a = index1_a[ia+1];
478 for(
IndexType ja = row_begin_a; ja < row_end_a; ++ja) {
480 const ValueType va = values_a[ja];
483 aux_index2_new_a[row_end] = ca;
484 aux_val_new_a[row_end] = va;
489 const IndexType row_begin_b = index1_b[ia];
490 const IndexType row_end_b = index1_b[ia+1];
491 for(
IndexType jb = row_begin_b; jb < row_end_b; ++jb) {
493 const ValueType vb = values_b[jb];
497 aux_index2_new_a[row_end] = cb;
498 aux_val_new_a[row_end] = Factor * vb;
501 aux_val_new_a[
marker[cb]] += Factor * vb;
508 SortRows(new_a_ptr, nrows,
ncols, aux_index2_new_a, aux_val_new_a);
515 delete[] aux_index2_new_a;
516 delete[] aux_val_new_a;
524 template <
class AMatrix,
class BMatrix>
528 const double Factor = 1.0
534 const IndexType* index1 = rB.index1_data().begin();
535 const IndexType* index2 = rB.index2_data().begin();
536 const ValueType*
data = rB.value_data().begin();
537 const SizeType transpose_nonzero_values = rB.value_data().end() - rB.value_data().begin();
539 const SizeType size_system_1 = rB.size1();
540 const SizeType size_system_2 = rB.size2();
542 if (rA.size1() != size_system_2 || rA.size2() != size_system_1 ) {
543 rA.resize(size_system_2, size_system_1,
false);
547 #pragma omp parallel for
548 for (
int i = 0; i < static_cast<int>(size_system_2 + 1); ++
i)
556 #pragma omp parallel for
557 for (
int i=0; i<static_cast<int>(size_system_1); ++
i) {
562 AtomicAdd(new_a_ptr[index2[
j] + 1], aux_1_index);
567 std::partial_sum(new_a_ptr.
begin(), new_a_ptr.
end(), &new_a_ptr[0]);
570 #pragma omp parallel for
571 for (
int i = 0; i < static_cast<int>(size_system_2); ++
i)
575 for (
int i=0; i<static_cast<int>(size_system_1); ++
i) {
581 const IndexType initial_position = new_a_ptr[current_row];
583 const IndexType current_index = initial_position + aux_indexes[current_row];
584 aux_index2_new_a[current_index] =
i;
585 aux_val_new_a[current_index] = Factor *
data[
j];
588 aux_indexes[current_row] += 1;
594 SortRows(&new_a_ptr[0], size_system_2, size_system_1, &aux_index2_new_a[0], &aux_val_new_a[0]);
597 CreateSolutionMatrix(rA, size_system_2, size_system_1, &new_a_ptr[0], &aux_index2_new_a[0], &aux_val_new_a[0]);
609 template <
class CMatrix,
typename TSize,
typename Ptr,
typename IndexType,
typename ValueType>
616 const ValueType* AuxValC
620 if ((NRows == 0) || (NCols == 0))
624 const TSize nonzero_values = CPtr[NRows];
626 C = CMatrix(NRows, NCols, nonzero_values);
627 IndexType* index1_c =
C.index1_data().begin();
628 IndexType* index2_c =
C.index2_data().begin();
629 double* values_c =
C.value_data().begin();
632 for (TSize
i = 0;
i < NRows;
i++)
633 index1_c[
i+1] = index1_c[
i] + (CPtr[
i+1] - CPtr[
i]);
635 #pragma omp parallel for
636 for (
int i = 0; i < static_cast<int>(nonzero_values);
i++) {
637 KRATOS_DEBUG_ERROR_IF(AuxIndex2C[
i] >
static_cast<IndexType>(NCols)) <<
"Index " << AuxIndex2C[
i] <<
" is greater than the number of columns " << NCols << std::endl;
638 index2_c[
i] = AuxIndex2C[
i];
639 values_c[
i] = AuxValC[
i];
642 C.set_filled(NRows+1, nonzero_values);
653 template <
typename TSize,
typename Col,
typename TIndexType,
typename ValueType>
655 const TIndexType* CPtr,
665 for (
int i_row=0; i_row<static_cast<int>(NRows); i_row++) {
666 const TIndexType row_beg = CPtr[i_row];
667 const TIndexType row_end = CPtr[i_row + 1];
671 const double v = Values[
j + row_beg];
675 while(
i >= 0 && Columns[
i + row_beg] >
c) {
676 KRATOS_DEBUG_ERROR_IF(Columns[
i + row_beg] >
static_cast<Col
>(NCols)) <<
" Index for column: " <<
i + row_beg <<
". Index " << Columns[
i + row_beg] <<
" is greater than the number of columns " << NCols << std::endl;
677 Columns[
i + 1 + row_beg] = Columns[
i + row_beg];
678 Values[
i + 1 + row_beg] = Values[
i + row_beg];
682 Columns[
i + 1 + row_beg] =
c;
683 Values[
i + 1 + row_beg] =
v;
702 const SizeType number_of_rows_blocks = rMatricespBlocks.size1();
703 const SizeType number_of_columns_blocks = rMatricespBlocks.size2();
706 if (ContributionCoefficients.size1() == 0 && ContributionCoefficients.size2() == 0) {
707 ContributionCoefficients.
resize(number_of_rows_blocks, number_of_columns_blocks);
709 for (
IndexType j = 0;
j < number_of_columns_blocks; ++
j) {
710 ContributionCoefficients(
i,
j) = 1.0;
714 KRATOS_ERROR_IF(ContributionCoefficients.size1() != number_of_rows_blocks || ContributionCoefficients.size2() != number_of_columns_blocks) <<
"The ContributionCoefficients dimensions" << ContributionCoefficients.size1() <<
" and " << ContributionCoefficients.size2() <<
"do not coincide with the dimensions of rMatricespBlocks" << number_of_rows_blocks <<
"and " << number_of_columns_blocks << std::endl;
716 if (TransposeBlocks.size1() == 0 && TransposeBlocks.size2() == 0) {
717 TransposeBlocks.resize(number_of_rows_blocks, number_of_columns_blocks);
720 TransposeBlocks(
i,
j) =
false;
724 KRATOS_ERROR_IF(TransposeBlocks.size1() != number_of_rows_blocks || TransposeBlocks.size2() != number_of_columns_blocks) <<
"The TransposeBlocks dimensions" << TransposeBlocks.size1() <<
" and " << TransposeBlocks.size2() <<
"do not coincide with the dimensions of rMatricespBlocks" << number_of_rows_blocks <<
"and " << number_of_columns_blocks << std::endl;
729 std::vector<SizeType> row_sizes(number_of_rows_blocks);
730 std::vector<SizeType> column_sizes(number_of_columns_blocks);
731 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
732 if (TransposeBlocks(
i, 0)) {
733 row_sizes[
i] = (*rMatricespBlocks(
i, 0)).size2();
735 row_sizes[
i] = (*rMatricespBlocks(
i, 0)).size1();
737 nrows += row_sizes[
i];
739 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
740 if (TransposeBlocks(0,
j)) {
741 column_sizes[
j] = (*rMatricespBlocks(0,
j)).size1();
743 column_sizes[
j] = (*rMatricespBlocks(0,
j)).size2();
749 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
750 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
751 if (TransposeBlocks(
i,
j)) {
752 KRATOS_ERROR_IF((*rMatricespBlocks(
i,
j)).size2() != row_sizes[
i] || (*rMatricespBlocks(
i,
j)).size1() != column_sizes[
j]) <<
" Not consistent size in block " <<
i <<
", " <<
j <<
".\t" << (*rMatricespBlocks(
i,
j)).size2() <<
", " << (*rMatricespBlocks(
i,
j)).size1() <<
" vs " << row_sizes[
i] <<
", " << row_sizes[
j] << std::endl;
754 KRATOS_ERROR_IF((*rMatricespBlocks(
i,
j)).size1() != row_sizes[
i] || (*rMatricespBlocks(
i,
j)).size2() != column_sizes[
j]) <<
" Not consistent size in block " <<
i <<
", " <<
j <<
".\t" << (*rMatricespBlocks(
i,
j)).size1() <<
", " << (*rMatricespBlocks(
i,
j)).size2() <<
" vs " << row_sizes[
i] <<
", " << row_sizes[
j] << std::endl;
759 if ((nrows == 0) || (
ncols == 0))
764 #pragma omp parallel for
765 for (
int i = 0; i < static_cast<int>(nrows + 1); ++
i)
771 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
772 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
773 check_non_zero_blocks(
i,
j) = 0;
781 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
782 for (
int k=0; k<static_cast<int>(row_sizes[
i]); ++
k) {
784 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
790 if (r_matrix.nnz() > 0) {
791 if (TransposeBlocks(
i,
j)) {
793 const SizeType size_system_1 = r_matrix.size1();
794 const SizeType size_system_2 = r_matrix.size2();
796 TransposeMatrix<CompressedMatrix, CompressedMatrix>(transpose, r_matrix);
809 check_non_zero_blocks(
i,
j) += partial_matrix_cols_aux;
812 IndexType& r_matrix_ptr_value = matrix_ptr[std::accumulate(row_sizes.begin(), row_sizes.begin() +
i, 0) +
k + 1];
813 AtomicAdd(r_matrix_ptr_value, matrix_cols_aux);
816 AtomicAdd(check_non_zero, matrix_cols_aux);
823 std::partial_sum(matrix_ptr, matrix_ptr + nrows + 1, matrix_ptr);
824 const SizeType nonzero_values = matrix_ptr[nrows];
828 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
829 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
830 const SizeType block_nnz = rMatricespBlocks(
i,
j)->nnz();
831 KRATOS_ERROR_IF_NOT(check_non_zero_blocks(
i,
j) == block_nnz) <<
"Inconsistent number of non-zero values. Check 0: " << block_nnz <<
" vs " << check_non_zero_blocks(
i,
j) <<
". Block: " <<
i <<
", " <<
j << std::endl;
832 total_nnz += block_nnz;
835 KRATOS_ERROR_IF_NOT(check_non_zero == total_nnz) <<
"Inconsistent number of non-zero values. Check 1: " << total_nnz <<
" vs " << check_non_zero << std::endl;
836 KRATOS_ERROR_IF_NOT(nonzero_values == total_nnz) <<
"Inconsistent number of non-zero values. Check 2: " << total_nnz <<
" vs " << nonzero_values << std::endl;
843 double* Matrix_values = rMatrix.value_data().begin();
844 IndexType* Matrix_index1 = rMatrix.index1_data().begin();
845 IndexType* Matrix_index2 = rMatrix.index2_data().begin();
847 Matrix_index1[0] = 0;
849 Matrix_index1[
i+1] = Matrix_index1[
i] + (matrix_ptr[
i + 1] - matrix_ptr[
i]);
854 for (
int i=0; i<static_cast<int>(number_of_rows_blocks); ++
i) {
855 for (
int k=0; k<static_cast<int>(row_sizes[
i]); ++
k) {
856 const IndexType row_beg = matrix_ptr[std::accumulate(row_sizes.begin(), row_sizes.begin() +
i, 0) +
k];
858 for (
int j=0; j<static_cast<int>(number_of_columns_blocks); ++
j) {
859 const SizeType initial_index_column = std::accumulate(column_sizes.begin(), column_sizes.begin() +
j, 0);
863 if (r_matrix.nnz() > 0) {
864 if (TransposeBlocks(
i,
j)) {
866 const SizeType size_system_1 = r_matrix.size1();
867 const SizeType size_system_2 = r_matrix.size2();
869 TransposeMatrix<CompressedMatrix, CompressedMatrix>(transpose, r_matrix);
881 rMatrix.set_filled(nrows+1, nonzero_values);
895 const int CurrentRow,
900 const IndexType* aux_matrix_index1 = rMatrix.index1_data().begin();
902 const IndexType row_begin = aux_matrix_index1[CurrentRow];
903 const IndexType row_end = aux_matrix_index1[CurrentRow + 1];
923 const int CurrentRow,
926 const double ContributionCoefficient = 1.0
930 const double* aux_values = rMatrix.value_data().begin();
931 const IndexType* aux_Matrix_index1 = rMatrix.index1_data().begin();
932 const IndexType* aux_Matrix_index2 = rMatrix.index2_data().begin();
934 const IndexType aux_Matrix_row_begin = aux_Matrix_index1[CurrentRow];
935 const IndexType aux_Matrix_row_end = aux_Matrix_index1[CurrentRow + 1];
937 for (
IndexType j=aux_Matrix_row_begin;
j<aux_Matrix_row_end;
j++) {
938 const IndexType col_index = InitialIndexColumn + aux_Matrix_index2[
j];
939 AuxIndex2[RowEnd] = col_index;
940 AuxVals[RowEnd] = ContributionCoefficient * aux_values[
j];
960 return "SparseMatrixMultiplicationUtility";
966 rOStream <<
"SparseMatrixMultiplicationUtility";
1033 template <
bool TNeedOut,
class TIndex>
1034 static TIndex* MergeRows(
1035 const TIndex* Column1,
1036 const TIndex* Column1End,
1037 const TIndex* Column2,
1038 const TIndex* Column2End,
1042 while(Column1 != Column1End && Column2 != Column2End) {
1043 TIndex c1 = *Column1;
1044 TIndex c2 = *Column2;
1047 if constexpr (TNeedOut) *Column3 = c1;
1049 }
else if (c1 == c2) {
1050 if constexpr (TNeedOut) *Column3 = c1;
1054 if constexpr (TNeedOut) *Column3 = c2;
1060 if constexpr (TNeedOut) {
1061 if (Column1 < Column1End) {
1062 return std::copy(Column1, Column1End, Column3);
1063 }
else if (Column2 < Column2End) {
1064 return std::copy(Column2, Column2End, Column3);
1069 return Column3 + (Column1End - Column1) + (Column2End - Column2);
1087 template <
class TIndex,
class TValueType>
1088 static TIndex* MergeRows(
1089 const TValueType &rAlpha1,
1090 const TIndex* Column1,
1091 const TIndex* Column1End,
1092 const TValueType *Value1,
1093 const TValueType &rAlpha2,
1094 const TIndex* Column2,
1095 const TIndex* Column2End,
1096 const TValueType *Value2,
1101 while(Column1 != Column1End && Column2 != Column2End) {
1102 TIndex c1 = *Column1;
1103 TIndex c2 = *Column2;
1109 *Value3 = rAlpha1 * (*Value1++);
1110 }
else if (c1 == c2) {
1115 *Value3 = rAlpha1 * (*Value1++) + rAlpha2 * (*Value2++);
1120 *Value3 = rAlpha2 * (*Value2++);
1127 while(Column1 < Column1End) {
1128 *Column3++ = *Column1++;
1129 *Value3++ = rAlpha1 * (*Value1++);
1132 while(Column2 < Column2End) {
1133 *Column3++ = *Column2++;
1134 *Value3++ = rAlpha2 * (*Value2++);
1152 template <
class TIndex>
1153 static TIndex ProdRowWidth(
1154 const TIndex* AColumn,
1155 const TIndex* AColumnEnd,
1157 const TIndex* BColumn,
1163 const TIndex nrow = AColumnEnd - AColumn;
1166 if (nrow == 0)
return 0;
1169 if (nrow == 1)
return BPtr[*AColumn + 1] - BPtr[*AColumn];
1173 int a1 = AColumn[0];
1174 int a2 = AColumn[1];
1176 return MergeRows<false>( BColumn + BPtr[a1], BColumn + BPtr[a1+1], BColumn + BPtr[a2], BColumn + BPtr[a2+1], Tmp1Column) - Tmp1Column;
1186 TIndex a1 = *AColumn++;
1187 TIndex a2 = *AColumn++;
1188 TIndex c_col1 = MergeRows<true>( BColumn + BPtr[a1], BColumn + BPtr[a1+1], BColumn + BPtr[a2], BColumn + BPtr[a2+1], Tmp1Column ) - Tmp1Column;
1191 while(AColumn + 1 < AColumnEnd) {
1195 TIndex c_col2 = MergeRows<true>( BColumn + BPtr[a1], BColumn + BPtr[a1+1], BColumn + BPtr[a2], BColumn + BPtr[a2+1], Tmp2Column ) - Tmp2Column;
1197 if (AColumn == AColumnEnd) {
1198 return MergeRows<false>( Tmp1Column, Tmp1Column + c_col1, Tmp2Column, Tmp2Column + c_col2, Tmp3Column ) - Tmp3Column;
1200 c_col1 = MergeRows<true>( Tmp1Column, Tmp1Column + c_col1, Tmp2Column, Tmp2Column + c_col2, Tmp3Column ) - Tmp3Column;
1202 std::swap(Tmp1Column, Tmp3Column);
1208 return MergeRows<false>( Tmp1Column, Tmp1Column + c_col1, BColumn + BPtr[a2], BColumn + BPtr[a2+1], Tmp2Column ) - Tmp2Column;
1227 template <
class TIndex,
class TValueType>
1228 static void ProdRow(
1229 const TIndex* AColumn,
1230 const TIndex* AColumnEnd,
1231 const TValueType *AValue,
1233 const TIndex* BColumn,
1234 const TValueType *BValue,
1236 TValueType *OutValue,
1238 TValueType *Tmp2Value,
1240 TValueType *Tmp3Value
1243 const TIndex nrow = AColumnEnd - AColumn;
1246 if (nrow == 0)
return;
1250 TIndex ac = *AColumn;
1251 TValueType av = *AValue;
1253 const TValueType *bv = BValue + BPtr[ac];
1254 const TIndex* bc = BColumn + BPtr[ac];
1255 const TIndex* be = BColumn + BPtr[ac+1];
1258 *OutColumn++ = *bc++;
1259 *OutValue++ = av * (*bv++);
1267 TIndex ac1 = AColumn[0];
1268 TIndex ac2 = AColumn[1];
1270 TValueType av1 = AValue[0];
1271 TValueType av2 = AValue[1];
1273 MergeRows( av1, BColumn + BPtr[ac1], BColumn + BPtr[ac1+1], BValue + BPtr[ac1], av2, BColumn + BPtr[ac2], BColumn + BPtr[ac2+1], BValue + BPtr[ac2], OutColumn, OutValue );
1283 TIndex ac1 = *AColumn++;
1284 TIndex ac2 = *AColumn++;
1286 TValueType av1 = *AValue++;
1287 TValueType av2 = *AValue++;
1289 TIndex* tm1_col = OutColumn;
1290 TValueType *tm1_val = OutValue;
1292 TIndex c_col1 = MergeRows( av1, BColumn + BPtr[ac1], BColumn + BPtr[ac1+1], BValue + BPtr[ac1], av2, BColumn + BPtr[ac2], BColumn + BPtr[ac2+1], BValue + BPtr[ac2], tm1_col, tm1_val ) - tm1_col;
1295 while(AColumn + 1 < AColumnEnd) {
1302 TIndex c_col2 = MergeRows( av1, BColumn + BPtr[ac1], BColumn + BPtr[ac1+1], BValue + BPtr[ac1], av2, BColumn + BPtr[ac2], BColumn + BPtr[ac2+1], BValue + BPtr[ac2], Tmp2Column, Tmp2Value ) - Tmp2Column;
1304 c_col1 = MergeRows( amgcl::math::identity<TValueType>(), tm1_col, tm1_col + c_col1, tm1_val, amgcl::math::identity<TValueType>(), Tmp2Column, Tmp2Column + c_col2, Tmp2Value, Tmp3Column, Tmp3Value ) - Tmp3Column;
1306 std::swap(Tmp3Column, tm1_col);
1307 std::swap(Tmp3Value, tm1_val);
1311 if (AColumn < AColumnEnd) {
1315 c_col1 = MergeRows( amgcl::math::identity<TValueType>(), tm1_col, tm1_col + c_col1, tm1_val, av2, BColumn + BPtr[ac2], BColumn + BPtr[ac2+1], BValue + BPtr[ac2], Tmp3Column, Tmp3Value ) - Tmp3Column;
1317 std::swap(Tmp3Column, tm1_col);
1318 std::swap(Tmp3Value, tm1_val);
1323 if (tm1_col != OutColumn) {
1324 std::copy(tm1_col, tm1_col + c_col1, OutColumn);
1325 std::copy(tm1_val, tm1_val + c_col1, OutValue);
Definition: amatrix_interface.h:41
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
iterator end()
Definition: amatrix_interface.h:243
iterator begin()
Definition: amatrix_interface.h:241
An utility to multiply sparse matrix in Ublas.
Definition: sparse_matrix_multiplication_utility.h:62
static void MatrixAdd(AMatrix &A, const BMatrix &B, const double Factor=1.0)
The first is a method in order to sum to sparse matrices in a efficient way.
Definition: sparse_matrix_multiplication_utility.h:390
virtual ~SparseMatrixMultiplicationUtility()=default
Desctructor.
static void ComputeAuxiliarValuesBlocks(const CompressedMatrix &rMatrix, IndexType *AuxIndex2, double *AuxVals, const int CurrentRow, IndexType &RowEnd, const SizeType InitialIndexColumn, const double ContributionCoefficient=1.0)
This is a method to compute the contribution of the auxiliar blocks.
Definition: sparse_matrix_multiplication_utility.h:919
static void TransposeMatrix(AMatrix &rA, const BMatrix &rB, const double Factor=1.0)
This method computes of the transpose matrix of a given matrix.
Definition: sparse_matrix_multiplication_utility.h:525
SparseMatrixMultiplicationUtility()
Default constructor.
Definition: sparse_matrix_multiplication_utility.h:90
static void AssembleSparseMatrixByBlocks(CompressedMatrix &rMatrix, const DenseMatrix< CompressedMatrix * > &rMatricespBlocks, DenseMatrix< double > ContributionCoefficients=DenseMatrix< double >(0, 0), DenseMatrix< bool > TransposeBlocks=DenseMatrix< bool >(0, 0))
This method assembles several sparse matrices into one large sparse matrix.
Definition: sparse_matrix_multiplication_utility.h:695
std::ptrdiff_t SignedIndexType
The signed index type.
Definition: sparse_matrix_multiplication_utility.h:77
std::size_t SizeType
The size type.
Definition: sparse_matrix_multiplication_utility.h:71
DenseVector< IndexType > IndexVectorType
A vector of indexes.
Definition: sparse_matrix_multiplication_utility.h:80
static void ComputeNonZeroBlocks(const CompressedMatrix &rMatrix, const int CurrentRow, IndexType &rNonZeroColsAux2)
This is a method to check the block containing nonzero values.
Definition: sparse_matrix_multiplication_utility.h:893
void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: sparse_matrix_multiplication_utility.h:964
static void MatrixMultiplicationSaad(const AMatrix &A, const BMatrix &B, CMatrix &C)
The first is an OpenMP-enabled modification of classic algorithm from Saad.
Definition: sparse_matrix_multiplication_utility.h:144
static void CreateSolutionMatrix(CMatrix &C, const TSize NRows, const TSize NCols, const Ptr *CPtr, const IndexType *AuxIndex2C, const ValueType *AuxValC)
This method is designed to create the final solution sparse matrix from the auxiliar values.
Definition: sparse_matrix_multiplication_utility.h:610
static void MatrixMultiplicationRMerge(const AMatrix &A, const BMatrix &B, CMatrix &C)
Row-merge algorithm from Rupp et al.
Definition: sparse_matrix_multiplication_utility.h:264
void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: sparse_matrix_multiplication_utility.h:970
DenseVector< SignedIndexType > SignedIndexVectorType
A vector of indexes (signed)
Definition: sparse_matrix_multiplication_utility.h:83
std::string Info() const
Turn back information as a string.
Definition: sparse_matrix_multiplication_utility.h:958
static void MatrixMultiplication(const AMatrix &rA, const BMatrix &rB, CMatrix &rC)
Matrix-matrix product C = A·B @detail This method uses a template for each matrix.
Definition: sparse_matrix_multiplication_utility.h:117
static void SortRows(const TIndexType *CPtr, const TSize NRows, const TSize NCols, Col *Columns, ValueType *Values)
This method is designed to reorder the rows by columns.
Definition: sparse_matrix_multiplication_utility.h:654
std::size_t IndexType
The index type.
Definition: sparse_matrix_multiplication_utility.h:74
KRATOS_CLASS_POINTER_DEFINITION(SparseMatrixMultiplicationUtility)
Pointer definition of TreeContactSearch.
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
ncols
Definition: GenerateCN.py:97
static double max(double a, double b)
Definition: GeometryFunctions.h:79
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
void AtomicAdd(TDataType &target, const TDataType &value)
Definition: atomic_utilities.h:55
boost::numeric::ublas::compressed_matrix< double > CompressedMatrix
Definition: ublas_interface.h:94
marker
Definition: exact_hinsberg_test.py:111
v
Definition: generate_convection_diffusion_explicit_element.py:114
int C
Definition: generate_hyper_elastic_simo_taylor_neo_hookean.py:27
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
data
Definition: mesh_to_mdpa_converter.py:59
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
A
Definition: sensitivityMatrix.py:70
B
Definition: sensitivityMatrix.py:76
integer i
Definition: TensorModule.f:17
Metafunction that returns value type of a matrix or a vector type.
Definition: sparse_matrix_multiplication_utility.h:105
T::value_type type
Definition: sparse_matrix_multiplication_utility.h:106