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 6*9371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) { 74e5e7fe4SHong Zhang Mat B; 84e5e7fe4SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 94e5e7fe4SHong Zhang Mat_SeqAIJ *b; 10d0f46423SBarry 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; 1101be0148SBarry Smith PetscInt bs = A->rmap->bs, bs2 = bs * bs, mbs = A->rmap->N / bs, diagcnt = 0; 12dd6ea824SBarry Smith MatScalar *av, *bv; 13eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 14b94d7dedSBarry Smith const int aconj = A->hermitian == PETSC_BOOL3_TRUE ? 1 : 0; 15eb1ec7c1SStefano Zampini #else 16eb1ec7c1SStefano Zampini const int aconj = 0; 17eb1ec7c1SStefano Zampini #endif 184e5e7fe4SHong Zhang 194e5e7fe4SHong Zhang PetscFunctionBegin; 204e5e7fe4SHong Zhang /* compute rowlengths of newmat */ 219566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &rowlengths, m + 1, &rowstart)); 22a7a3a9ebSHong Zhang 23a7a3a9ebSHong Zhang for (i = 0; i < mbs; i++) rowlengths[i * bs] = 0; 24a7a3a9ebSHong Zhang k = 0; 25a7a3a9ebSHong Zhang for (i = 0; i < mbs; i++) { 264e5e7fe4SHong Zhang nz = ai[i + 1] - ai[i]; 2701be0148SBarry Smith if (nz) { 2801be0148SBarry Smith rowlengths[k] += nz; /* no. of upper triangular blocks */ 29*9371c9d4SSatish Balay if (*aj == i) { 30*9371c9d4SSatish Balay aj++; 31*9371c9d4SSatish Balay diagcnt++; 32*9371c9d4SSatish Balay nz--; 33*9371c9d4SSatish Balay } /* skip diagonal */ 3401be0148SBarry Smith for (j = 0; j < nz; j++) { /* no. of lower triangular blocks */ 35*9371c9d4SSatish Balay rowlengths[(*aj) * bs]++; 36*9371c9d4SSatish Balay aj++; 37a7a3a9ebSHong Zhang } 3801be0148SBarry Smith } 39a7a3a9ebSHong Zhang rowlengths[k] *= bs; 40*9371c9d4SSatish Balay for (j = 1; j < bs; j++) { rowlengths[k + j] = rowlengths[k]; } 41a7a3a9ebSHong Zhang k += bs; 424e5e7fe4SHong Zhang } 434e5e7fe4SHong Zhang 44bd019fc1SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 459566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, m, n)); 479566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQAIJ)); 489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, rowlengths)); 499566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, A->rmap->bs)); 50bd019fc1SStefano Zampini } else B = *newmat; 514e5e7fe4SHong Zhang 524e5e7fe4SHong Zhang b = (Mat_SeqAIJ *)(B->data); 534e5e7fe4SHong Zhang bi = b->i; 544e5e7fe4SHong Zhang bj = b->j; 554e5e7fe4SHong Zhang bv = b->a; 564e5e7fe4SHong Zhang 574e5e7fe4SHong Zhang /* set b->i */ 58*9371c9d4SSatish Balay bi[0] = 0; 59*9371c9d4SSatish Balay rowstart[0] = 0; 60a7a3a9ebSHong Zhang for (i = 0; i < mbs; i++) { 61a7a3a9ebSHong Zhang for (j = 0; j < bs; j++) { 62a7a3a9ebSHong Zhang b->ilen[i * bs + j] = rowlengths[i * bs]; 63a7a3a9ebSHong Zhang rowstart[i * bs + j + 1] = rowstart[i * bs + j] + rowlengths[i * bs]; 644e5e7fe4SHong Zhang } 65a7a3a9ebSHong Zhang bi[i + 1] = bi[i] + rowlengths[i * bs] / bs; 66a7a3a9ebSHong Zhang } 67aed4548fSBarry 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); 684e5e7fe4SHong Zhang 694e5e7fe4SHong Zhang /* set b->j and b->a */ 70*9371c9d4SSatish Balay aj = a->j; 71*9371c9d4SSatish Balay av = a->a; 72a7a3a9ebSHong Zhang for (i = 0; i < mbs; i++) { 7301be0148SBarry Smith nz = ai[i + 1] - ai[i]; 74a7a3a9ebSHong Zhang /* diagonal block */ 7501be0148SBarry Smith if (nz && *aj == i) { 7601be0148SBarry Smith nz--; 77a7a3a9ebSHong Zhang for (j = 0; j < bs; j++) { /* row i*bs+j */ 78a7a3a9ebSHong Zhang itmp = i * bs + j; 79a7a3a9ebSHong Zhang for (k = 0; k < bs; k++) { /* col i*bs+k */ 80a7a3a9ebSHong Zhang *(bj + rowstart[itmp]) = (*aj) * bs + k; 81a7a3a9ebSHong Zhang *(bv + rowstart[itmp]) = *(av + k * bs + j); 82a7a3a9ebSHong Zhang rowstart[itmp]++; 83a7a3a9ebSHong Zhang } 84a7a3a9ebSHong Zhang } 85*9371c9d4SSatish Balay aj++; 86*9371c9d4SSatish Balay av += bs2; 8701be0148SBarry Smith } 88a7a3a9ebSHong Zhang 894e5e7fe4SHong Zhang while (nz--) { 90a7a3a9ebSHong Zhang /* lower triangular blocks */ 91a7a3a9ebSHong Zhang for (j = 0; j < bs; j++) { /* row (*aj)*bs+j */ 92a7a3a9ebSHong Zhang itmp = (*aj) * bs + j; 93a7a3a9ebSHong Zhang for (k = 0; k < bs; k++) { /* col i*bs+k */ 94a7a3a9ebSHong Zhang *(bj + rowstart[itmp]) = i * bs + k; 95eb1ec7c1SStefano Zampini *(bv + rowstart[itmp]) = aconj ? PetscConj(*(av + j * bs + k)) : *(av + j * bs + k); 96a7a3a9ebSHong Zhang rowstart[itmp]++; 97a7a3a9ebSHong Zhang } 98a7a3a9ebSHong Zhang } 99a7a3a9ebSHong Zhang /* upper triangular blocks */ 100a7a3a9ebSHong Zhang for (j = 0; j < bs; j++) { /* row i*bs+j */ 101a7a3a9ebSHong Zhang itmp = i * bs + j; 102a7a3a9ebSHong Zhang for (k = 0; k < bs; k++) { /* col (*aj)*bs+k */ 103a7a3a9ebSHong Zhang *(bj + rowstart[itmp]) = (*aj) * bs + k; 104a7a3a9ebSHong Zhang *(bv + rowstart[itmp]) = *(av + k * bs + j); 105a7a3a9ebSHong Zhang rowstart[itmp]++; 106a7a3a9ebSHong Zhang } 107a7a3a9ebSHong Zhang } 108*9371c9d4SSatish Balay aj++; 109*9371c9d4SSatish Balay av += bs2; 1104e5e7fe4SHong Zhang } 1114e5e7fe4SHong Zhang } 1129566063dSJacob Faibussowitsch PetscCall(PetscFree2(rowlengths, rowstart)); 1139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 1149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 1154e5e7fe4SHong Zhang 116511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 1179566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 118c3d102feSKris Buschelman } else { 1194e5e7fe4SHong Zhang *newmat = B; 120c3d102feSKris Buschelman } 1214e5e7fe4SHong Zhang PetscFunctionReturn(0); 1224e5e7fe4SHong Zhang } 123be1d678aSKris Buschelman 124*9371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqSBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) { 125676c34cdSKris Buschelman Mat B; 12659557b74SHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 127861ba921SHong Zhang Mat_SeqSBAIJ *b; 128ae8d29abSPierre Jolivet PetscInt *ai = a->i, *aj, m = A->rmap->N, n = A->cmap->N, i, j, *bi, *bj, *rowlengths, bs = PetscAbs(A->rmap->bs); 129dd6ea824SBarry Smith MatScalar *av, *bv; 130b05258aeSStefano Zampini PetscBool miss = PETSC_FALSE; 13159557b74SHong Zhang 13259557b74SHong Zhang PetscFunctionBegin; 133b05258aeSStefano Zampini #if !defined(PETSC_USE_COMPLEX) 134b94d7dedSBarry Smith PetscCheck(A->symmetric == PETSC_BOOL3_TRUE, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)"); 135b05258aeSStefano Zampini #else 136b94d7dedSBarry 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)"); 137b05258aeSStefano Zampini #endif 13808401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Matrix must be square"); 13959557b74SHong Zhang 1409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m / bs, &rowlengths)); 141ae8d29abSPierre Jolivet for (i = 0; i < m / bs; i++) { 142b05258aeSStefano Zampini if (a->diag[i * bs] == ai[i * bs + 1]) { /* missing diagonal */ 143b05258aeSStefano Zampini rowlengths[i] = (ai[i * bs + 1] - ai[i * bs]) / bs; /* allocate some extra space */ 144b05258aeSStefano Zampini miss = PETSC_TRUE; 145b05258aeSStefano Zampini } else { 146ae8d29abSPierre Jolivet rowlengths[i] = (ai[i * bs + 1] - a->diag[i * bs]) / bs; 14759557b74SHong Zhang } 148b05258aeSStefano Zampini } 149bd019fc1SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 1509566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 1519566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, m, n)); 1529566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQSBAIJ)); 1539566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, rowlengths)); 154bd019fc1SStefano Zampini } else B = *newmat; 15559557b74SHong Zhang 156b05258aeSStefano Zampini if (bs == 1 && !miss) { 157676c34cdSKris Buschelman b = (Mat_SeqSBAIJ *)(B->data); 158861ba921SHong Zhang bi = b->i; 159861ba921SHong Zhang bj = b->j; 160861ba921SHong Zhang bv = b->a; 161861ba921SHong Zhang 162861ba921SHong Zhang bi[0] = 0; 16359557b74SHong Zhang for (i = 0; i < m; i++) { 16459557b74SHong Zhang aj = a->j + a->diag[i]; 16559557b74SHong Zhang av = a->a + a->diag[i]; 166861ba921SHong Zhang for (j = 0; j < rowlengths[i]; j++) { 167*9371c9d4SSatish Balay *bj = *aj; 168*9371c9d4SSatish Balay bj++; 169*9371c9d4SSatish Balay aj++; 170*9371c9d4SSatish Balay *bv = *av; 171*9371c9d4SSatish Balay bv++; 172*9371c9d4SSatish Balay av++; 173861ba921SHong Zhang } 174861ba921SHong Zhang bi[i + 1] = bi[i] + rowlengths[i]; 175861ba921SHong Zhang b->ilen[i] = rowlengths[i]; 17659557b74SHong Zhang } 1779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 1789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 179ae8d29abSPierre Jolivet } else { 1809566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE)); 181ae8d29abSPierre 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 */ 182ae8d29abSPierre Jolivet /* if reuse is equal to MAT_INITIAL_MATRIX, it has been appropriately preallocated before */ 183ae8d29abSPierre Jolivet /* MAT_INPLACE_MATRIX, it will be replaced with MatHeaderReplace below */ 1849566063dSJacob Faibussowitsch PetscCall(MatConvert_Basic(A, newtype, MAT_REUSE_MATRIX, &B)); 185ae8d29abSPierre Jolivet } 1869566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlengths)); 187511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 1889566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 189ae8d29abSPierre Jolivet } else *newmat = B; 19059557b74SHong Zhang PetscFunctionReturn(0); 19159557b74SHong Zhang } 19259557b74SHong Zhang 193*9371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) { 194a0e1a404SHong Zhang Mat B; 195a0e1a404SHong Zhang Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ *)A->data; 196a0e1a404SHong Zhang Mat_SeqBAIJ *b; 197d0f46423SBarry Smith PetscInt *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->n, i, k, *bi, *bj, *browlengths, nz, *browstart, itmp; 19874ee4d9fSHong Zhang PetscInt bs = A->rmap->bs, bs2 = bs * bs, mbs = m / bs, col, row; 199dd6ea824SBarry Smith MatScalar *av, *bv; 200eb1ec7c1SStefano Zampini #if defined(PETSC_USE_COMPLEX) 201b94d7dedSBarry Smith const int aconj = A->hermitian == PETSC_BOOL3_TRUE ? 1 : 0; 202eb1ec7c1SStefano Zampini #else 203eb1ec7c1SStefano Zampini const int aconj = 0; 204eb1ec7c1SStefano Zampini #endif 205a0e1a404SHong Zhang 206a0e1a404SHong Zhang PetscFunctionBegin; 207a0e1a404SHong Zhang /* compute browlengths of newmat */ 2089566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mbs, &browlengths, mbs, &browstart)); 209a0e1a404SHong Zhang for (i = 0; i < mbs; i++) browlengths[i] = 0; 210a0e1a404SHong Zhang for (i = 0; i < mbs; i++) { 211a0e1a404SHong Zhang nz = ai[i + 1] - ai[i]; 212a0e1a404SHong Zhang aj++; /* skip diagonal */ 213a0e1a404SHong Zhang for (k = 1; k < nz; k++) { /* no. of lower triangular blocks */ 214*9371c9d4SSatish Balay browlengths[*aj]++; 215*9371c9d4SSatish Balay aj++; 216a0e1a404SHong Zhang } 217a0e1a404SHong Zhang browlengths[i] += nz; /* no. of upper triangular blocks */ 218a0e1a404SHong Zhang } 219a0e1a404SHong Zhang 220bd019fc1SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 2219566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 2229566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, m, n)); 2239566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQBAIJ)); 2249566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, browlengths)); 225bd019fc1SStefano Zampini } else B = *newmat; 226a0e1a404SHong Zhang 227a0e1a404SHong Zhang b = (Mat_SeqBAIJ *)(B->data); 228a0e1a404SHong Zhang bi = b->i; 229a0e1a404SHong Zhang bj = b->j; 230a0e1a404SHong Zhang bv = b->a; 231a0e1a404SHong Zhang 232a0e1a404SHong Zhang /* set b->i */ 233a0e1a404SHong Zhang bi[0] = 0; 234a0e1a404SHong Zhang for (i = 0; i < mbs; i++) { 235a0e1a404SHong Zhang b->ilen[i] = browlengths[i]; 236a0e1a404SHong Zhang bi[i + 1] = bi[i] + browlengths[i]; 237a0e1a404SHong Zhang browstart[i] = bi[i]; 238a0e1a404SHong Zhang } 239aed4548fSBarry 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); 240a0e1a404SHong Zhang 241a0e1a404SHong Zhang /* set b->j and b->a */ 242*9371c9d4SSatish Balay aj = a->j; 243*9371c9d4SSatish Balay av = a->a; 244a0e1a404SHong Zhang for (i = 0; i < mbs; i++) { 245a0e1a404SHong Zhang /* diagonal block */ 246*9371c9d4SSatish Balay *(bj + browstart[i]) = *aj; 247*9371c9d4SSatish Balay aj++; 24826fbe8dcSKarl Rupp 249a0e1a404SHong Zhang itmp = bs2 * browstart[i]; 250a0e1a404SHong Zhang for (k = 0; k < bs2; k++) { 251*9371c9d4SSatish Balay *(bv + itmp + k) = *av; 252*9371c9d4SSatish Balay av++; 253a0e1a404SHong Zhang } 254a0e1a404SHong Zhang browstart[i]++; 255a0e1a404SHong Zhang 256a0e1a404SHong Zhang nz = ai[i + 1] - ai[i] - 1; 257a0e1a404SHong Zhang while (nz--) { 25874ee4d9fSHong Zhang /* lower triangular blocks - transpose blocks of A */ 25974ee4d9fSHong Zhang *(bj + browstart[*aj]) = i; /* block col index */ 26026fbe8dcSKarl Rupp 26174ee4d9fSHong Zhang itmp = bs2 * browstart[*aj]; /* row index */ 26274ee4d9fSHong Zhang for (col = 0; col < bs; col++) { 26374ee4d9fSHong Zhang k = col; 26474ee4d9fSHong Zhang for (row = 0; row < bs; row++) { 265eb1ec7c1SStefano Zampini bv[itmp + col * bs + row] = aconj ? PetscConj(av[k]) : av[k]; 266eb1ec7c1SStefano Zampini k += bs; 26774ee4d9fSHong Zhang } 268a0e1a404SHong Zhang } 269a0e1a404SHong Zhang browstart[*aj]++; 270a0e1a404SHong Zhang 271a0e1a404SHong Zhang /* upper triangular blocks */ 272*9371c9d4SSatish Balay *(bj + browstart[i]) = *aj; 273*9371c9d4SSatish Balay aj++; 27426fbe8dcSKarl Rupp 275a0e1a404SHong Zhang itmp = bs2 * browstart[i]; 276*9371c9d4SSatish Balay for (k = 0; k < bs2; k++) { bv[itmp + k] = av[k]; } 27774ee4d9fSHong Zhang av += bs2; 278a0e1a404SHong Zhang browstart[i]++; 279a0e1a404SHong Zhang } 280a0e1a404SHong Zhang } 2819566063dSJacob Faibussowitsch PetscCall(PetscFree2(browlengths, browstart)); 2829566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 2839566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 284a0e1a404SHong Zhang 285511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 2869566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 287ae8d29abSPierre Jolivet } else *newmat = B; 288a0e1a404SHong Zhang PetscFunctionReturn(0); 289a0e1a404SHong Zhang } 290be1d678aSKris Buschelman 291*9371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_SeqBAIJ_SeqSBAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) { 292a0e1a404SHong Zhang Mat B; 293a0e1a404SHong Zhang Mat_SeqBAIJ *a = (Mat_SeqBAIJ *)A->data; 294a0e1a404SHong Zhang Mat_SeqSBAIJ *b; 295d0f46423SBarry Smith PetscInt *ai = a->i, *aj, m = A->rmap->N, n = A->cmap->n, i, j, k, *bi, *bj, *browlengths; 296d0f46423SBarry Smith PetscInt bs = A->rmap->bs, bs2 = bs * bs, mbs = m / bs, dd; 297dd6ea824SBarry Smith MatScalar *av, *bv; 298ace3abfcSBarry Smith PetscBool flg; 299a0e1a404SHong Zhang 300a0e1a404SHong Zhang PetscFunctionBegin; 30128b400f6SJacob Faibussowitsch PetscCheck(A->symmetric, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "Matrix must be symmetric. Call MatSetOption(mat,MAT_SYMMETRIC,PETSC_TRUE)"); 30208401ef6SPierre Jolivet PetscCheck(n == m, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3039566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqBAIJ(A, &flg, &dd)); /* check for missing diagonals, then mark diag */ 30428b400f6SJacob Faibussowitsch PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix is missing diagonal %" PetscInt_FMT, dd); 305a0e1a404SHong Zhang 3069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mbs, &browlengths)); 307*9371c9d4SSatish Balay for (i = 0; i < mbs; i++) { browlengths[i] = ai[i + 1] - a->diag[i]; } 308a0e1a404SHong Zhang 309bd019fc1SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 3109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 3119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, m, n)); 3129566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATSEQSBAIJ)); 3139566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(B, bs, 0, browlengths)); 314bd019fc1SStefano Zampini } else B = *newmat; 315a0e1a404SHong Zhang 316a0e1a404SHong Zhang b = (Mat_SeqSBAIJ *)(B->data); 317a0e1a404SHong Zhang bi = b->i; 318a0e1a404SHong Zhang bj = b->j; 319a0e1a404SHong Zhang bv = b->a; 320a0e1a404SHong Zhang 321a0e1a404SHong Zhang bi[0] = 0; 322a0e1a404SHong Zhang for (i = 0; i < mbs; i++) { 323a0e1a404SHong Zhang aj = a->j + a->diag[i]; 324a0e1a404SHong Zhang av = a->a + (a->diag[i]) * bs2; 325a0e1a404SHong Zhang for (j = 0; j < browlengths[i]; j++) { 326*9371c9d4SSatish Balay *bj = *aj; 327*9371c9d4SSatish Balay bj++; 328*9371c9d4SSatish Balay aj++; 329a0e1a404SHong Zhang for (k = 0; k < bs2; k++) { 330*9371c9d4SSatish Balay *bv = *av; 331*9371c9d4SSatish Balay bv++; 332*9371c9d4SSatish Balay av++; 333a0e1a404SHong Zhang } 334a0e1a404SHong Zhang } 335a0e1a404SHong Zhang bi[i + 1] = bi[i] + browlengths[i]; 336a0e1a404SHong Zhang b->ilen[i] = browlengths[i]; 337a0e1a404SHong Zhang } 3389566063dSJacob Faibussowitsch PetscCall(PetscFree(browlengths)); 3399566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 3409566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 341a0e1a404SHong Zhang 342511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 3439566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 344ae8d29abSPierre Jolivet } else *newmat = B; 345a0e1a404SHong Zhang PetscFunctionReturn(0); 346a0e1a404SHong Zhang } 347