xref: /petsc/src/mat/impls/baij/seq/aijbaij.c (revision 6c2b77d522d8aa5c8b27f04fddd7150d0d6755fb)
1 
2 #include <../src/mat/impls/baij/seq/baij.h>
3 
4 PETSC_INTERN PetscErrorCode MatConvert_SeqBAIJ_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
5 {
6   Mat          B;
7   Mat_SeqAIJ  *b;
8   PetscBool    roworiented;
9   Mat_SeqBAIJ *a  = (Mat_SeqBAIJ *)A->data;
10   PetscInt     bs = A->rmap->bs, *ai = a->i, *aj = a->j, n = A->rmap->N / bs, i, j, k;
11   PetscInt    *rowlengths, *rows, *cols, maxlen            = 0, ncols;
12   MatScalar   *aa = a->a;
13 
14   PetscFunctionBegin;
15   if (reuse == MAT_REUSE_MATRIX) {
16     B = *newmat;
17     for (i = 0; i < n; i++) maxlen = PetscMax(maxlen, (ai[i + 1] - ai[i]));
18   } else {
19     PetscCall(PetscMalloc1(n * bs, &rowlengths));
20     for (i = 0; i < n; i++) {
21       maxlen = PetscMax(maxlen, (ai[i + 1] - ai[i]));
22       for (j = 0; j < bs; j++) rowlengths[i * bs + j] = bs * (ai[i + 1] - ai[i]);
23     }
24     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
25     PetscCall(MatSetType(B, MATSEQAIJ));
26     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
27     PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs));
28     PetscCall(MatSeqAIJSetPreallocation(B, 0, rowlengths));
29     PetscCall(PetscFree(rowlengths));
30   }
31   b           = (Mat_SeqAIJ *)B->data;
32   roworiented = b->roworiented;
33 
34   PetscCall(MatSetOption(B, MAT_ROW_ORIENTED, PETSC_FALSE));
35   PetscCall(PetscMalloc1(bs, &rows));
36   PetscCall(PetscMalloc1(bs * maxlen, &cols));
37   for (i = 0; i < n; i++) {
38     for (j = 0; j < bs; j++) rows[j] = i * bs + j;
39     ncols = ai[i + 1] - ai[i];
40     for (k = 0; k < ncols; k++) {
41       for (j = 0; j < bs; j++) cols[k * bs + j] = bs * (*aj) + j;
42       aj++;
43     }
44     PetscCall(MatSetValues(B, bs, rows, bs * ncols, cols, aa, INSERT_VALUES));
45     aa += ncols * bs * bs;
46   }
47   PetscCall(PetscFree(cols));
48   PetscCall(PetscFree(rows));
49   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
50   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
51   PetscCall(MatSetOption(B, MAT_ROW_ORIENTED, roworiented));
52 
53   if (reuse == MAT_INPLACE_MATRIX) {
54     PetscCall(MatHeaderReplace(A, &B));
55   } else *newmat = B;
56   PetscFunctionReturn(0);
57 }
58 
59 #include <../src/mat/impls/aij/seq/aij.h>
60 
61 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
62 {
63   Mat          B;
64   Mat_SeqAIJ  *a = (Mat_SeqAIJ *)A->data;
65   Mat_SeqBAIJ *b;
66   PetscInt    *ai = a->i, m = A->rmap->N, n = A->cmap->N, i, *rowlengths, bs = PetscAbs(A->rmap->bs);
67 
68   PetscFunctionBegin;
69   if (reuse != MAT_REUSE_MATRIX) {
70     PetscCall(PetscMalloc1(m / bs, &rowlengths));
71     for (i = 0; i < m / bs; i++) rowlengths[i] = (ai[i * bs + 1] - ai[i * bs]) / bs;
72     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
73     PetscCall(MatSetSizes(B, m, n, m, n));
74     PetscCall(MatSetType(B, MATSEQBAIJ));
75     PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, rowlengths));
76     PetscCall(PetscFree(rowlengths));
77   } else B = *newmat;
78 
79   if (bs == 1) {
80     b = (Mat_SeqBAIJ *)(B->data);
81 
82     PetscCall(PetscArraycpy(b->i, a->i, m + 1));
83     PetscCall(PetscArraycpy(b->ilen, a->ilen, m));
84     PetscCall(PetscArraycpy(b->j, a->j, a->nz));
85     PetscCall(PetscArraycpy(b->a, a->a, a->nz));
86 
87     PetscCall(MatSetOption(B, MAT_ROW_ORIENTED, PETSC_TRUE));
88     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
89     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
90   } else {
91     /* reuse may not be equal to MAT_REUSE_MATRIX, but the basic converter will reallocate or replace newmat if this value is not used */
92     /* if reuse is equal to MAT_INITIAL_MATRIX, it has been appropriately preallocated before                                          */
93     /*                      MAT_INPLACE_MATRIX, it will be replaced with MatHeaderReplace below                                        */
94     PetscCall(MatConvert_Basic(A, newtype, MAT_REUSE_MATRIX, &B));
95   }
96 
97   if (reuse == MAT_INPLACE_MATRIX) {
98     PetscCall(MatHeaderReplace(A, &B));
99   } else *newmat = B;
100   PetscFunctionReturn(0);
101 }
102