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