xref: /petsc/src/mat/impls/sbaij/seq/aijsbaij.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
159557b74SHong Zhang 
2c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>
3c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h>
4c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h>
559557b74SHong Zhang 
6d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
7d71ae5a4SJacob Faibussowitsch {
84e5e7fe4SHong Zhang   Mat           B;
94e5e7fe4SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
104e5e7fe4SHong Zhang   Mat_SeqAIJ   *b;
11d0f46423SBarry Smith   PetscInt     *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->n, i, j, k, *bi, *bj, *rowlengths, nz, *rowstart, itmp;
1201be0148SBarry Smith   PetscInt      bs = A->rmap->bs, bs2 = bs * bs, mbs = A->rmap->N / bs, diagcnt = 0;
13dd6ea824SBarry Smith   MatScalar    *av, *bv;
14eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
15b94d7dedSBarry Smith   const int aconj = A->hermitian == PETSC_BOOL3_TRUE ? 1 : 0;
16eb1ec7c1SStefano Zampini #else
17eb1ec7c1SStefano Zampini   const int aconj = 0;
18eb1ec7c1SStefano Zampini #endif
194e5e7fe4SHong Zhang 
204e5e7fe4SHong Zhang   PetscFunctionBegin;
214e5e7fe4SHong Zhang   /* compute rowlengths of newmat */
229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(m, &rowlengths, m + 1, &rowstart));
23a7a3a9ebSHong Zhang 
24a7a3a9ebSHong Zhang   for (i = 0; i < mbs; i++) rowlengths[i * bs] = 0;
25a7a3a9ebSHong Zhang   k = 0;
26a7a3a9ebSHong Zhang   for (i = 0; i < mbs; i++) {
274e5e7fe4SHong Zhang     nz = ai[i + 1] - ai[i];
2801be0148SBarry Smith     if (nz) {
2901be0148SBarry Smith       rowlengths[k] += nz; /* no. of upper triangular blocks */
309371c9d4SSatish Balay       if (*aj == i) {
319371c9d4SSatish Balay         aj++;
329371c9d4SSatish Balay         diagcnt++;
339371c9d4SSatish Balay         nz--;
349371c9d4SSatish Balay       }                          /* skip diagonal */
3501be0148SBarry Smith       for (j = 0; j < nz; j++) { /* no. of lower triangular blocks */
369371c9d4SSatish Balay         rowlengths[(*aj) * bs]++;
379371c9d4SSatish Balay         aj++;
38a7a3a9ebSHong Zhang       }
3901be0148SBarry Smith     }
40a7a3a9ebSHong Zhang     rowlengths[k] *= bs;
41ad540459SPierre Jolivet     for (j = 1; j < bs; j++) rowlengths[k + j] = rowlengths[k];
42a7a3a9ebSHong Zhang     k += bs;
434e5e7fe4SHong Zhang   }
444e5e7fe4SHong Zhang 
45bd019fc1SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
469566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
479566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
489566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
499566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, 0, rowlengths));
509566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(B, A->rmap->bs));
51bd019fc1SStefano Zampini   } else B = *newmat;
524e5e7fe4SHong Zhang 
534e5e7fe4SHong Zhang   b  = (Mat_SeqAIJ *)(B->data);
544e5e7fe4SHong Zhang   bi = b->i;
554e5e7fe4SHong Zhang   bj = b->j;
564e5e7fe4SHong Zhang   bv = b->a;
574e5e7fe4SHong Zhang 
584e5e7fe4SHong Zhang   /* set b->i */
599371c9d4SSatish Balay   bi[0]       = 0;
609371c9d4SSatish Balay   rowstart[0] = 0;
61a7a3a9ebSHong Zhang   for (i = 0; i < mbs; i++) {
62a7a3a9ebSHong Zhang     for (j = 0; j < bs; j++) {
63a7a3a9ebSHong Zhang       b->ilen[i * bs + j]      = rowlengths[i * bs];
64a7a3a9ebSHong Zhang       rowstart[i * bs + j + 1] = rowstart[i * bs + j] + rowlengths[i * bs];
654e5e7fe4SHong Zhang     }
66a7a3a9ebSHong Zhang     bi[i + 1] = bi[i] + rowlengths[i * bs] / bs;
67a7a3a9ebSHong Zhang   }
68aed4548fSBarry Smith   PetscCheck(bi[mbs] == 2 * a->nz - diagcnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "bi[mbs]: %" PetscInt_FMT " != 2*a->nz-diagcnt: %" PetscInt_FMT, bi[mbs], 2 * a->nz - diagcnt);
694e5e7fe4SHong Zhang 
704e5e7fe4SHong Zhang   /* set b->j and b->a */
719371c9d4SSatish Balay   aj = a->j;
729371c9d4SSatish Balay   av = a->a;
73a7a3a9ebSHong Zhang   for (i = 0; i < mbs; i++) {
7401be0148SBarry Smith     nz = ai[i + 1] - ai[i];
75a7a3a9ebSHong Zhang     /* diagonal block */
7601be0148SBarry Smith     if (nz && *aj == i) {
7701be0148SBarry Smith       nz--;
78a7a3a9ebSHong Zhang       for (j = 0; j < bs; j++) { /* row i*bs+j */
79a7a3a9ebSHong Zhang         itmp = i * bs + j;
80a7a3a9ebSHong Zhang         for (k = 0; k < bs; k++) { /* col i*bs+k */
81a7a3a9ebSHong Zhang           *(bj + rowstart[itmp]) = (*aj) * bs + k;
82a7a3a9ebSHong Zhang           *(bv + rowstart[itmp]) = *(av + k * bs + j);
83a7a3a9ebSHong Zhang           rowstart[itmp]++;
84a7a3a9ebSHong Zhang         }
85a7a3a9ebSHong Zhang       }
869371c9d4SSatish Balay       aj++;
879371c9d4SSatish Balay       av += bs2;
8801be0148SBarry Smith     }
89a7a3a9ebSHong Zhang 
904e5e7fe4SHong Zhang     while (nz--) {
91a7a3a9ebSHong Zhang       /* lower triangular blocks */
92a7a3a9ebSHong Zhang       for (j = 0; j < bs; j++) { /* row (*aj)*bs+j */
93a7a3a9ebSHong Zhang         itmp = (*aj) * bs + j;
94a7a3a9ebSHong Zhang         for (k = 0; k < bs; k++) { /* col i*bs+k */
95a7a3a9ebSHong Zhang           *(bj + rowstart[itmp]) = i * bs + k;
96eb1ec7c1SStefano Zampini           *(bv + rowstart[itmp]) = aconj ? PetscConj(*(av + j * bs + k)) : *(av + j * bs + k);
97a7a3a9ebSHong Zhang           rowstart[itmp]++;
98a7a3a9ebSHong Zhang         }
99a7a3a9ebSHong Zhang       }
100a7a3a9ebSHong Zhang       /* upper triangular blocks */
101a7a3a9ebSHong Zhang       for (j = 0; j < bs; j++) { /* row i*bs+j */
102a7a3a9ebSHong Zhang         itmp = i * bs + j;
103a7a3a9ebSHong Zhang         for (k = 0; k < bs; k++) { /* col (*aj)*bs+k */
104a7a3a9ebSHong Zhang           *(bj + rowstart[itmp]) = (*aj) * bs + k;
105a7a3a9ebSHong Zhang           *(bv + rowstart[itmp]) = *(av + k * bs + j);
106a7a3a9ebSHong Zhang           rowstart[itmp]++;
107a7a3a9ebSHong Zhang         }
108a7a3a9ebSHong Zhang       }
1099371c9d4SSatish Balay       aj++;
1109371c9d4SSatish Balay       av += bs2;
1114e5e7fe4SHong Zhang     }
1124e5e7fe4SHong Zhang   }
1139566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rowlengths, rowstart));
1149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1159566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1164e5e7fe4SHong Zhang 
117511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1189566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
119c3d102feSKris Buschelman   } else {
1204e5e7fe4SHong Zhang     *newmat = B;
121c3d102feSKris Buschelman   }
122*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1234e5e7fe4SHong Zhang }
124be1d678aSKris Buschelman 
1255a2b941aSBarry Smith #include <../src/mat/impls/aij/seq/aij.h>
1265a2b941aSBarry Smith 
1275a2b941aSBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqSBAIJ_Preallocate(Mat A, PetscInt **nnz)
1285a2b941aSBarry Smith {
1295a2b941aSBarry Smith   PetscInt    m, n, bs = PetscAbs(A->rmap->bs);
1305a2b941aSBarry Smith   PetscInt   *ii;
1315a2b941aSBarry Smith   Mat_SeqAIJ *Aa = (Mat_SeqAIJ *)A->data;
1325a2b941aSBarry Smith 
1335a2b941aSBarry Smith   PetscFunctionBegin;
1345a2b941aSBarry Smith   PetscCall(MatGetSize(A, &m, &n));
1355a2b941aSBarry Smith   PetscCall(PetscCalloc1(m / bs, nnz));
1365a2b941aSBarry Smith   PetscCall(PetscMalloc1(bs, &ii));
1375a2b941aSBarry Smith 
1385a2b941aSBarry Smith   /* loop over all potential blocks in the matrix to see if the potential block has a nonzero */
1395a2b941aSBarry Smith   for (PetscInt i = 0; i < m / bs; i++) {
1405a2b941aSBarry Smith     for (PetscInt k = 0; k < bs; k++) ii[k] = Aa->i[i * bs + k];
1415a2b941aSBarry Smith     for (PetscInt j = 0; j < n / bs; j++) {
1425a2b941aSBarry Smith       for (PetscInt k = 0; k < bs; k++) {
1435a2b941aSBarry Smith         for (; ii[k] < Aa->i[i * bs + k + 1] && Aa->j[ii[k]] < (j + 1) * bs; ii[k]++) {
1445a2b941aSBarry Smith           if (j >= i && Aa->j[ii[k]] >= j * bs) {
1455a2b941aSBarry Smith             /* found a nonzero in the potential block so allocate for that block and jump to check the next potential block */
1465a2b941aSBarry Smith             (*nnz)[i]++;
1475a2b941aSBarry Smith             goto theend;
1485a2b941aSBarry Smith           }
1495a2b941aSBarry Smith         }
1505a2b941aSBarry Smith       }
1515a2b941aSBarry Smith     theend:;
1525a2b941aSBarry Smith     }
1535a2b941aSBarry Smith   }
1545a2b941aSBarry Smith   PetscCall(PetscFree(ii));
155*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1565a2b941aSBarry Smith }
1575a2b941aSBarry Smith 
158d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqSBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
159d71ae5a4SJacob Faibussowitsch {
160676c34cdSKris Buschelman   Mat           B;
16159557b74SHong Zhang   Mat_SeqAIJ   *a = (Mat_SeqAIJ *)A->data;
162861ba921SHong Zhang   Mat_SeqSBAIJ *b;
163ae8d29abSPierre Jolivet   PetscInt     *ai = a->i, *aj, m = A->rmap->N, n = A->cmap->N, i, j, *bi, *bj, *rowlengths, bs = PetscAbs(A->rmap->bs);
164dd6ea824SBarry Smith   MatScalar    *av, *bv;
165b05258aeSStefano Zampini   PetscBool     miss = PETSC_FALSE;
16659557b74SHong Zhang 
16759557b74SHong Zhang   PetscFunctionBegin;
168b05258aeSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
169b94d7dedSBarry Smith   PetscCheck(A->symmetric == PETSC_BOOL3_TRUE, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)");
170b05258aeSStefano Zampini #else
171b94d7dedSBarry Smith   PetscCheck(A->symmetric == PETSC_BOOL3_TRUE || A->hermitian == PETSC_BOOL3_TRUE, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "Matrix must be either symmetric or hermitian. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE) and/or MatSetOption(mat,MAT_HERMITIAN,PETSC_TRUE)");
172b05258aeSStefano Zampini #endif
17308401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Matrix must be square");
17459557b74SHong Zhang 
1755a2b941aSBarry Smith   if (bs == 1) {
1765a2b941aSBarry Smith     PetscCall(PetscMalloc1(m, &rowlengths));
1775a2b941aSBarry Smith     for (i = 0; i < m; i++) {
1785a2b941aSBarry Smith       if (a->diag[i] == ai[i + 1]) {             /* missing diagonal */
1795a2b941aSBarry Smith         rowlengths[i] = (ai[i + 1] - ai[i]) + 1; /* allocate some extra space */
180b05258aeSStefano Zampini         miss          = PETSC_TRUE;
181b05258aeSStefano Zampini       } else {
1825a2b941aSBarry Smith         rowlengths[i] = (ai[i + 1] - a->diag[i]);
18359557b74SHong Zhang       }
184b05258aeSStefano Zampini     }
1855a2b941aSBarry Smith   } else PetscCall(MatConvert_SeqAIJ_SeqSBAIJ_Preallocate(A, &rowlengths));
186bd019fc1SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1879566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1889566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1899566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQSBAIJ));
1909566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, rowlengths));
191bd019fc1SStefano Zampini   } else B = *newmat;
19259557b74SHong Zhang 
193b05258aeSStefano Zampini   if (bs == 1 && !miss) {
194676c34cdSKris Buschelman     b  = (Mat_SeqSBAIJ *)(B->data);
195861ba921SHong Zhang     bi = b->i;
196861ba921SHong Zhang     bj = b->j;
197861ba921SHong Zhang     bv = b->a;
198861ba921SHong Zhang 
199861ba921SHong Zhang     bi[0] = 0;
20059557b74SHong Zhang     for (i = 0; i < m; i++) {
20159557b74SHong Zhang       aj = a->j + a->diag[i];
20259557b74SHong Zhang       av = a->a + a->diag[i];
203861ba921SHong Zhang       for (j = 0; j < rowlengths[i]; j++) {
2049371c9d4SSatish Balay         *bj = *aj;
2059371c9d4SSatish Balay         bj++;
2069371c9d4SSatish Balay         aj++;
2079371c9d4SSatish Balay         *bv = *av;
2089371c9d4SSatish Balay         bv++;
2099371c9d4SSatish Balay         av++;
210861ba921SHong Zhang       }
211861ba921SHong Zhang       bi[i + 1]  = bi[i] + rowlengths[i];
212861ba921SHong Zhang       b->ilen[i] = rowlengths[i];
21359557b74SHong Zhang     }
2149566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2159566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
216ae8d29abSPierre Jolivet   } else {
2179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE));
218ae8d29abSPierre Jolivet     /* reuse may not be equal to MAT_REUSE_MATRIX, but the basic converter will reallocate or replace newmat if this value is not used */
219ae8d29abSPierre Jolivet     /* if reuse is equal to MAT_INITIAL_MATRIX, it has been appropriately preallocated before                                          */
220ae8d29abSPierre Jolivet     /*                      MAT_INPLACE_MATRIX, it will be replaced with MatHeaderReplace below                                        */
2219566063dSJacob Faibussowitsch     PetscCall(MatConvert_Basic(A, newtype, MAT_REUSE_MATRIX, &B));
222ae8d29abSPierre Jolivet   }
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(rowlengths));
224511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2259566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
226ae8d29abSPierre Jolivet   } else *newmat = B;
227*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22859557b74SHong Zhang }
22959557b74SHong Zhang 
230d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
231d71ae5a4SJacob Faibussowitsch {
232a0e1a404SHong Zhang   Mat           B;
233a0e1a404SHong Zhang   Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data;
234a0e1a404SHong Zhang   Mat_SeqBAIJ  *b;
235d0f46423SBarry Smith   PetscInt     *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->n, i, k, *bi, *bj, *browlengths, nz, *browstart, itmp;
23674ee4d9fSHong Zhang   PetscInt      bs = A->rmap->bs, bs2 = bs * bs, mbs = m / bs, col, row;
237dd6ea824SBarry Smith   MatScalar    *av, *bv;
238eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX)
239b94d7dedSBarry Smith   const int aconj = A->hermitian == PETSC_BOOL3_TRUE ? 1 : 0;
240eb1ec7c1SStefano Zampini #else
241eb1ec7c1SStefano Zampini   const int aconj = 0;
242eb1ec7c1SStefano Zampini #endif
243a0e1a404SHong Zhang 
244a0e1a404SHong Zhang   PetscFunctionBegin;
245a0e1a404SHong Zhang   /* compute browlengths of newmat */
2469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(mbs, &browlengths, mbs, &browstart));
247a0e1a404SHong Zhang   for (i = 0; i < mbs; i++) browlengths[i] = 0;
248a0e1a404SHong Zhang   for (i = 0; i < mbs; i++) {
249a0e1a404SHong Zhang     nz = ai[i + 1] - ai[i];
250a0e1a404SHong Zhang     aj++;                      /* skip diagonal */
251a0e1a404SHong Zhang     for (k = 1; k < nz; k++) { /* no. of lower triangular blocks */
2529371c9d4SSatish Balay       browlengths[*aj]++;
2539371c9d4SSatish Balay       aj++;
254a0e1a404SHong Zhang     }
255a0e1a404SHong Zhang     browlengths[i] += nz; /* no. of upper triangular blocks */
256a0e1a404SHong Zhang   }
257a0e1a404SHong Zhang 
258bd019fc1SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2599566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2609566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
2619566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQBAIJ));
2629566063dSJacob Faibussowitsch     PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, browlengths));
263bd019fc1SStefano Zampini   } else B = *newmat;
264a0e1a404SHong Zhang 
265a0e1a404SHong Zhang   b  = (Mat_SeqBAIJ *)(B->data);
266a0e1a404SHong Zhang   bi = b->i;
267a0e1a404SHong Zhang   bj = b->j;
268a0e1a404SHong Zhang   bv = b->a;
269a0e1a404SHong Zhang 
270a0e1a404SHong Zhang   /* set b->i */
271a0e1a404SHong Zhang   bi[0] = 0;
272a0e1a404SHong Zhang   for (i = 0; i < mbs; i++) {
273a0e1a404SHong Zhang     b->ilen[i]   = browlengths[i];
274a0e1a404SHong Zhang     bi[i + 1]    = bi[i] + browlengths[i];
275a0e1a404SHong Zhang     browstart[i] = bi[i];
276a0e1a404SHong Zhang   }
277aed4548fSBarry Smith   PetscCheck(bi[mbs] == 2 * a->nz - mbs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "bi[mbs]: %" PetscInt_FMT " != 2*a->nz - mbs: %" PetscInt_FMT, bi[mbs], 2 * a->nz - mbs);
278a0e1a404SHong Zhang 
279a0e1a404SHong Zhang   /* set b->j and b->a */
2809371c9d4SSatish Balay   aj = a->j;
2819371c9d4SSatish Balay   av = a->a;
282a0e1a404SHong Zhang   for (i = 0; i < mbs; i++) {
283a0e1a404SHong Zhang     /* diagonal block */
2849371c9d4SSatish Balay     *(bj + browstart[i]) = *aj;
2859371c9d4SSatish Balay     aj++;
28626fbe8dcSKarl Rupp 
287a0e1a404SHong Zhang     itmp = bs2 * browstart[i];
288a0e1a404SHong Zhang     for (k = 0; k < bs2; k++) {
2899371c9d4SSatish Balay       *(bv + itmp + k) = *av;
2909371c9d4SSatish Balay       av++;
291a0e1a404SHong Zhang     }
292a0e1a404SHong Zhang     browstart[i]++;
293a0e1a404SHong Zhang 
294a0e1a404SHong Zhang     nz = ai[i + 1] - ai[i] - 1;
295a0e1a404SHong Zhang     while (nz--) {
29674ee4d9fSHong Zhang       /* lower triangular blocks - transpose blocks of A */
29774ee4d9fSHong Zhang       *(bj + browstart[*aj]) = i; /* block col index */
29826fbe8dcSKarl Rupp 
29974ee4d9fSHong Zhang       itmp = bs2 * browstart[*aj]; /* row index */
30074ee4d9fSHong Zhang       for (col = 0; col < bs; col++) {
30174ee4d9fSHong Zhang         k = col;
30274ee4d9fSHong Zhang         for (row = 0; row < bs; row++) {
303eb1ec7c1SStefano Zampini           bv[itmp + col * bs + row] = aconj ? PetscConj(av[k]) : av[k];
304eb1ec7c1SStefano Zampini           k += bs;
30574ee4d9fSHong Zhang         }
306a0e1a404SHong Zhang       }
307a0e1a404SHong Zhang       browstart[*aj]++;
308a0e1a404SHong Zhang 
309a0e1a404SHong Zhang       /* upper triangular blocks */
3109371c9d4SSatish Balay       *(bj + browstart[i]) = *aj;
3119371c9d4SSatish Balay       aj++;
31226fbe8dcSKarl Rupp 
313a0e1a404SHong Zhang       itmp = bs2 * browstart[i];
314ad540459SPierre Jolivet       for (k = 0; k < bs2; k++) bv[itmp + k] = av[k];
31574ee4d9fSHong Zhang       av += bs2;
316a0e1a404SHong Zhang       browstart[i]++;
317a0e1a404SHong Zhang     }
318a0e1a404SHong Zhang   }
3199566063dSJacob Faibussowitsch   PetscCall(PetscFree2(browlengths, browstart));
3209566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
3219566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
322a0e1a404SHong Zhang 
323511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
3249566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
325ae8d29abSPierre Jolivet   } else *newmat = B;
326*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
327a0e1a404SHong Zhang }
328be1d678aSKris Buschelman 
329d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqBAIJ_SeqSBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
330d71ae5a4SJacob Faibussowitsch {
331a0e1a404SHong Zhang   Mat           B;
332a0e1a404SHong Zhang   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ *)A->data;
333a0e1a404SHong Zhang   Mat_SeqSBAIJ *b;
334d0f46423SBarry Smith   PetscInt     *ai = a->i, *aj, m = A->rmap->N, n = A->cmap->n, i, j, k, *bi, *bj, *browlengths;
335d0f46423SBarry Smith   PetscInt      bs = A->rmap->bs, bs2 = bs * bs, mbs = m / bs, dd;
336dd6ea824SBarry Smith   MatScalar    *av, *bv;
337ace3abfcSBarry Smith   PetscBool     flg;
338a0e1a404SHong Zhang 
339a0e1a404SHong Zhang   PetscFunctionBegin;
34028b400f6SJacob Faibussowitsch   PetscCheck(A->symmetric, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)");
34108401ef6SPierre Jolivet   PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Matrix must be square");
3429566063dSJacob Faibussowitsch   PetscCall(MatMissingDiagonal_SeqBAIJ(A, &flg, &dd)); /* check for missing diagonals, then mark diag */
34328b400f6SJacob Faibussowitsch   PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal %" PetscInt_FMT, dd);
344a0e1a404SHong Zhang 
3459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mbs, &browlengths));
346ad540459SPierre Jolivet   for (i = 0; i < mbs; i++) browlengths[i] = ai[i + 1] - a->diag[i];
347a0e1a404SHong Zhang 
348bd019fc1SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
3499566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
3509566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
3519566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQSBAIJ));
3529566063dSJacob Faibussowitsch     PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, browlengths));
353bd019fc1SStefano Zampini   } else B = *newmat;
354a0e1a404SHong Zhang 
355a0e1a404SHong Zhang   b  = (Mat_SeqSBAIJ *)(B->data);
356a0e1a404SHong Zhang   bi = b->i;
357a0e1a404SHong Zhang   bj = b->j;
358a0e1a404SHong Zhang   bv = b->a;
359a0e1a404SHong Zhang 
360a0e1a404SHong Zhang   bi[0] = 0;
361a0e1a404SHong Zhang   for (i = 0; i < mbs; i++) {
362a0e1a404SHong Zhang     aj = a->j + a->diag[i];
363a0e1a404SHong Zhang     av = a->a + (a->diag[i]) * bs2;
364a0e1a404SHong Zhang     for (j = 0; j < browlengths[i]; j++) {
3659371c9d4SSatish Balay       *bj = *aj;
3669371c9d4SSatish Balay       bj++;
3679371c9d4SSatish Balay       aj++;
368a0e1a404SHong Zhang       for (k = 0; k < bs2; k++) {
3699371c9d4SSatish Balay         *bv = *av;
3709371c9d4SSatish Balay         bv++;
3719371c9d4SSatish Balay         av++;
372a0e1a404SHong Zhang       }
373a0e1a404SHong Zhang     }
374a0e1a404SHong Zhang     bi[i + 1]  = bi[i] + browlengths[i];
375a0e1a404SHong Zhang     b->ilen[i] = browlengths[i];
376a0e1a404SHong Zhang   }
3779566063dSJacob Faibussowitsch   PetscCall(PetscFree(browlengths));
3789566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
3799566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
380a0e1a404SHong Zhang 
381511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
3829566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
383ae8d29abSPierre Jolivet   } else *newmat = B;
384*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
385a0e1a404SHong Zhang }
386