1d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h> /*I "petscmat.h" I*/ 2d4002b98SHong Zhang #include <../src/mat/impls/sell/mpi/mpisell.h> /*I "petscmat.h" I*/ 3d4002b98SHong Zhang #include <petsc/private/vecimpl.h> 4d4002b98SHong Zhang #include <petsc/private/isimpl.h> 5d4002b98SHong Zhang #include <petscblaslapack.h> 6d4002b98SHong Zhang #include <petscsf.h> 7d4002b98SHong Zhang 8d4002b98SHong Zhang /*MC 9d4002b98SHong Zhang MATSELL - MATSELL = "sell" - A matrix type to be used for sparse matrices. 10d4002b98SHong Zhang 1111a5261eSBarry Smith This matrix type is identical to `MATSEQSELL` when constructed with a single process communicator, 1211a5261eSBarry Smith and `MATMPISELL` otherwise. As a result, for single process communicators, 1311a5261eSBarry Smith `MatSeqSELLSetPreallocation()` is supported, and similarly `MatMPISELLSetPreallocation()` is supported 14d4002b98SHong Zhang for communicators controlling multiple processes. It is recommended that you call both of 15d4002b98SHong Zhang the above preallocation routines for simplicity. 16d4002b98SHong Zhang 17d4002b98SHong Zhang Options Database Keys: 1820f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()` 19d4002b98SHong Zhang 20d4002b98SHong Zhang Level: beginner 21d4002b98SHong Zhang 2267be906fSBarry Smith .seealso: `Mat`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSELL()`, `MatCreateSeqSELL()`, `MATSEQSELL`, `MATMPISELL` 23d4002b98SHong Zhang M*/ 24d4002b98SHong Zhang 25ba38deedSJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_MPISELL(Mat Y, Vec D, InsertMode is) 26d71ae5a4SJacob Faibussowitsch { 27d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)Y->data; 28d4002b98SHong Zhang 29d4002b98SHong Zhang PetscFunctionBegin; 30d4002b98SHong Zhang if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) { 319566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(sell->A, D, is)); 32d4002b98SHong Zhang } else { 339566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 34d4002b98SHong Zhang } 353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36d4002b98SHong Zhang } 37d4002b98SHong Zhang 38d4002b98SHong Zhang /* 39d4002b98SHong Zhang Local utility routine that creates a mapping from the global column 40d4002b98SHong Zhang number to the local number in the off-diagonal part of the local 41d4002b98SHong Zhang storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at 42d4002b98SHong Zhang a slightly higher hash table cost; without it it is not scalable (each processor 43da81f932SPierre Jolivet has an order N integer array but is fast to access. 44d4002b98SHong Zhang */ 45d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat) 46d71ae5a4SJacob Faibussowitsch { 47d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 48d4002b98SHong Zhang PetscInt n = sell->B->cmap->n, i; 49d4002b98SHong Zhang 50d4002b98SHong Zhang PetscFunctionBegin; 5128b400f6SJacob Faibussowitsch PetscCheck(sell->garray, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MPISELL Matrix was assembled but is missing garray"); 52d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 53eec179cfSJacob Faibussowitsch PetscCall(PetscHMapICreateWithSize(n, &sell->colmap)); 54c76ffc5fSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscHMapISet(sell->colmap, sell->garray[i] + 1, i + 1)); 55d4002b98SHong Zhang #else 569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(mat->cmap->N + 1, &sell->colmap)); 57d4002b98SHong Zhang for (i = 0; i < n; i++) sell->colmap[sell->garray[i]] = i + 1; 58d4002b98SHong Zhang #endif 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60d4002b98SHong Zhang } 61d4002b98SHong Zhang 62d4002b98SHong Zhang #define MatSetValues_SeqSELL_A_Private(row, col, value, addv, orow, ocol) \ 63d4002b98SHong Zhang { \ 64d4002b98SHong Zhang if (col <= lastcol1) low1 = 0; \ 65d4002b98SHong Zhang else high1 = nrow1; \ 66d4002b98SHong Zhang lastcol1 = col; \ 67d4002b98SHong Zhang while (high1 - low1 > 5) { \ 68d4002b98SHong Zhang t = (low1 + high1) / 2; \ 694f8ff0b3SHong Zhang if (cp1[sliceheight * t] > col) high1 = t; \ 70d4002b98SHong Zhang else low1 = t; \ 71d4002b98SHong Zhang } \ 72d4002b98SHong Zhang for (_i = low1; _i < high1; _i++) { \ 734f8ff0b3SHong Zhang if (cp1[sliceheight * _i] > col) break; \ 744f8ff0b3SHong Zhang if (cp1[sliceheight * _i] == col) { \ 754f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp1[sliceheight * _i] += value; \ 764f8ff0b3SHong Zhang else vp1[sliceheight * _i] = value; \ 772d1451d4SHong Zhang inserted = PETSC_TRUE; \ 78d4002b98SHong Zhang goto a_noinsert; \ 79d4002b98SHong Zhang } \ 80d4002b98SHong Zhang } \ 819371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \ 829371c9d4SSatish Balay low1 = 0; \ 839371c9d4SSatish Balay high1 = nrow1; \ 849371c9d4SSatish Balay goto a_noinsert; \ 859371c9d4SSatish Balay } \ 869371c9d4SSatish Balay if (nonew == 1) { \ 879371c9d4SSatish Balay low1 = 0; \ 889371c9d4SSatish Balay high1 = nrow1; \ 899371c9d4SSatish Balay goto a_noinsert; \ 909371c9d4SSatish Balay } \ 9108401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \ 9207e43b41SHong Zhang MatSeqXSELLReallocateSELL(A, am, 1, nrow1, a->sliidx, a->sliceheight, row / sliceheight, row, col, a->colidx, a->val, cp1, vp1, nonew, MatScalar); \ 93d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 94d4002b98SHong Zhang for (ii = nrow1 - 1; ii >= _i; ii--) { \ 954f8ff0b3SHong Zhang cp1[sliceheight * (ii + 1)] = cp1[sliceheight * ii]; \ 964f8ff0b3SHong Zhang vp1[sliceheight * (ii + 1)] = vp1[sliceheight * ii]; \ 97d4002b98SHong Zhang } \ 984f8ff0b3SHong Zhang cp1[sliceheight * _i] = col; \ 994f8ff0b3SHong Zhang vp1[sliceheight * _i] = value; \ 1009371c9d4SSatish Balay a->nz++; \ 1019371c9d4SSatish Balay nrow1++; \ 1029371c9d4SSatish Balay A->nonzerostate++; \ 103d4002b98SHong Zhang a_noinsert:; \ 104d4002b98SHong Zhang a->rlen[row] = nrow1; \ 105d4002b98SHong Zhang } 106d4002b98SHong Zhang 107d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row, col, value, addv, orow, ocol) \ 108d4002b98SHong Zhang { \ 109d4002b98SHong Zhang if (col <= lastcol2) low2 = 0; \ 110d4002b98SHong Zhang else high2 = nrow2; \ 111d4002b98SHong Zhang lastcol2 = col; \ 112d4002b98SHong Zhang while (high2 - low2 > 5) { \ 113d4002b98SHong Zhang t = (low2 + high2) / 2; \ 1144f8ff0b3SHong Zhang if (cp2[sliceheight * t] > col) high2 = t; \ 115d4002b98SHong Zhang else low2 = t; \ 116d4002b98SHong Zhang } \ 117d4002b98SHong Zhang for (_i = low2; _i < high2; _i++) { \ 1184f8ff0b3SHong Zhang if (cp2[sliceheight * _i] > col) break; \ 1194f8ff0b3SHong Zhang if (cp2[sliceheight * _i] == col) { \ 1204f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp2[sliceheight * _i] += value; \ 1214f8ff0b3SHong Zhang else vp2[sliceheight * _i] = value; \ 1222d1451d4SHong Zhang inserted = PETSC_TRUE; \ 123d4002b98SHong Zhang goto b_noinsert; \ 124d4002b98SHong Zhang } \ 125d4002b98SHong Zhang } \ 1269371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \ 1279371c9d4SSatish Balay low2 = 0; \ 1289371c9d4SSatish Balay high2 = nrow2; \ 1299371c9d4SSatish Balay goto b_noinsert; \ 1309371c9d4SSatish Balay } \ 1319371c9d4SSatish Balay if (nonew == 1) { \ 1329371c9d4SSatish Balay low2 = 0; \ 1339371c9d4SSatish Balay high2 = nrow2; \ 1349371c9d4SSatish Balay goto b_noinsert; \ 1359371c9d4SSatish Balay } \ 13608401ef6SPierre Jolivet PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \ 13707e43b41SHong Zhang MatSeqXSELLReallocateSELL(B, bm, 1, nrow2, b->sliidx, b->sliceheight, row / sliceheight, row, col, b->colidx, b->val, cp2, vp2, nonew, MatScalar); \ 138d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 139d4002b98SHong Zhang for (ii = nrow2 - 1; ii >= _i; ii--) { \ 1404f8ff0b3SHong Zhang cp2[sliceheight * (ii + 1)] = cp2[sliceheight * ii]; \ 1414f8ff0b3SHong Zhang vp2[sliceheight * (ii + 1)] = vp2[sliceheight * ii]; \ 142d4002b98SHong Zhang } \ 1434f8ff0b3SHong Zhang cp2[sliceheight * _i] = col; \ 1444f8ff0b3SHong Zhang vp2[sliceheight * _i] = value; \ 1459371c9d4SSatish Balay b->nz++; \ 1469371c9d4SSatish Balay nrow2++; \ 1479371c9d4SSatish Balay B->nonzerostate++; \ 148d4002b98SHong Zhang b_noinsert:; \ 149d4002b98SHong Zhang b->rlen[row] = nrow2; \ 150d4002b98SHong Zhang } 151d4002b98SHong Zhang 15243b34f9dSJacob Faibussowitsch static PetscErrorCode MatSetValues_MPISELL(Mat mat, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode addv) 153d71ae5a4SJacob Faibussowitsch { 154d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 155d4002b98SHong Zhang PetscScalar value; 156d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend, shift1, shift2; 157d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 158d4002b98SHong Zhang PetscBool roworiented = sell->roworiented; 159d4002b98SHong Zhang 160d4002b98SHong Zhang /* Some Variables required in the macro */ 161d4002b98SHong Zhang Mat A = sell->A; 162d4002b98SHong Zhang Mat_SeqSELL *a = (Mat_SeqSELL *)A->data; 163d4002b98SHong Zhang PetscBool ignorezeroentries = a->ignorezeroentries, found; 164d4002b98SHong Zhang Mat B = sell->B; 165d4002b98SHong Zhang Mat_SeqSELL *b = (Mat_SeqSELL *)B->data; 16607e43b41SHong Zhang PetscInt *cp1, *cp2, ii, _i, nrow1, nrow2, low1, high1, low2, high2, t, lastcol1, lastcol2, sliceheight = a->sliceheight; 167d4002b98SHong Zhang MatScalar *vp1, *vp2; 168d4002b98SHong Zhang 169d4002b98SHong Zhang PetscFunctionBegin; 170d4002b98SHong Zhang for (i = 0; i < m; i++) { 171d4002b98SHong Zhang if (im[i] < 0) continue; 1726bdcaf15SBarry Smith PetscCheck(im[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, im[i], mat->rmap->N - 1); 173d4002b98SHong Zhang if (im[i] >= rstart && im[i] < rend) { 174d4002b98SHong Zhang row = im[i] - rstart; 175d4002b98SHong Zhang lastcol1 = -1; 17607e43b41SHong Zhang shift1 = a->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 1778e3a54c0SPierre Jolivet cp1 = PetscSafePointerPlusOffset(a->colidx, shift1); 1788e3a54c0SPierre Jolivet vp1 = PetscSafePointerPlusOffset(a->val, shift1); 179d4002b98SHong Zhang nrow1 = a->rlen[row]; 180d4002b98SHong Zhang low1 = 0; 181d4002b98SHong Zhang high1 = nrow1; 182d4002b98SHong Zhang lastcol2 = -1; 18307e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 1848e3a54c0SPierre Jolivet cp2 = PetscSafePointerPlusOffset(b->colidx, shift2); 1858e3a54c0SPierre Jolivet vp2 = PetscSafePointerPlusOffset(b->val, shift2); 186d4002b98SHong Zhang nrow2 = b->rlen[row]; 187d4002b98SHong Zhang low2 = 0; 188d4002b98SHong Zhang high2 = nrow2; 189d4002b98SHong Zhang 190d4002b98SHong Zhang for (j = 0; j < n; j++) { 191d4002b98SHong Zhang if (roworiented) value = v[i * n + j]; 192d4002b98SHong Zhang else value = v[i + j * m]; 193d4002b98SHong Zhang if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 194d4002b98SHong Zhang if (in[j] >= cstart && in[j] < cend) { 195d4002b98SHong Zhang col = in[j] - cstart; 196d4002b98SHong Zhang MatSetValue_SeqSELL_Private(A, row, col, value, addv, im[i], in[j], cp1, vp1, lastcol1, low1, high1); /* set one value */ 1972d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 1982d1451d4SHong Zhang if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) A->offloadmask = PETSC_OFFLOAD_CPU; 1992d1451d4SHong Zhang #endif 200f7d195e4SLawrence Mitchell } else if (in[j] < 0) { 201f7d195e4SLawrence Mitchell continue; 202f7d195e4SLawrence Mitchell } else { 203f7d195e4SLawrence Mitchell PetscCheck(in[j] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[j], mat->cmap->N - 1); 204d4002b98SHong Zhang if (mat->was_assembled) { 20548a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 206d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 207eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, in[j] + 1, 0, &col)); 208d4002b98SHong Zhang col--; 209d4002b98SHong Zhang #else 210d4002b98SHong Zhang col = sell->colmap[in[j]] - 1; 211d4002b98SHong Zhang #endif 212*f4f49eeaSPierre Jolivet if (col < 0 && !((Mat_SeqSELL *)sell->B->data)->nonew) { 2139566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(mat)); 214d4002b98SHong Zhang col = in[j]; 215d4002b98SHong Zhang /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */ 216d4002b98SHong Zhang B = sell->B; 217d4002b98SHong Zhang b = (Mat_SeqSELL *)B->data; 21807e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 219d4002b98SHong Zhang cp2 = b->colidx + shift2; 220d4002b98SHong Zhang vp2 = b->val + shift2; 221d4002b98SHong Zhang nrow2 = b->rlen[row]; 222d4002b98SHong Zhang low2 = 0; 223d4002b98SHong Zhang high2 = nrow2; 2242d1451d4SHong Zhang found = PETSC_FALSE; 225f7d195e4SLawrence Mitchell } else { 226f7d195e4SLawrence Mitchell PetscCheck(col >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", im[i], in[j]); 227f7d195e4SLawrence Mitchell } 228d4002b98SHong Zhang } else col = in[j]; 229d4002b98SHong Zhang MatSetValue_SeqSELL_Private(B, row, col, value, addv, im[i], in[j], cp2, vp2, lastcol2, low2, high2); /* set one value */ 2302d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 2312d1451d4SHong Zhang if (B->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) B->offloadmask = PETSC_OFFLOAD_CPU; 2322d1451d4SHong Zhang #endif 233d4002b98SHong Zhang } 234d4002b98SHong Zhang } 235d4002b98SHong Zhang } else { 23628b400f6SJacob Faibussowitsch PetscCheck(!mat->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", im[i]); 237d4002b98SHong Zhang if (!sell->donotstash) { 238d4002b98SHong Zhang mat->assembled = PETSC_FALSE; 239d4002b98SHong Zhang if (roworiented) { 2409566063dSJacob Faibussowitsch PetscCall(MatStashValuesRow_Private(&mat->stash, im[i], n, in, v + i * n, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 241d4002b98SHong Zhang } else { 2429566063dSJacob Faibussowitsch PetscCall(MatStashValuesCol_Private(&mat->stash, im[i], n, in, v + i, m, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 243d4002b98SHong Zhang } 244d4002b98SHong Zhang } 245d4002b98SHong Zhang } 246d4002b98SHong Zhang } 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 248d4002b98SHong Zhang } 249d4002b98SHong Zhang 250ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetValues_MPISELL(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 251d71ae5a4SJacob Faibussowitsch { 252d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 253d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend; 254d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 255d4002b98SHong Zhang 256d4002b98SHong Zhang PetscFunctionBegin; 257d4002b98SHong Zhang for (i = 0; i < m; i++) { 25854c59aa7SJacob Faibussowitsch if (idxm[i] < 0) continue; /* negative row */ 25954c59aa7SJacob Faibussowitsch PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 260d4002b98SHong Zhang if (idxm[i] >= rstart && idxm[i] < rend) { 261d4002b98SHong Zhang row = idxm[i] - rstart; 262d4002b98SHong Zhang for (j = 0; j < n; j++) { 26354c59aa7SJacob Faibussowitsch if (idxn[j] < 0) continue; /* negative column */ 26454c59aa7SJacob Faibussowitsch PetscCheck(idxn[j] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, idxn[j], mat->cmap->N - 1); 265d4002b98SHong Zhang if (idxn[j] >= cstart && idxn[j] < cend) { 266d4002b98SHong Zhang col = idxn[j] - cstart; 2679566063dSJacob Faibussowitsch PetscCall(MatGetValues(sell->A, 1, &row, 1, &col, v + i * n + j)); 268d4002b98SHong Zhang } else { 26948a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 270d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 271eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, idxn[j] + 1, 0, &col)); 272d4002b98SHong Zhang col--; 273d4002b98SHong Zhang #else 274d4002b98SHong Zhang col = sell->colmap[idxn[j]] - 1; 275d4002b98SHong Zhang #endif 276d4002b98SHong Zhang if ((col < 0) || (sell->garray[col] != idxn[j])) *(v + i * n + j) = 0.0; 27748a46eb9SPierre Jolivet else PetscCall(MatGetValues(sell->B, 1, &row, 1, &col, v + i * n + j)); 278d4002b98SHong Zhang } 279d4002b98SHong Zhang } 280d4002b98SHong Zhang } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only local values currently supported"); 281d4002b98SHong Zhang } 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 283d4002b98SHong Zhang } 284d4002b98SHong Zhang 285ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat, MatAssemblyType mode) 286d71ae5a4SJacob Faibussowitsch { 287d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 288d4002b98SHong Zhang PetscInt nstash, reallocs; 289d4002b98SHong Zhang 290d4002b98SHong Zhang PetscFunctionBegin; 2913ba16761SJacob Faibussowitsch if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 292d4002b98SHong Zhang 2939566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 2949566063dSJacob Faibussowitsch PetscCall(MatStashGetInfo_Private(&mat->stash, &nstash, &reallocs)); 2959566063dSJacob Faibussowitsch PetscCall(PetscInfo(sell->A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs)); 2963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 297d4002b98SHong Zhang } 298d4002b98SHong Zhang 299d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat, MatAssemblyType mode) 300d71ae5a4SJacob Faibussowitsch { 301d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 302d4002b98SHong Zhang PetscMPIInt n; 303d4002b98SHong Zhang PetscInt i, flg; 304d4002b98SHong Zhang PetscInt *row, *col; 305d4002b98SHong Zhang PetscScalar *val; 306d4002b98SHong Zhang PetscBool other_disassembled; 307d4002b98SHong Zhang /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */ 308d4002b98SHong Zhang PetscFunctionBegin; 309d4002b98SHong Zhang if (!sell->donotstash && !mat->nooffprocentries) { 310d4002b98SHong Zhang while (1) { 3119566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&mat->stash, &n, &row, &col, &val, &flg)); 312d4002b98SHong Zhang if (!flg) break; 313d4002b98SHong Zhang 314d4002b98SHong Zhang for (i = 0; i < n; i++) { /* assemble one by one */ 3159566063dSJacob Faibussowitsch PetscCall(MatSetValues_MPISELL(mat, 1, row + i, 1, col + i, val + i, mat->insertmode)); 316d4002b98SHong Zhang } 317d4002b98SHong Zhang } 3189566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&mat->stash)); 319d4002b98SHong Zhang } 3202d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3212d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU) sell->A->offloadmask = PETSC_OFFLOAD_CPU; 3222d1451d4SHong Zhang #endif 3239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->A, mode)); 3249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->A, mode)); 325d4002b98SHong Zhang 326d4002b98SHong Zhang /* 327d4002b98SHong Zhang determine if any processor has disassembled, if so we must 3286aad120cSJose E. Roman also disassemble ourselves, in order that we may reassemble. 329d4002b98SHong Zhang */ 330d4002b98SHong Zhang /* 331d4002b98SHong Zhang if nonzero structure of submatrix B cannot change then we know that 332d4002b98SHong Zhang no processor disassembled thus we can skip this stuff 333d4002b98SHong Zhang */ 334d4002b98SHong Zhang if (!((Mat_SeqSELL *)sell->B->data)->nonew) { 3355f9db2b2SJunchao Zhang PetscCall(MPIU_Allreduce(&mat->was_assembled, &other_disassembled, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 3362d1451d4SHong Zhang if (mat->was_assembled && !other_disassembled) PetscCall(MatDisAssemble_MPISELL(mat)); 337d4002b98SHong Zhang } 33848a46eb9SPierre Jolivet if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) PetscCall(MatSetUpMultiply_MPISELL(mat)); 3392d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3402d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU && sell->B->offloadmask != PETSC_OFFLOAD_UNALLOCATED) sell->B->offloadmask = PETSC_OFFLOAD_CPU; 3412d1451d4SHong Zhang #endif 3429566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->B, mode)); 3439566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->B, mode)); 3449566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 345f4259b30SLisandro Dalcin sell->rowvalues = NULL; 3469566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 347d4002b98SHong Zhang 348d4002b98SHong Zhang /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */ 349*f4f49eeaSPierre Jolivet if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL *)sell->A->data)->nonew) { 350d4002b98SHong Zhang PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate; 3511c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&state, &mat->nonzerostate, 1, MPIU_INT64, MPI_SUM, PetscObjectComm((PetscObject)mat))); 352d4002b98SHong Zhang } 3532d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3542d1451d4SHong Zhang mat->offloadmask = PETSC_OFFLOAD_BOTH; 3552d1451d4SHong Zhang #endif 3563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 357d4002b98SHong Zhang } 358d4002b98SHong Zhang 359ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_MPISELL(Mat A) 360d71ae5a4SJacob Faibussowitsch { 361d4002b98SHong Zhang Mat_MPISELL *l = (Mat_MPISELL *)A->data; 362d4002b98SHong Zhang 363d4002b98SHong Zhang PetscFunctionBegin; 3649566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->A)); 3659566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->B)); 3663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 367d4002b98SHong Zhang } 368d4002b98SHong Zhang 369ba38deedSJacob Faibussowitsch static PetscErrorCode MatMult_MPISELL(Mat A, Vec xx, Vec yy) 370d71ae5a4SJacob Faibussowitsch { 371d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 372d4002b98SHong Zhang PetscInt nt; 373d4002b98SHong Zhang 374d4002b98SHong Zhang PetscFunctionBegin; 3759566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(xx, &nt)); 37608401ef6SPierre Jolivet PetscCheck(nt == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible partition of A (%" PetscInt_FMT ") and xx (%" PetscInt_FMT ")", A->cmap->n, nt); 3779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3789566063dSJacob Faibussowitsch PetscCall((*a->A->ops->mult)(a->A, xx, yy)); 3799566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3809566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, yy, yy)); 3813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 382d4002b98SHong Zhang } 383d4002b98SHong Zhang 384fa078d78SJacob Faibussowitsch static PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A, Vec bb, Vec xx) 385d71ae5a4SJacob Faibussowitsch { 386d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 387d4002b98SHong Zhang 388d4002b98SHong Zhang PetscFunctionBegin; 3899566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(a->A, bb, xx)); 3903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 391d4002b98SHong Zhang } 392d4002b98SHong Zhang 393ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 394d71ae5a4SJacob Faibussowitsch { 395d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 396d4002b98SHong Zhang 397d4002b98SHong Zhang PetscFunctionBegin; 3989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3999566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multadd)(a->A, xx, yy, zz)); 4009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 4019566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, zz, zz)); 4023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 403d4002b98SHong Zhang } 404d4002b98SHong Zhang 405ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultTranspose_MPISELL(Mat A, Vec xx, Vec yy) 406d71ae5a4SJacob Faibussowitsch { 407d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 408d4002b98SHong Zhang 409d4002b98SHong Zhang PetscFunctionBegin; 410d4002b98SHong Zhang /* do nondiagonal part */ 4119566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 412d4002b98SHong Zhang /* do local part */ 4139566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtranspose)(a->A, xx, yy)); 414a29b4eb7SJunchao Zhang /* add partial results together */ 4159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 418d4002b98SHong Zhang } 419d4002b98SHong Zhang 420ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsTranspose_MPISELL(Mat Amat, Mat Bmat, PetscReal tol, PetscBool *f) 421d71ae5a4SJacob Faibussowitsch { 422d4002b98SHong Zhang MPI_Comm comm; 423d4002b98SHong Zhang Mat_MPISELL *Asell = (Mat_MPISELL *)Amat->data, *Bsell; 424d4002b98SHong Zhang Mat Adia = Asell->A, Bdia, Aoff, Boff, *Aoffs, *Boffs; 425d4002b98SHong Zhang IS Me, Notme; 426d4002b98SHong Zhang PetscInt M, N, first, last, *notme, i; 427d4002b98SHong Zhang PetscMPIInt size; 428d4002b98SHong Zhang 429d4002b98SHong Zhang PetscFunctionBegin; 430d4002b98SHong Zhang /* Easy test: symmetric diagonal block */ 4319371c9d4SSatish Balay Bsell = (Mat_MPISELL *)Bmat->data; 4329371c9d4SSatish Balay Bdia = Bsell->A; 4339566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Adia, Bdia, tol, f)); 4343ba16761SJacob Faibussowitsch if (!*f) PetscFunctionReturn(PETSC_SUCCESS); 4359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm)); 4369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 4373ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 438d4002b98SHong Zhang 439d4002b98SHong Zhang /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */ 4409566063dSJacob Faibussowitsch PetscCall(MatGetSize(Amat, &M, &N)); 4419566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &first, &last)); 4429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(N - last + first, ¬me)); 443d4002b98SHong Zhang for (i = 0; i < first; i++) notme[i] = i; 444d4002b98SHong Zhang for (i = last; i < M; i++) notme[i - last + first] = i; 4459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(MPI_COMM_SELF, N - last + first, notme, PETSC_COPY_VALUES, &Notme)); 4469566063dSJacob Faibussowitsch PetscCall(ISCreateStride(MPI_COMM_SELF, last - first, first, 1, &Me)); 4479566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Amat, 1, &Me, &Notme, MAT_INITIAL_MATRIX, &Aoffs)); 448d4002b98SHong Zhang Aoff = Aoffs[0]; 4499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Bmat, 1, &Notme, &Me, MAT_INITIAL_MATRIX, &Boffs)); 450d4002b98SHong Zhang Boff = Boffs[0]; 4519566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Aoff, Boff, tol, f)); 4529566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Aoffs)); 4539566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Boffs)); 4549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Me)); 4559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Notme)); 4569566063dSJacob Faibussowitsch PetscCall(PetscFree(notme)); 4573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 458d4002b98SHong Zhang } 459d4002b98SHong Zhang 460ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 461d71ae5a4SJacob Faibussowitsch { 462d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 463d4002b98SHong Zhang 464d4002b98SHong Zhang PetscFunctionBegin; 465d4002b98SHong Zhang /* do nondiagonal part */ 4669566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 467d4002b98SHong Zhang /* do local part */ 4689566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtransposeadd)(a->A, xx, yy, zz)); 469e4a140f6SJunchao Zhang /* add partial results together */ 4709566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4719566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 473d4002b98SHong Zhang } 474d4002b98SHong Zhang 475d4002b98SHong Zhang /* 476d4002b98SHong Zhang This only works correctly for square matrices where the subblock A->A is the 477d4002b98SHong Zhang diagonal block 478d4002b98SHong Zhang */ 479ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_MPISELL(Mat A, Vec v) 480d71ae5a4SJacob Faibussowitsch { 481d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 482d4002b98SHong Zhang 483d4002b98SHong Zhang PetscFunctionBegin; 48408401ef6SPierre Jolivet PetscCheck(A->rmap->N == A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Supports only square matrix where A->A is diag block"); 485aed4548fSBarry Smith PetscCheck(A->rmap->rstart == A->cmap->rstart && A->rmap->rend == A->cmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "row partition must equal col partition"); 4869566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(a->A, v)); 4873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 488d4002b98SHong Zhang } 489d4002b98SHong Zhang 490ba38deedSJacob Faibussowitsch static PetscErrorCode MatScale_MPISELL(Mat A, PetscScalar aa) 491d71ae5a4SJacob Faibussowitsch { 492d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 493d4002b98SHong Zhang 494d4002b98SHong Zhang PetscFunctionBegin; 4959566063dSJacob Faibussowitsch PetscCall(MatScale(a->A, aa)); 4969566063dSJacob Faibussowitsch PetscCall(MatScale(a->B, aa)); 4973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 498d4002b98SHong Zhang } 499d4002b98SHong Zhang 500d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPISELL(Mat mat) 501d71ae5a4SJacob Faibussowitsch { 502d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 503d4002b98SHong Zhang 504d4002b98SHong Zhang PetscFunctionBegin; 5053ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)mat, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT, mat->rmap->N, mat->cmap->N)); 5069566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&mat->stash)); 5079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 5089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->A)); 5099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->B)); 510d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 511eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&sell->colmap)); 512d4002b98SHong Zhang #else 5139566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->colmap)); 514d4002b98SHong Zhang #endif 5159566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->garray)); 5169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->lvec)); 5179566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sell->Mvctx)); 5189566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 5199566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->ld)); 5209566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->data)); 521d4002b98SHong Zhang 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL)); 5239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatStoreValues_C", NULL)); 5249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatRetrieveValues_C", NULL)); 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatIsTranspose_C", NULL)); 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMPISELLSetPreallocation_C", NULL)); 5279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpiaij_C", NULL)); 528b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA) 529b5917f1bSHong Zhang PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpisellcuda_C", NULL)); 530b5917f1bSHong Zhang #endif 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalScaleLocal_C", NULL)); 5323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 533d4002b98SHong Zhang } 534d4002b98SHong Zhang 535d4002b98SHong Zhang #include <petscdraw.h> 536ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat, PetscViewer viewer) 537d71ae5a4SJacob Faibussowitsch { 538d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 539d4002b98SHong Zhang PetscMPIInt rank = sell->rank, size = sell->size; 540d4002b98SHong Zhang PetscBool isdraw, iascii, isbinary; 541d4002b98SHong Zhang PetscViewer sviewer; 542d4002b98SHong Zhang PetscViewerFormat format; 543d4002b98SHong Zhang 544d4002b98SHong Zhang PetscFunctionBegin; 5459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 548d4002b98SHong Zhang if (iascii) { 5499566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 550d4002b98SHong Zhang if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 551d4002b98SHong Zhang MatInfo info; 5526335e310SSatish Balay PetscInt *inodes; 553d4002b98SHong Zhang 5549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 5559566063dSJacob Faibussowitsch PetscCall(MatGetInfo(mat, MAT_LOCAL, &info)); 5569566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, NULL, &inodes, NULL)); 5579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 558d4002b98SHong Zhang if (!inodes) { 5599371c9d4SSatish Balay PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", not using I-node routines\n", rank, mat->rmap->n, (PetscInt)info.nz_used, 5609371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 561d4002b98SHong Zhang } else { 5629371c9d4SSatish Balay PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", using I-node routines\n", rank, mat->rmap->n, (PetscInt)info.nz_used, 5639371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 564d4002b98SHong Zhang } 5659566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->A, MAT_LOCAL, &info)); 5669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] on-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5679566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->B, MAT_LOCAL, &info)); 5689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] off-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5699566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 5719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Information on VecScatter used in matrix-vector product: \n")); 5729566063dSJacob Faibussowitsch PetscCall(VecScatterView(sell->Mvctx, viewer)); 5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 574d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_INFO) { 575d4002b98SHong Zhang PetscInt inodecount, inodelimit, *inodes; 5769566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, &inodecount, &inodes, &inodelimit)); 577d4002b98SHong Zhang if (inodes) { 5789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n", inodecount, inodelimit)); 579d4002b98SHong Zhang } else { 5809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "not using I-node (on process 0) routines\n")); 581d4002b98SHong Zhang } 5823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 583d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 5843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 585d4002b98SHong Zhang } 586d4002b98SHong Zhang } else if (isbinary) { 587d4002b98SHong Zhang if (size == 1) { 5889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sell->A, ((PetscObject)mat)->name)); 5899566063dSJacob Faibussowitsch PetscCall(MatView(sell->A, viewer)); 590d4002b98SHong Zhang } else { 5919566063dSJacob Faibussowitsch /* PetscCall(MatView_MPISELL_Binary(mat,viewer)); */ 592d4002b98SHong Zhang } 5933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 594d4002b98SHong Zhang } else if (isdraw) { 595d4002b98SHong Zhang PetscDraw draw; 596d4002b98SHong Zhang PetscBool isnull; 5979566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5989566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 5993ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 600d4002b98SHong Zhang } 601d4002b98SHong Zhang 602d4002b98SHong Zhang { 603d4002b98SHong Zhang /* assemble the entire matrix onto first processor. */ 604d4002b98SHong Zhang Mat A; 605d4002b98SHong Zhang Mat_SeqSELL *Aloc; 606d4002b98SHong Zhang PetscInt M = mat->rmap->N, N = mat->cmap->N, *acolidx, row, col, i, j; 607d4002b98SHong Zhang MatScalar *aval; 608d4002b98SHong Zhang PetscBool isnonzero; 609d4002b98SHong Zhang 6109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &A)); 611dd400576SPatrick Sanan if (rank == 0) { 6129566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, M, N, M, N)); 613d4002b98SHong Zhang } else { 6149566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, 0, 0, M, N)); 615d4002b98SHong Zhang } 616d4002b98SHong Zhang /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */ 6179566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPISELL)); 6189566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, 0, NULL, 0, NULL)); 6199566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 620d4002b98SHong Zhang 621d4002b98SHong Zhang /* copy over the A part */ 622d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->A->data; 6239371c9d4SSatish Balay acolidx = Aloc->colidx; 6249371c9d4SSatish Balay aval = Aloc->val; 625d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { /* loop over slices */ 626d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) { 62707e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]); 628d4002b98SHong Zhang if (isnonzero) { /* check the mask bit */ 62907e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart; 630d4002b98SHong Zhang col = *acolidx + mat->rmap->rstart; 6319566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES)); 632d4002b98SHong Zhang } 6339371c9d4SSatish Balay aval++; 6349371c9d4SSatish Balay acolidx++; 635d4002b98SHong Zhang } 636d4002b98SHong Zhang } 637d4002b98SHong Zhang 638d4002b98SHong Zhang /* copy over the B part */ 639d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->B->data; 6409371c9d4SSatish Balay acolidx = Aloc->colidx; 6419371c9d4SSatish Balay aval = Aloc->val; 642d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { 643d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) { 64407e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]); 645d4002b98SHong Zhang if (isnonzero) { 64607e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart; 647d4002b98SHong Zhang col = sell->garray[*acolidx]; 6489566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES)); 649d4002b98SHong Zhang } 6509371c9d4SSatish Balay aval++; 6519371c9d4SSatish Balay acolidx++; 652d4002b98SHong Zhang } 653d4002b98SHong Zhang } 654d4002b98SHong Zhang 6559566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 6569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 657d4002b98SHong Zhang /* 658d4002b98SHong Zhang Everyone has to call to draw the matrix since the graphics waits are 659d4002b98SHong Zhang synchronized across all processors that share the PetscDraw object 660d4002b98SHong Zhang */ 6619566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 662dd400576SPatrick Sanan if (rank == 0) { 663*f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)((Mat_MPISELL *)A->data)->A, ((PetscObject)mat)->name)); 664*f4f49eeaSPierre Jolivet PetscCall(MatView_SeqSELL(((Mat_MPISELL *)A->data)->A, sviewer)); 665d4002b98SHong Zhang } 6669566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 6679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 668d4002b98SHong Zhang } 6693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 670d4002b98SHong Zhang } 671d4002b98SHong Zhang 672ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_MPISELL(Mat mat, PetscViewer viewer) 673d71ae5a4SJacob Faibussowitsch { 674d4002b98SHong Zhang PetscBool iascii, isdraw, issocket, isbinary; 675d4002b98SHong Zhang 676d4002b98SHong Zhang PetscFunctionBegin; 6779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 6789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 6809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSOCKET, &issocket)); 68148a46eb9SPierre Jolivet if (iascii || isdraw || isbinary || issocket) PetscCall(MatView_MPISELL_ASCIIorDraworSocket(mat, viewer)); 6823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 683d4002b98SHong Zhang } 684d4002b98SHong Zhang 685ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetGhosts_MPISELL(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 686d71ae5a4SJacob Faibussowitsch { 687d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 688d4002b98SHong Zhang 689d4002b98SHong Zhang PetscFunctionBegin; 6909566063dSJacob Faibussowitsch PetscCall(MatGetSize(sell->B, NULL, nghosts)); 691d4002b98SHong Zhang if (ghosts) *ghosts = sell->garray; 6923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 693d4002b98SHong Zhang } 694d4002b98SHong Zhang 695ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetInfo_MPISELL(Mat matin, MatInfoType flag, MatInfo *info) 696d71ae5a4SJacob Faibussowitsch { 697d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 698d4002b98SHong Zhang Mat A = mat->A, B = mat->B; 6993966268fSBarry Smith PetscLogDouble isend[5], irecv[5]; 700d4002b98SHong Zhang 701d4002b98SHong Zhang PetscFunctionBegin; 702d4002b98SHong Zhang info->block_size = 1.0; 7039566063dSJacob Faibussowitsch PetscCall(MatGetInfo(A, MAT_LOCAL, info)); 704d4002b98SHong Zhang 7059371c9d4SSatish Balay isend[0] = info->nz_used; 7069371c9d4SSatish Balay isend[1] = info->nz_allocated; 7079371c9d4SSatish Balay isend[2] = info->nz_unneeded; 7089371c9d4SSatish Balay isend[3] = info->memory; 7099371c9d4SSatish Balay isend[4] = info->mallocs; 710d4002b98SHong Zhang 7119566063dSJacob Faibussowitsch PetscCall(MatGetInfo(B, MAT_LOCAL, info)); 712d4002b98SHong Zhang 7139371c9d4SSatish Balay isend[0] += info->nz_used; 7149371c9d4SSatish Balay isend[1] += info->nz_allocated; 7159371c9d4SSatish Balay isend[2] += info->nz_unneeded; 7169371c9d4SSatish Balay isend[3] += info->memory; 7179371c9d4SSatish Balay isend[4] += info->mallocs; 718d4002b98SHong Zhang if (flag == MAT_LOCAL) { 719d4002b98SHong Zhang info->nz_used = isend[0]; 720d4002b98SHong Zhang info->nz_allocated = isend[1]; 721d4002b98SHong Zhang info->nz_unneeded = isend[2]; 722d4002b98SHong Zhang info->memory = isend[3]; 723d4002b98SHong Zhang info->mallocs = isend[4]; 724d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_MAX) { 7251c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)matin))); 726d4002b98SHong Zhang 727d4002b98SHong Zhang info->nz_used = irecv[0]; 728d4002b98SHong Zhang info->nz_allocated = irecv[1]; 729d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 730d4002b98SHong Zhang info->memory = irecv[3]; 731d4002b98SHong Zhang info->mallocs = irecv[4]; 732d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_SUM) { 7331c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)matin))); 734d4002b98SHong Zhang 735d4002b98SHong Zhang info->nz_used = irecv[0]; 736d4002b98SHong Zhang info->nz_allocated = irecv[1]; 737d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 738d4002b98SHong Zhang info->memory = irecv[3]; 739d4002b98SHong Zhang info->mallocs = irecv[4]; 740d4002b98SHong Zhang } 741d4002b98SHong Zhang info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 742d4002b98SHong Zhang info->fill_ratio_needed = 0; 743d4002b98SHong Zhang info->factor_mallocs = 0; 7443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 745d4002b98SHong Zhang } 746d4002b98SHong Zhang 74743b34f9dSJacob Faibussowitsch static PetscErrorCode MatSetOption_MPISELL(Mat A, MatOption op, PetscBool flg) 748d71ae5a4SJacob Faibussowitsch { 749d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 750d4002b98SHong Zhang 751d4002b98SHong Zhang PetscFunctionBegin; 752d4002b98SHong Zhang switch (op) { 753d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATIONS: 754d4002b98SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR: 755d4002b98SHong Zhang case MAT_UNUSED_NONZERO_LOCATION_ERR: 756d4002b98SHong Zhang case MAT_KEEP_NONZERO_PATTERN: 757d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR: 758d4002b98SHong Zhang case MAT_USE_INODES: 759d4002b98SHong Zhang case MAT_IGNORE_ZERO_ENTRIES: 760d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7619566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7629566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 763d4002b98SHong Zhang break; 764d4002b98SHong Zhang case MAT_ROW_ORIENTED: 765d4002b98SHong Zhang MatCheckPreallocated(A, 1); 766d4002b98SHong Zhang a->roworiented = flg; 767d4002b98SHong Zhang 7689566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7699566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 770d4002b98SHong Zhang break; 7718c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 772d71ae5a4SJacob Faibussowitsch case MAT_SORTED_FULL: 773d71ae5a4SJacob Faibussowitsch PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); 774d71ae5a4SJacob Faibussowitsch break; 775d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_OFF_PROC_ENTRIES: 776d71ae5a4SJacob Faibussowitsch a->donotstash = flg; 777d71ae5a4SJacob Faibussowitsch break; 778d4002b98SHong Zhang case MAT_SPD: 779d71ae5a4SJacob Faibussowitsch case MAT_SPD_ETERNAL: 780d71ae5a4SJacob Faibussowitsch break; 781d4002b98SHong Zhang case MAT_SYMMETRIC: 782d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7839566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 784d4002b98SHong Zhang break; 785d4002b98SHong Zhang case MAT_STRUCTURALLY_SYMMETRIC: 786d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7879566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 788d4002b98SHong Zhang break; 789d4002b98SHong Zhang case MAT_HERMITIAN: 790d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7919566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 792d4002b98SHong Zhang break; 793d4002b98SHong Zhang case MAT_SYMMETRY_ETERNAL: 794d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7959566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 796d4002b98SHong Zhang break; 797b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 798b94d7dedSBarry Smith MatCheckPreallocated(A, 1); 799b94d7dedSBarry Smith PetscCall(MatSetOption(a->A, op, flg)); 800b94d7dedSBarry Smith break; 801d71ae5a4SJacob Faibussowitsch default: 802d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 803d4002b98SHong Zhang } 8043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 805d4002b98SHong Zhang } 806d4002b98SHong Zhang 807ba38deedSJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_MPISELL(Mat mat, Vec ll, Vec rr) 808d71ae5a4SJacob Faibussowitsch { 809d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 810d4002b98SHong Zhang Mat a = sell->A, b = sell->B; 811d4002b98SHong Zhang PetscInt s1, s2, s3; 812d4002b98SHong Zhang 813d4002b98SHong Zhang PetscFunctionBegin; 8149566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &s2, &s3)); 815d4002b98SHong Zhang if (rr) { 8169566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &s1)); 81708401ef6SPierre Jolivet PetscCheck(s1 == s3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "right vector non-conforming local size"); 818d4002b98SHong Zhang /* Overlap communication with computation. */ 8199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 820d4002b98SHong Zhang } 821d4002b98SHong Zhang if (ll) { 8229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &s1)); 82308401ef6SPierre Jolivet PetscCheck(s1 == s2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "left vector non-conforming local size"); 824dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, ll, NULL); 825d4002b98SHong Zhang } 826d4002b98SHong Zhang /* scale the diagonal block */ 827dbbe0bcdSBarry Smith PetscUseTypeMethod(a, diagonalscale, ll, rr); 828d4002b98SHong Zhang 829d4002b98SHong Zhang if (rr) { 830d4002b98SHong Zhang /* Do a scatter end and then right scale the off-diagonal block */ 8319566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 832dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, NULL, sell->lvec); 833d4002b98SHong Zhang } 8343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 835d4002b98SHong Zhang } 836d4002b98SHong Zhang 837ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetUnfactored_MPISELL(Mat A) 838d71ae5a4SJacob Faibussowitsch { 839d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 840d4002b98SHong Zhang 841d4002b98SHong Zhang PetscFunctionBegin; 8429566063dSJacob Faibussowitsch PetscCall(MatSetUnfactored(a->A)); 8433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 844d4002b98SHong Zhang } 845d4002b98SHong Zhang 846ba38deedSJacob Faibussowitsch static PetscErrorCode MatEqual_MPISELL(Mat A, Mat B, PetscBool *flag) 847d71ae5a4SJacob Faibussowitsch { 848d4002b98SHong Zhang Mat_MPISELL *matB = (Mat_MPISELL *)B->data, *matA = (Mat_MPISELL *)A->data; 849d4002b98SHong Zhang Mat a, b, c, d; 850d4002b98SHong Zhang PetscBool flg; 851d4002b98SHong Zhang 852d4002b98SHong Zhang PetscFunctionBegin; 8539371c9d4SSatish Balay a = matA->A; 8549371c9d4SSatish Balay b = matA->B; 8559371c9d4SSatish Balay c = matB->A; 8569371c9d4SSatish Balay d = matB->B; 857d4002b98SHong Zhang 8589566063dSJacob Faibussowitsch PetscCall(MatEqual(a, c, &flg)); 85948a46eb9SPierre Jolivet if (flg) PetscCall(MatEqual(b, d, &flg)); 8601c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&flg, flag, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 8613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 862d4002b98SHong Zhang } 863d4002b98SHong Zhang 864ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_MPISELL(Mat A, Mat B, MatStructure str) 865d71ae5a4SJacob Faibussowitsch { 866d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 867d4002b98SHong Zhang Mat_MPISELL *b = (Mat_MPISELL *)B->data; 868d4002b98SHong Zhang 869d4002b98SHong Zhang PetscFunctionBegin; 870d4002b98SHong Zhang /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 871d4002b98SHong Zhang if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 872d4002b98SHong Zhang /* because of the column compression in the off-processor part of the matrix a->B, 873d4002b98SHong Zhang the number of columns in a->B and b->B may be different, hence we cannot call 874d4002b98SHong Zhang the MatCopy() directly on the two parts. If need be, we can provide a more 875d4002b98SHong Zhang efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 876d4002b98SHong Zhang then copying the submatrices */ 8779566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 878d4002b98SHong Zhang } else { 8799566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 8809566063dSJacob Faibussowitsch PetscCall(MatCopy(a->B, b->B, str)); 881d4002b98SHong Zhang } 8823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 883d4002b98SHong Zhang } 884d4002b98SHong Zhang 885ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetUp_MPISELL(Mat A) 886d71ae5a4SJacob Faibussowitsch { 887d4002b98SHong Zhang PetscFunctionBegin; 8889566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 8893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 890d4002b98SHong Zhang } 891d4002b98SHong Zhang 892ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_MPISELL(Mat mat) 893d71ae5a4SJacob Faibussowitsch { 8945f80ce2aSJacob Faibussowitsch PetscFunctionBegin; 8955f80ce2aSJacob Faibussowitsch if (PetscDefined(USE_COMPLEX)) { 896d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 897d4002b98SHong Zhang 8989566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->A)); 8999566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->B)); 9005f80ce2aSJacob Faibussowitsch } 9013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 902d4002b98SHong Zhang } 903d4002b98SHong Zhang 904ba38deedSJacob Faibussowitsch static PetscErrorCode MatRealPart_MPISELL(Mat A) 905d71ae5a4SJacob Faibussowitsch { 906d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 907d4002b98SHong Zhang 908d4002b98SHong Zhang PetscFunctionBegin; 9099566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->A)); 9109566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->B)); 9113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 912d4002b98SHong Zhang } 913d4002b98SHong Zhang 914ba38deedSJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_MPISELL(Mat A) 915d71ae5a4SJacob Faibussowitsch { 916d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 917d4002b98SHong Zhang 918d4002b98SHong Zhang PetscFunctionBegin; 9199566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->A)); 9209566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->B)); 9213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 922d4002b98SHong Zhang } 923d4002b98SHong Zhang 924ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A, const PetscScalar **values) 925d71ae5a4SJacob Faibussowitsch { 926d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 927d4002b98SHong Zhang 928d4002b98SHong Zhang PetscFunctionBegin; 9299566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(a->A, values)); 930d4002b98SHong Zhang A->factorerrortype = a->A->factorerrortype; 9313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 932d4002b98SHong Zhang } 933d4002b98SHong Zhang 934d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_MPISELL(Mat x, PetscRandom rctx) 935d71ae5a4SJacob Faibussowitsch { 936d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)x->data; 937d4002b98SHong Zhang 938d4002b98SHong Zhang PetscFunctionBegin; 9399566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->A, rctx)); 9409566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->B, rctx)); 9419566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 9429566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 944d4002b98SHong Zhang } 945d4002b98SHong Zhang 94643b34f9dSJacob Faibussowitsch static PetscErrorCode MatSetFromOptions_MPISELL(Mat A, PetscOptionItems *PetscOptionsObject) 947d71ae5a4SJacob Faibussowitsch { 948d4002b98SHong Zhang PetscFunctionBegin; 949d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MPISELL options"); 950d0609cedSBarry Smith PetscOptionsHeadEnd(); 9513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 952d4002b98SHong Zhang } 953d4002b98SHong Zhang 954ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_MPISELL(Mat Y, PetscScalar a) 955d71ae5a4SJacob Faibussowitsch { 956d4002b98SHong Zhang Mat_MPISELL *msell = (Mat_MPISELL *)Y->data; 957d4002b98SHong Zhang Mat_SeqSELL *sell = (Mat_SeqSELL *)msell->A->data; 958d4002b98SHong Zhang 959d4002b98SHong Zhang PetscFunctionBegin; 960d4002b98SHong Zhang if (!Y->preallocated) { 9619566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(Y, 1, NULL, 0, NULL)); 962d4002b98SHong Zhang } else if (!sell->nz) { 963d4002b98SHong Zhang PetscInt nonew = sell->nonew; 9649566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(msell->A, 1, NULL)); 965d4002b98SHong Zhang sell->nonew = nonew; 966d4002b98SHong Zhang } 9679566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 9683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 969d4002b98SHong Zhang } 970d4002b98SHong Zhang 971ba38deedSJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_MPISELL(Mat A, PetscBool *missing, PetscInt *d) 972d71ae5a4SJacob Faibussowitsch { 973d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 974d4002b98SHong Zhang 975d4002b98SHong Zhang PetscFunctionBegin; 97608401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only works for square matrices"); 9779566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(a->A, missing, d)); 978d4002b98SHong Zhang if (d) { 979d4002b98SHong Zhang PetscInt rstart; 9809566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 981d4002b98SHong Zhang *d += rstart; 982d4002b98SHong Zhang } 9833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 984d4002b98SHong Zhang } 985d4002b98SHong Zhang 986ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A, Mat *a) 987d71ae5a4SJacob Faibussowitsch { 988d4002b98SHong Zhang PetscFunctionBegin; 989d4002b98SHong Zhang *a = ((Mat_MPISELL *)A->data)->A; 9903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 991d4002b98SHong Zhang } 992d4002b98SHong Zhang 99343b34f9dSJacob Faibussowitsch static PetscErrorCode MatStoreValues_MPISELL(Mat mat) 99443b34f9dSJacob Faibussowitsch { 99543b34f9dSJacob Faibussowitsch Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 99643b34f9dSJacob Faibussowitsch 99743b34f9dSJacob Faibussowitsch PetscFunctionBegin; 99843b34f9dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->A)); 99943b34f9dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->B)); 100043b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100143b34f9dSJacob Faibussowitsch } 100243b34f9dSJacob Faibussowitsch 100343b34f9dSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_MPISELL(Mat mat) 100443b34f9dSJacob Faibussowitsch { 100543b34f9dSJacob Faibussowitsch Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 100643b34f9dSJacob Faibussowitsch 100743b34f9dSJacob Faibussowitsch PetscFunctionBegin; 100843b34f9dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->A)); 100943b34f9dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->B)); 101043b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101143b34f9dSJacob Faibussowitsch } 101243b34f9dSJacob Faibussowitsch 101343b34f9dSJacob Faibussowitsch static PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[]) 101443b34f9dSJacob Faibussowitsch { 101543b34f9dSJacob Faibussowitsch Mat_MPISELL *b; 101643b34f9dSJacob Faibussowitsch 101743b34f9dSJacob Faibussowitsch PetscFunctionBegin; 101843b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 101943b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 102043b34f9dSJacob Faibussowitsch b = (Mat_MPISELL *)B->data; 102143b34f9dSJacob Faibussowitsch 102243b34f9dSJacob Faibussowitsch if (!B->preallocated) { 102343b34f9dSJacob Faibussowitsch /* Explicitly create 2 MATSEQSELL matrices. */ 102443b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->A)); 102543b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(b->A, B->rmap->n, B->cmap->n, B->rmap->n, B->cmap->n)); 102643b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->A, B, B)); 102743b34f9dSJacob Faibussowitsch PetscCall(MatSetType(b->A, MATSEQSELL)); 102843b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->B)); 102943b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(b->B, B->rmap->n, B->cmap->N, B->rmap->n, B->cmap->N)); 103043b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->B, B, B)); 103143b34f9dSJacob Faibussowitsch PetscCall(MatSetType(b->B, MATSEQSELL)); 103243b34f9dSJacob Faibussowitsch } 103343b34f9dSJacob Faibussowitsch 103443b34f9dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->A, d_rlenmax, d_rlen)); 103543b34f9dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->B, o_rlenmax, o_rlen)); 103643b34f9dSJacob Faibussowitsch B->preallocated = PETSC_TRUE; 103743b34f9dSJacob Faibussowitsch B->was_assembled = PETSC_FALSE; 103843b34f9dSJacob Faibussowitsch /* 103943b34f9dSJacob Faibussowitsch critical for MatAssemblyEnd to work. 104043b34f9dSJacob Faibussowitsch MatAssemblyBegin checks it to set up was_assembled 104143b34f9dSJacob Faibussowitsch and MatAssemblyEnd checks was_assembled to determine whether to build garray 104243b34f9dSJacob Faibussowitsch */ 104343b34f9dSJacob Faibussowitsch B->assembled = PETSC_FALSE; 104443b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 104543b34f9dSJacob Faibussowitsch } 104643b34f9dSJacob Faibussowitsch 104743b34f9dSJacob Faibussowitsch static PetscErrorCode MatDuplicate_MPISELL(Mat matin, MatDuplicateOption cpvalues, Mat *newmat) 104843b34f9dSJacob Faibussowitsch { 104943b34f9dSJacob Faibussowitsch Mat mat; 105043b34f9dSJacob Faibussowitsch Mat_MPISELL *a, *oldmat = (Mat_MPISELL *)matin->data; 105143b34f9dSJacob Faibussowitsch 105243b34f9dSJacob Faibussowitsch PetscFunctionBegin; 105343b34f9dSJacob Faibussowitsch *newmat = NULL; 105443b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)matin), &mat)); 105543b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, matin->rmap->n, matin->cmap->n, matin->rmap->N, matin->cmap->N)); 105643b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(mat, matin, matin)); 105743b34f9dSJacob Faibussowitsch PetscCall(MatSetType(mat, ((PetscObject)matin)->type_name)); 105843b34f9dSJacob Faibussowitsch a = (Mat_MPISELL *)mat->data; 105943b34f9dSJacob Faibussowitsch 106043b34f9dSJacob Faibussowitsch mat->factortype = matin->factortype; 106143b34f9dSJacob Faibussowitsch mat->assembled = PETSC_TRUE; 106243b34f9dSJacob Faibussowitsch mat->insertmode = NOT_SET_VALUES; 106343b34f9dSJacob Faibussowitsch mat->preallocated = PETSC_TRUE; 106443b34f9dSJacob Faibussowitsch 106543b34f9dSJacob Faibussowitsch a->size = oldmat->size; 106643b34f9dSJacob Faibussowitsch a->rank = oldmat->rank; 106743b34f9dSJacob Faibussowitsch a->donotstash = oldmat->donotstash; 106843b34f9dSJacob Faibussowitsch a->roworiented = oldmat->roworiented; 106943b34f9dSJacob Faibussowitsch a->rowindices = NULL; 107043b34f9dSJacob Faibussowitsch a->rowvalues = NULL; 107143b34f9dSJacob Faibussowitsch a->getrowactive = PETSC_FALSE; 107243b34f9dSJacob Faibussowitsch 107343b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->rmap, &mat->rmap)); 107443b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->cmap, &mat->cmap)); 107543b34f9dSJacob Faibussowitsch 107643b34f9dSJacob Faibussowitsch if (oldmat->colmap) { 107743b34f9dSJacob Faibussowitsch #if defined(PETSC_USE_CTABLE) 107843b34f9dSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(oldmat->colmap, &a->colmap)); 107943b34f9dSJacob Faibussowitsch #else 108043b34f9dSJacob Faibussowitsch PetscCall(PetscMalloc1(mat->cmap->N, &a->colmap)); 108143b34f9dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->colmap, oldmat->colmap, mat->cmap->N)); 108243b34f9dSJacob Faibussowitsch #endif 108343b34f9dSJacob Faibussowitsch } else a->colmap = NULL; 108443b34f9dSJacob Faibussowitsch if (oldmat->garray) { 108543b34f9dSJacob Faibussowitsch PetscInt len; 108643b34f9dSJacob Faibussowitsch len = oldmat->B->cmap->n; 108743b34f9dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &a->garray)); 108843b34f9dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(a->garray, oldmat->garray, len)); 108943b34f9dSJacob Faibussowitsch } else a->garray = NULL; 109043b34f9dSJacob Faibussowitsch 109143b34f9dSJacob Faibussowitsch PetscCall(VecDuplicate(oldmat->lvec, &a->lvec)); 109243b34f9dSJacob Faibussowitsch PetscCall(VecScatterCopy(oldmat->Mvctx, &a->Mvctx)); 109343b34f9dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->A, cpvalues, &a->A)); 109443b34f9dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->B, cpvalues, &a->B)); 109543b34f9dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)matin)->qlist, &((PetscObject)mat)->qlist)); 109643b34f9dSJacob Faibussowitsch *newmat = mat; 109743b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109843b34f9dSJacob Faibussowitsch } 109943b34f9dSJacob Faibussowitsch 110043b34f9dSJacob Faibussowitsch static const struct _MatOps MatOps_Values = {MatSetValues_MPISELL, 1101f4259b30SLisandro Dalcin NULL, 1102f4259b30SLisandro Dalcin NULL, 1103d4002b98SHong Zhang MatMult_MPISELL, 1104d4002b98SHong Zhang /* 4*/ MatMultAdd_MPISELL, 1105d4002b98SHong Zhang MatMultTranspose_MPISELL, 1106d4002b98SHong Zhang MatMultTransposeAdd_MPISELL, 1107f4259b30SLisandro Dalcin NULL, 1108f4259b30SLisandro Dalcin NULL, 1109f4259b30SLisandro Dalcin NULL, 1110f4259b30SLisandro Dalcin /*10*/ NULL, 1111f4259b30SLisandro Dalcin NULL, 1112f4259b30SLisandro Dalcin NULL, 1113d4002b98SHong Zhang MatSOR_MPISELL, 1114f4259b30SLisandro Dalcin NULL, 1115d4002b98SHong Zhang /*15*/ MatGetInfo_MPISELL, 1116d4002b98SHong Zhang MatEqual_MPISELL, 1117d4002b98SHong Zhang MatGetDiagonal_MPISELL, 1118d4002b98SHong Zhang MatDiagonalScale_MPISELL, 1119f4259b30SLisandro Dalcin NULL, 1120d4002b98SHong Zhang /*20*/ MatAssemblyBegin_MPISELL, 1121d4002b98SHong Zhang MatAssemblyEnd_MPISELL, 1122d4002b98SHong Zhang MatSetOption_MPISELL, 1123d4002b98SHong Zhang MatZeroEntries_MPISELL, 1124f4259b30SLisandro Dalcin /*24*/ NULL, 1125f4259b30SLisandro Dalcin NULL, 1126f4259b30SLisandro Dalcin NULL, 1127f4259b30SLisandro Dalcin NULL, 1128f4259b30SLisandro Dalcin NULL, 1129d4002b98SHong Zhang /*29*/ MatSetUp_MPISELL, 1130f4259b30SLisandro Dalcin NULL, 1131f4259b30SLisandro Dalcin NULL, 1132d4002b98SHong Zhang MatGetDiagonalBlock_MPISELL, 1133f4259b30SLisandro Dalcin NULL, 1134d4002b98SHong Zhang /*34*/ MatDuplicate_MPISELL, 1135f4259b30SLisandro Dalcin NULL, 1136f4259b30SLisandro Dalcin NULL, 1137f4259b30SLisandro Dalcin NULL, 1138f4259b30SLisandro Dalcin NULL, 1139f4259b30SLisandro Dalcin /*39*/ NULL, 1140f4259b30SLisandro Dalcin NULL, 1141f4259b30SLisandro Dalcin NULL, 1142d4002b98SHong Zhang MatGetValues_MPISELL, 1143d4002b98SHong Zhang MatCopy_MPISELL, 1144f4259b30SLisandro Dalcin /*44*/ NULL, 1145d4002b98SHong Zhang MatScale_MPISELL, 1146d4002b98SHong Zhang MatShift_MPISELL, 1147d4002b98SHong Zhang MatDiagonalSet_MPISELL, 1148f4259b30SLisandro Dalcin NULL, 1149d4002b98SHong Zhang /*49*/ MatSetRandom_MPISELL, 1150f4259b30SLisandro Dalcin NULL, 1151f4259b30SLisandro Dalcin NULL, 1152f4259b30SLisandro Dalcin NULL, 1153f4259b30SLisandro Dalcin NULL, 1154d4002b98SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ, 1155f4259b30SLisandro Dalcin NULL, 1156d4002b98SHong Zhang MatSetUnfactored_MPISELL, 1157f4259b30SLisandro Dalcin NULL, 1158f4259b30SLisandro Dalcin NULL, 1159f4259b30SLisandro Dalcin /*59*/ NULL, 1160d4002b98SHong Zhang MatDestroy_MPISELL, 1161d4002b98SHong Zhang MatView_MPISELL, 1162f4259b30SLisandro Dalcin NULL, 1163f4259b30SLisandro Dalcin NULL, 1164f4259b30SLisandro Dalcin /*64*/ NULL, 1165f4259b30SLisandro Dalcin NULL, 1166f4259b30SLisandro Dalcin NULL, 1167f4259b30SLisandro Dalcin NULL, 1168f4259b30SLisandro Dalcin NULL, 1169f4259b30SLisandro Dalcin /*69*/ NULL, 1170f4259b30SLisandro Dalcin NULL, 1171f4259b30SLisandro Dalcin NULL, 1172f4259b30SLisandro Dalcin NULL, 1173f4259b30SLisandro Dalcin NULL, 1174f4259b30SLisandro Dalcin NULL, 1175d4002b98SHong Zhang /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */ 1176d4002b98SHong Zhang MatSetFromOptions_MPISELL, 1177f4259b30SLisandro Dalcin NULL, 1178f4259b30SLisandro Dalcin NULL, 1179f4259b30SLisandro Dalcin NULL, 1180f4259b30SLisandro Dalcin /*80*/ NULL, 1181f4259b30SLisandro Dalcin NULL, 1182f4259b30SLisandro Dalcin NULL, 1183f4259b30SLisandro Dalcin /*83*/ NULL, 1184f4259b30SLisandro Dalcin NULL, 1185f4259b30SLisandro Dalcin NULL, 1186f4259b30SLisandro Dalcin NULL, 1187f4259b30SLisandro Dalcin NULL, 1188f4259b30SLisandro Dalcin NULL, 1189f4259b30SLisandro Dalcin /*89*/ NULL, 1190f4259b30SLisandro Dalcin NULL, 1191f4259b30SLisandro Dalcin NULL, 1192f4259b30SLisandro Dalcin NULL, 1193f4259b30SLisandro Dalcin NULL, 1194f4259b30SLisandro Dalcin /*94*/ NULL, 1195f4259b30SLisandro Dalcin NULL, 1196f4259b30SLisandro Dalcin NULL, 1197f4259b30SLisandro Dalcin NULL, 1198f4259b30SLisandro Dalcin NULL, 1199f4259b30SLisandro Dalcin /*99*/ NULL, 1200f4259b30SLisandro Dalcin NULL, 1201f4259b30SLisandro Dalcin NULL, 1202d4002b98SHong Zhang MatConjugate_MPISELL, 1203f4259b30SLisandro Dalcin NULL, 1204f4259b30SLisandro Dalcin /*104*/ NULL, 1205d4002b98SHong Zhang MatRealPart_MPISELL, 1206d4002b98SHong Zhang MatImaginaryPart_MPISELL, 1207f4259b30SLisandro Dalcin NULL, 1208f4259b30SLisandro Dalcin NULL, 1209f4259b30SLisandro Dalcin /*109*/ NULL, 1210f4259b30SLisandro Dalcin NULL, 1211f4259b30SLisandro Dalcin NULL, 1212f4259b30SLisandro Dalcin NULL, 1213d4002b98SHong Zhang MatMissingDiagonal_MPISELL, 1214f4259b30SLisandro Dalcin /*114*/ NULL, 1215f4259b30SLisandro Dalcin NULL, 1216d4002b98SHong Zhang MatGetGhosts_MPISELL, 1217f4259b30SLisandro Dalcin NULL, 1218f4259b30SLisandro Dalcin NULL, 121943b34f9dSJacob Faibussowitsch /*119*/ MatMultDiagonalBlock_MPISELL, 1220f4259b30SLisandro Dalcin NULL, 1221f4259b30SLisandro Dalcin NULL, 1222f4259b30SLisandro Dalcin NULL, 1223f4259b30SLisandro Dalcin NULL, 1224f4259b30SLisandro Dalcin /*124*/ NULL, 1225f4259b30SLisandro Dalcin NULL, 1226d4002b98SHong Zhang MatInvertBlockDiagonal_MPISELL, 1227f4259b30SLisandro Dalcin NULL, 1228f4259b30SLisandro Dalcin NULL, 1229f4259b30SLisandro Dalcin /*129*/ NULL, 1230f4259b30SLisandro Dalcin NULL, 1231f4259b30SLisandro Dalcin NULL, 1232f4259b30SLisandro Dalcin NULL, 1233f4259b30SLisandro Dalcin NULL, 1234f4259b30SLisandro Dalcin /*134*/ NULL, 1235f4259b30SLisandro Dalcin NULL, 1236f4259b30SLisandro Dalcin NULL, 1237f4259b30SLisandro Dalcin NULL, 1238f4259b30SLisandro Dalcin NULL, 1239f4259b30SLisandro Dalcin /*139*/ NULL, 1240f4259b30SLisandro Dalcin NULL, 1241f4259b30SLisandro Dalcin NULL, 1242d4002b98SHong Zhang MatFDColoringSetUp_MPIXAIJ, 1243f4259b30SLisandro Dalcin NULL, 1244d70f29a3SPierre Jolivet /*144*/ NULL, 1245d70f29a3SPierre Jolivet NULL, 1246d70f29a3SPierre Jolivet NULL, 124799a7f59eSMark Adams NULL, 124899a7f59eSMark Adams NULL, 12497fb60732SBarry Smith NULL, 1250dec0b466SHong Zhang /*150*/ NULL, 1251eede4a3fSMark Adams NULL, 1252dec0b466SHong Zhang NULL}; 1253d4002b98SHong Zhang 1254d4002b98SHong Zhang /*@C 125511a5261eSBarry Smith MatMPISELLSetPreallocation - Preallocates memory for a `MATMPISELL` sparse parallel matrix in sell format. 1256d4002b98SHong Zhang For good matrix assembly performance the user should preallocate the matrix storage by 125767be906fSBarry Smith setting the parameters `d_nz` (or `d_nnz`) and `o_nz` (or `o_nnz`). 1258d4002b98SHong Zhang 1259d083f849SBarry Smith Collective 1260d4002b98SHong Zhang 1261d4002b98SHong Zhang Input Parameters: 1262d4002b98SHong Zhang + B - the matrix 1263d4002b98SHong Zhang . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1264d4002b98SHong Zhang (same value is used for all local rows) 1265d4002b98SHong Zhang . d_nnz - array containing the number of nonzeros in the various rows of the 1266d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 126767be906fSBarry Smith or NULL (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 1268d4002b98SHong Zhang The size of this array is equal to the number of local rows, i.e 'm'. 1269d4002b98SHong Zhang For matrices that will be factored, you must leave room for (and set) 1270d4002b98SHong Zhang the diagonal entry even if it is zero. 1271d4002b98SHong Zhang . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1272d4002b98SHong Zhang submatrix (same value is used for all local rows). 1273d4002b98SHong Zhang - o_nnz - array containing the number of nonzeros in the various rows of the 1274d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 127567be906fSBarry Smith each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1276d4002b98SHong Zhang structure. The size of this array is equal to the number 1277d4002b98SHong Zhang of local rows, i.e 'm'. 1278d4002b98SHong Zhang 1279d4002b98SHong Zhang Example usage: 1280d4002b98SHong Zhang Consider the following 8x8 matrix with 34 non-zero values, that is 1281d4002b98SHong Zhang assembled across 3 processors. Lets assume that proc0 owns 3 rows, 1282d4002b98SHong Zhang proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 128367be906fSBarry Smith as follows 1284d4002b98SHong Zhang 1285d4002b98SHong Zhang .vb 1286d4002b98SHong Zhang 1 2 0 | 0 3 0 | 0 4 1287d4002b98SHong Zhang Proc0 0 5 6 | 7 0 0 | 8 0 1288d4002b98SHong Zhang 9 0 10 | 11 0 0 | 12 0 1289d4002b98SHong Zhang ------------------------------------- 1290d4002b98SHong Zhang 13 0 14 | 15 16 17 | 0 0 1291d4002b98SHong Zhang Proc1 0 18 0 | 19 20 21 | 0 0 1292d4002b98SHong Zhang 0 0 0 | 22 23 0 | 24 0 1293d4002b98SHong Zhang ------------------------------------- 1294d4002b98SHong Zhang Proc2 25 26 27 | 0 0 28 | 29 0 1295d4002b98SHong Zhang 30 0 0 | 31 32 33 | 0 34 1296d4002b98SHong Zhang .ve 1297d4002b98SHong Zhang 129827430b45SBarry Smith This can be represented as a collection of submatrices as 1299d4002b98SHong Zhang 1300d4002b98SHong Zhang .vb 1301d4002b98SHong Zhang A B C 1302d4002b98SHong Zhang D E F 1303d4002b98SHong Zhang G H I 1304d4002b98SHong Zhang .ve 1305d4002b98SHong Zhang 1306d4002b98SHong Zhang Where the submatrices A,B,C are owned by proc0, D,E,F are 1307d4002b98SHong Zhang owned by proc1, G,H,I are owned by proc2. 1308d4002b98SHong Zhang 1309d4002b98SHong Zhang The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1310d4002b98SHong Zhang The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1311d4002b98SHong Zhang The 'M','N' parameters are 8,8, and have the same values on all procs. 1312d4002b98SHong Zhang 1313d4002b98SHong Zhang The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 1314d4002b98SHong Zhang submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 1315d4002b98SHong Zhang corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 1316d4002b98SHong Zhang Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 131727430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 1318d4002b98SHong Zhang matrix, ans [DF] as another SeqSELL matrix. 1319d4002b98SHong Zhang 132067be906fSBarry Smith When `d_nz`, `o_nz` parameters are specified, `d_nz` storage elements are 1321d4002b98SHong Zhang allocated for every row of the local diagonal submatrix, and o_nz 1322d4002b98SHong Zhang storage locations are allocated for every row of the OFF-DIAGONAL submat. 132367be906fSBarry Smith One way to choose `d_nz` and `o_nz` is to use the max nonzerors per local 1324d4002b98SHong Zhang rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 132527430b45SBarry Smith In this case, the values of d_nz,o_nz are 1326d4002b98SHong Zhang .vb 132727430b45SBarry Smith proc0 dnz = 2, o_nz = 2 132827430b45SBarry Smith proc1 dnz = 3, o_nz = 2 132927430b45SBarry Smith proc2 dnz = 1, o_nz = 4 1330d4002b98SHong Zhang .ve 1331d4002b98SHong Zhang We are allocating m*(d_nz+o_nz) storage locations for every proc. This 1332d4002b98SHong Zhang translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 1333d4002b98SHong Zhang for proc3. i.e we are using 12+15+10=37 storage locations to store 1334d4002b98SHong Zhang 34 values. 1335d4002b98SHong Zhang 133667be906fSBarry Smith When `d_nnz`, `o_nnz` parameters are specified, the storage is specified 1337a5b23f4aSJose E. Roman for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 133827430b45SBarry Smith In the above case the values for d_nnz,o_nnz are 1339d4002b98SHong Zhang .vb 134027430b45SBarry Smith proc0 d_nnz = [2,2,2] and o_nnz = [2,2,2] 134127430b45SBarry Smith proc1 d_nnz = [3,3,2] and o_nnz = [2,1,1] 134227430b45SBarry Smith proc2 d_nnz = [1,1] and o_nnz = [4,4] 1343d4002b98SHong Zhang .ve 1344d4002b98SHong Zhang Here the space allocated is according to nz (or maximum values in the nnz 1345d4002b98SHong Zhang if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37 1346d4002b98SHong Zhang 1347d4002b98SHong Zhang Level: intermediate 1348d4002b98SHong Zhang 134967be906fSBarry Smith Notes: 135067be906fSBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 135167be906fSBarry Smith 135267be906fSBarry Smith The stored row and column indices begin with zero. 135367be906fSBarry Smith 135467be906fSBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 135567be906fSBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 135667be906fSBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 135767be906fSBarry Smith 135867be906fSBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 135967be906fSBarry Smith as the submatrix which is obtained by extraction the part corresponding to 136067be906fSBarry Smith the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 136167be906fSBarry Smith first row that belongs to the processor, r2 is the last row belonging to 136267be906fSBarry Smith the this processor, and c1-c2 is range of indices of the local part of a 136367be906fSBarry Smith vector suitable for applying the matrix to. This is an mxn matrix. In the 136467be906fSBarry Smith common case of a square matrix, the row and column ranges are the same and 136567be906fSBarry Smith the DIAGONAL part is also square. The remaining portion of the local 136667be906fSBarry Smith submatrix (mxN) constitute the OFF-DIAGONAL portion. 136767be906fSBarry Smith 136867be906fSBarry Smith If `o_nnz`, `d_nnz` are specified, then `o_nz`, and `d_nz` are ignored. 136967be906fSBarry Smith 137067be906fSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 137167be906fSBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 137267be906fSBarry Smith You can also run with the option -info and look for messages with the string 137367be906fSBarry Smith malloc in them to see if additional memory allocation was needed. 137467be906fSBarry Smith 137567be906fSBarry Smith .seealso: `Mat`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatCreatesell()`, 137611a5261eSBarry Smith `MATMPISELL`, `MatGetInfo()`, `PetscSplitOwnership()`, `MATSELL` 1377d4002b98SHong Zhang @*/ 1378d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1379d71ae5a4SJacob Faibussowitsch { 1380d4002b98SHong Zhang PetscFunctionBegin; 1381d4002b98SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 1382d4002b98SHong Zhang PetscValidType(B, 1); 1383cac4c232SBarry Smith PetscTryMethod(B, "MatMPISELLSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 13843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1385d4002b98SHong Zhang } 1386d4002b98SHong Zhang 1387ed73aabaSBarry Smith /*MC 1388ed73aabaSBarry Smith MATMPISELL - MATMPISELL = "mpisell" - A matrix type to be used for MPI sparse matrices, 1389ed73aabaSBarry Smith based on the sliced Ellpack format 1390ed73aabaSBarry Smith 139127430b45SBarry Smith Options Database Key: 139220f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()` 1393ed73aabaSBarry Smith 1394ed73aabaSBarry Smith Level: beginner 1395ed73aabaSBarry Smith 139667be906fSBarry Smith .seealso: `Mat`, `MatCreateSell()`, `MATSEQSELL`, `MATSELL`, `MATSEQAIJ`, `MATAIJ`, `MATMPIAIJ` 1397ed73aabaSBarry Smith M*/ 1398ed73aabaSBarry Smith 1399d4002b98SHong Zhang /*@C 140011a5261eSBarry Smith MatCreateSELL - Creates a sparse parallel matrix in `MATSELL` format. 1401d4002b98SHong Zhang 1402d083f849SBarry Smith Collective 1403d4002b98SHong Zhang 1404d4002b98SHong Zhang Input Parameters: 1405d4002b98SHong Zhang + comm - MPI communicator 140611a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE` to have calculated if M is given) 1407d4002b98SHong Zhang This value should be the same as the local size used in creating the 1408d4002b98SHong Zhang y vector for the matrix-vector product y = Ax. 1409d4002b98SHong Zhang . n - This value should be the same as the local size used in creating the 141020f4b53cSBarry Smith x vector for the matrix-vector product y = Ax. (or `PETSC_DECIDE` to have 141120f4b53cSBarry Smith calculated if `N` is given) For square matrices n is almost always `m`. 141220f4b53cSBarry Smith . M - number of global rows (or `PETSC_DETERMINE` to have calculated if `m` is given) 141320f4b53cSBarry Smith . N - number of global columns (or `PETSC_DETERMINE` to have calculated if `n` is given) 1414d4002b98SHong Zhang . d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix 1415d4002b98SHong Zhang (same value is used for all local rows) 1416d4002b98SHong Zhang . d_rlen - array containing the number of nonzeros in the various rows of the 1417d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 141820f4b53cSBarry Smith or `NULL`, if d_rlenmax is used to specify the nonzero structure. 141920f4b53cSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1420d4002b98SHong Zhang . o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local 1421d4002b98SHong Zhang submatrix (same value is used for all local rows). 1422d4002b98SHong Zhang - o_rlen - array containing the number of nonzeros in the various rows of the 1423d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 142420f4b53cSBarry Smith each row) or `NULL`, if `o_rlenmax` is used to specify the nonzero 1425d4002b98SHong Zhang structure. The size of this array is equal to the number 142620f4b53cSBarry Smith of local rows, i.e `m`. 1427d4002b98SHong Zhang 1428d4002b98SHong Zhang Output Parameter: 1429d4002b98SHong Zhang . A - the matrix 1430d4002b98SHong Zhang 143127430b45SBarry Smith Options Database Key: 1432fe59aa6dSJacob Faibussowitsch . -mat_sell_oneindex - Internally use indexing starting at 1 143327430b45SBarry Smith rather than 0. When calling `MatSetValues()`, 143427430b45SBarry Smith the user still MUST index entries starting at 0! 143527430b45SBarry Smith 143627430b45SBarry Smith Example: 143727430b45SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 143827430b45SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 143927430b45SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 144027430b45SBarry Smith as follows 144127430b45SBarry Smith 144227430b45SBarry Smith .vb 144327430b45SBarry Smith 1 2 0 | 0 3 0 | 0 4 144427430b45SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 144527430b45SBarry Smith 9 0 10 | 11 0 0 | 12 0 144627430b45SBarry Smith ------------------------------------- 144727430b45SBarry Smith 13 0 14 | 15 16 17 | 0 0 144827430b45SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 144927430b45SBarry Smith 0 0 0 | 22 23 0 | 24 0 145027430b45SBarry Smith ------------------------------------- 145127430b45SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 145227430b45SBarry Smith 30 0 0 | 31 32 33 | 0 34 145327430b45SBarry Smith .ve 145427430b45SBarry Smith 145520f4b53cSBarry Smith This can be represented as a collection of submatrices as 145627430b45SBarry Smith .vb 145727430b45SBarry Smith A B C 145827430b45SBarry Smith D E F 145927430b45SBarry Smith G H I 146027430b45SBarry Smith .ve 146127430b45SBarry Smith 146227430b45SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 146327430b45SBarry Smith owned by proc1, G,H,I are owned by proc2. 146427430b45SBarry Smith 146527430b45SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 146627430b45SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 146727430b45SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 146827430b45SBarry Smith 146927430b45SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 147027430b45SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 147127430b45SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 147227430b45SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 147327430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 147427430b45SBarry Smith matrix, ans [DF] as another `MATSEQSELL` matrix. 147527430b45SBarry Smith 147627430b45SBarry Smith When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are 147727430b45SBarry Smith allocated for every row of the local diagonal submatrix, and o_rlenmax 147827430b45SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 147927430b45SBarry Smith One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local 148027430b45SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 148120f4b53cSBarry Smith In this case, the values of d_rlenmax,o_rlenmax are 148227430b45SBarry Smith .vb 148320f4b53cSBarry Smith proc0 - d_rlenmax = 2, o_rlenmax = 2 148420f4b53cSBarry Smith proc1 - d_rlenmax = 3, o_rlenmax = 2 148520f4b53cSBarry Smith proc2 - d_rlenmax = 1, o_rlenmax = 4 148627430b45SBarry Smith .ve 148727430b45SBarry Smith We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This 148827430b45SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 148927430b45SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 149027430b45SBarry Smith 34 values. 149127430b45SBarry Smith 149220f4b53cSBarry Smith When `d_rlen`, `o_rlen` parameters are specified, the storage is specified 149327430b45SBarry Smith for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 149420f4b53cSBarry Smith In the above case the values for `d_nnz`, `o_nnz` are 149527430b45SBarry Smith .vb 149620f4b53cSBarry Smith proc0 - d_nnz = [2,2,2] and o_nnz = [2,2,2] 149720f4b53cSBarry Smith proc1 - d_nnz = [3,3,2] and o_nnz = [2,1,1] 149820f4b53cSBarry Smith proc2 - d_nnz = [1,1] and o_nnz = [4,4] 149927430b45SBarry Smith .ve 150027430b45SBarry Smith Here the space allocated is still 37 though there are 34 nonzeros because 150127430b45SBarry Smith the allocation is always done according to rlenmax. 150227430b45SBarry Smith 150327430b45SBarry Smith Level: intermediate 150427430b45SBarry Smith 150527430b45SBarry Smith Notes: 150611a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 1507f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 150811a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqSELLSetPreallocation()`] 1509d4002b98SHong Zhang 1510d4002b98SHong Zhang If the *_rlen parameter is given then the *_rlenmax parameter is ignored 1511d4002b98SHong Zhang 151220f4b53cSBarry Smith `m`, `n`, `M`, `N` parameters specify the size of the matrix, and its partitioning across 151320f4b53cSBarry Smith processors, while `d_rlenmax`, `d_rlen`, `o_rlenmax` , `o_rlen` parameters specify the approximate 1514d4002b98SHong Zhang storage requirements for this matrix. 1515d4002b98SHong Zhang 151611a5261eSBarry Smith If `PETSC_DECIDE` or `PETSC_DETERMINE` is used for a particular argument on one 1517d4002b98SHong Zhang processor than it must be used on all processors that share the object for 1518d4002b98SHong Zhang that argument. 1519d4002b98SHong Zhang 1520d4002b98SHong Zhang The user MUST specify either the local or global matrix dimensions 1521d4002b98SHong Zhang (possibly both). 1522d4002b98SHong Zhang 1523d4002b98SHong Zhang The parallel matrix is partitioned across processors such that the 1524d4002b98SHong Zhang first m0 rows belong to process 0, the next m1 rows belong to 1525d4002b98SHong Zhang process 1, the next m2 rows belong to process 2 etc.. where 1526d4002b98SHong Zhang m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 152720f4b53cSBarry Smith values corresponding to [`m` x `N`] submatrix. 1528d4002b98SHong Zhang 1529d4002b98SHong Zhang The columns are logically partitioned with the n0 columns belonging 1530d4002b98SHong Zhang to 0th partition, the next n1 columns belonging to the next 153120f4b53cSBarry Smith partition etc.. where n0,n1,n2... are the input parameter `n`. 1532d4002b98SHong Zhang 1533d4002b98SHong Zhang The DIAGONAL portion of the local submatrix on any given processor 153420f4b53cSBarry Smith is the submatrix corresponding to the rows and columns `m`, `n` 1535d4002b98SHong Zhang corresponding to the given processor. i.e diagonal matrix on 1536d4002b98SHong Zhang process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 1537d4002b98SHong Zhang etc. The remaining portion of the local submatrix [m x (N-n)] 1538d4002b98SHong Zhang constitute the OFF-DIAGONAL portion. The example below better 1539d4002b98SHong Zhang illustrates this concept. 1540d4002b98SHong Zhang 1541d4002b98SHong Zhang For a square global matrix we define each processor's diagonal portion 1542d4002b98SHong Zhang to be its local rows and the corresponding columns (a square submatrix); 1543d4002b98SHong Zhang each processor's off-diagonal portion encompasses the remainder of the 1544d4002b98SHong Zhang local matrix (a rectangular submatrix). 1545d4002b98SHong Zhang 154620f4b53cSBarry Smith If `o_rlen`, `d_rlen` are specified, then `o_rlenmax`, and `d_rlenmax` are ignored. 1547d4002b98SHong Zhang 1548d4002b98SHong Zhang When calling this routine with a single process communicator, a matrix of 154911a5261eSBarry Smith type `MATSEQSELL` is returned. If a matrix of type `MATMPISELL` is desired for this 155027430b45SBarry Smith type of communicator, use the construction mechanism 1551d4002b98SHong Zhang .vb 155227430b45SBarry Smith MatCreate(...,&A); 155327430b45SBarry Smith MatSetType(A,MATMPISELL); 155427430b45SBarry Smith MatSetSizes(A, m,n,M,N); 155527430b45SBarry Smith MatMPISELLSetPreallocation(A,...); 1556d4002b98SHong Zhang .ve 1557d4002b98SHong Zhang 155867be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatMPISELLSetPreallocation()`, `MatMPISELLSetPreallocationSELL()`, 1559db781477SPatrick Sanan `MATMPISELL`, `MatCreateMPISELLWithArrays()` 1560d4002b98SHong Zhang @*/ 1561d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSELL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt M, PetscInt N, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[], Mat *A) 1562d71ae5a4SJacob Faibussowitsch { 1563d4002b98SHong Zhang PetscMPIInt size; 1564d4002b98SHong Zhang 1565d4002b98SHong Zhang PetscFunctionBegin; 15669566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 15679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 15689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1569d4002b98SHong Zhang if (size > 1) { 15709566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPISELL)); 15719566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(*A, d_rlenmax, d_rlen, o_rlenmax, o_rlen)); 1572d4002b98SHong Zhang } else { 15739566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSELL)); 15749566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(*A, d_rlenmax, d_rlen)); 1575d4002b98SHong Zhang } 15763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1577d4002b98SHong Zhang } 1578d4002b98SHong Zhang 1579fa078d78SJacob Faibussowitsch /*@C 1580fa078d78SJacob Faibussowitsch MatMPISELLGetSeqSELL - Returns the local pieces of this distributed matrix 1581fa078d78SJacob Faibussowitsch 1582fa078d78SJacob Faibussowitsch Not Collective 1583fa078d78SJacob Faibussowitsch 1584fa078d78SJacob Faibussowitsch Input Parameter: 1585fa078d78SJacob Faibussowitsch . A - the `MATMPISELL` matrix 1586fa078d78SJacob Faibussowitsch 1587fa078d78SJacob Faibussowitsch Output Parameters: 1588fa078d78SJacob Faibussowitsch + Ad - The diagonal portion of `A` 15894cf0e950SBarry Smith . Ao - The off-diagonal portion of `A` 1590fa078d78SJacob Faibussowitsch - colmap - An array mapping local column numbers of `Ao` to global column numbers of the parallel matrix 1591fa078d78SJacob Faibussowitsch 1592fa078d78SJacob Faibussowitsch Level: advanced 1593fa078d78SJacob Faibussowitsch 1594fa078d78SJacob Faibussowitsch .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL` 1595fa078d78SJacob Faibussowitsch @*/ 1596fa078d78SJacob Faibussowitsch PetscErrorCode MatMPISELLGetSeqSELL(Mat A, Mat *Ad, Mat *Ao, const PetscInt *colmap[]) 1597fa078d78SJacob Faibussowitsch { 1598fa078d78SJacob Faibussowitsch Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1599fa078d78SJacob Faibussowitsch PetscBool flg; 1600fa078d78SJacob Faibussowitsch 1601fa078d78SJacob Faibussowitsch PetscFunctionBegin; 1602fa078d78SJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &flg)); 1603fa078d78SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "This function requires a MATMPISELL matrix as input"); 1604fa078d78SJacob Faibussowitsch if (Ad) *Ad = a->A; 1605fa078d78SJacob Faibussowitsch if (Ao) *Ao = a->B; 1606fa078d78SJacob Faibussowitsch if (colmap) *colmap = a->garray; 1607fa078d78SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1608fa078d78SJacob Faibussowitsch } 1609fa078d78SJacob Faibussowitsch 1610fa078d78SJacob Faibussowitsch /*@C 1611fa078d78SJacob Faibussowitsch MatMPISELLGetLocalMatCondensed - Creates a `MATSEQSELL` matrix from an `MATMPISELL` matrix by 1612fa078d78SJacob Faibussowitsch taking all its local rows and NON-ZERO columns 1613fa078d78SJacob Faibussowitsch 1614fa078d78SJacob Faibussowitsch Not Collective 1615fa078d78SJacob Faibussowitsch 1616fa078d78SJacob Faibussowitsch Input Parameters: 1617fa078d78SJacob Faibussowitsch + A - the matrix 1618fa078d78SJacob Faibussowitsch . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 1619fa078d78SJacob Faibussowitsch . row - index sets of rows to extract (or `NULL`) 1620fa078d78SJacob Faibussowitsch - col - index sets of columns to extract (or `NULL`) 1621fa078d78SJacob Faibussowitsch 1622fa078d78SJacob Faibussowitsch Output Parameter: 1623fa078d78SJacob Faibussowitsch . A_loc - the local sequential matrix generated 1624fa078d78SJacob Faibussowitsch 1625fa078d78SJacob Faibussowitsch Level: advanced 1626fa078d78SJacob Faibussowitsch 1627fa078d78SJacob Faibussowitsch .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL`, `MatGetOwnershipRange()`, `MatMPISELLGetLocalMat()` 1628fa078d78SJacob Faibussowitsch @*/ 1629fa078d78SJacob Faibussowitsch PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A, MatReuse scall, IS *row, IS *col, Mat *A_loc) 1630fa078d78SJacob Faibussowitsch { 1631fa078d78SJacob Faibussowitsch Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1632fa078d78SJacob Faibussowitsch PetscInt i, start, end, ncols, nzA, nzB, *cmap, imark, *idx; 1633fa078d78SJacob Faibussowitsch IS isrowa, iscola; 1634fa078d78SJacob Faibussowitsch Mat *aloc; 1635fa078d78SJacob Faibussowitsch PetscBool match; 1636fa078d78SJacob Faibussowitsch 1637fa078d78SJacob Faibussowitsch PetscFunctionBegin; 1638fa078d78SJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &match)); 1639fa078d78SJacob Faibussowitsch PetscCheck(match, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Requires MATMPISELL matrix as input"); 1640fa078d78SJacob Faibussowitsch PetscCall(PetscLogEventBegin(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 1641fa078d78SJacob Faibussowitsch if (!row) { 1642fa078d78SJacob Faibussowitsch start = A->rmap->rstart; 1643fa078d78SJacob Faibussowitsch end = A->rmap->rend; 1644fa078d78SJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, end - start, start, 1, &isrowa)); 1645fa078d78SJacob Faibussowitsch } else { 1646fa078d78SJacob Faibussowitsch isrowa = *row; 1647fa078d78SJacob Faibussowitsch } 1648fa078d78SJacob Faibussowitsch if (!col) { 1649fa078d78SJacob Faibussowitsch start = A->cmap->rstart; 1650fa078d78SJacob Faibussowitsch cmap = a->garray; 1651fa078d78SJacob Faibussowitsch nzA = a->A->cmap->n; 1652fa078d78SJacob Faibussowitsch nzB = a->B->cmap->n; 1653fa078d78SJacob Faibussowitsch PetscCall(PetscMalloc1(nzA + nzB, &idx)); 1654fa078d78SJacob Faibussowitsch ncols = 0; 1655fa078d78SJacob Faibussowitsch for (i = 0; i < nzB; i++) { 1656fa078d78SJacob Faibussowitsch if (cmap[i] < start) idx[ncols++] = cmap[i]; 1657fa078d78SJacob Faibussowitsch else break; 1658fa078d78SJacob Faibussowitsch } 1659fa078d78SJacob Faibussowitsch imark = i; 1660fa078d78SJacob Faibussowitsch for (i = 0; i < nzA; i++) idx[ncols++] = start + i; 1661fa078d78SJacob Faibussowitsch for (i = imark; i < nzB; i++) idx[ncols++] = cmap[i]; 1662fa078d78SJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, &iscola)); 1663fa078d78SJacob Faibussowitsch } else { 1664fa078d78SJacob Faibussowitsch iscola = *col; 1665fa078d78SJacob Faibussowitsch } 1666fa078d78SJacob Faibussowitsch if (scall != MAT_INITIAL_MATRIX) { 1667fa078d78SJacob Faibussowitsch PetscCall(PetscMalloc1(1, &aloc)); 1668fa078d78SJacob Faibussowitsch aloc[0] = *A_loc; 1669fa078d78SJacob Faibussowitsch } 1670fa078d78SJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrowa, &iscola, scall, &aloc)); 1671fa078d78SJacob Faibussowitsch *A_loc = aloc[0]; 1672fa078d78SJacob Faibussowitsch PetscCall(PetscFree(aloc)); 1673fa078d78SJacob Faibussowitsch if (!row) PetscCall(ISDestroy(&isrowa)); 1674fa078d78SJacob Faibussowitsch if (!col) PetscCall(ISDestroy(&iscola)); 1675fa078d78SJacob Faibussowitsch PetscCall(PetscLogEventEnd(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 1676fa078d78SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1677fa078d78SJacob Faibussowitsch } 1678fa078d78SJacob Faibussowitsch 1679d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h> 1680d4002b98SHong Zhang 1681d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1682d71ae5a4SJacob Faibussowitsch { 1683d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1684d4002b98SHong Zhang Mat B; 1685d4002b98SHong Zhang Mat_MPIAIJ *b; 1686d4002b98SHong Zhang 1687d4002b98SHong Zhang PetscFunctionBegin; 168828b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1689d4002b98SHong Zhang 169094a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 169194a8b381SRichard Tran Mills B = *newmat; 169294a8b381SRichard Tran Mills } else { 16939566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 16949566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPIAIJ)); 16959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 16969566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 16979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL)); 16989566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 169994a8b381SRichard Tran Mills } 1700d4002b98SHong Zhang b = (Mat_MPIAIJ *)B->data; 170194a8b381SRichard Tran Mills 170294a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 17039566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A)); 17049566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B)); 170594a8b381SRichard Tran Mills } else { 17069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 17079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 17089566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(A)); 17099566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A)); 17109566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B)); 17119566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 17129566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 17139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 171594a8b381SRichard Tran Mills } 1716d4002b98SHong Zhang 1717d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 17189566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1719d4002b98SHong Zhang } else { 1720d4002b98SHong Zhang *newmat = B; 1721d4002b98SHong Zhang } 17223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1723d4002b98SHong Zhang } 1724d4002b98SHong Zhang 1725d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1726d71ae5a4SJacob Faibussowitsch { 1727d4002b98SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 1728d4002b98SHong Zhang Mat B; 1729d4002b98SHong Zhang Mat_MPISELL *b; 1730d4002b98SHong Zhang 1731d4002b98SHong Zhang PetscFunctionBegin; 173228b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1733d4002b98SHong Zhang 173494a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 173594a8b381SRichard Tran Mills B = *newmat; 173694a8b381SRichard Tran Mills } else { 17372d1451d4SHong Zhang Mat_SeqAIJ *Aa = (Mat_SeqAIJ *)a->A->data, *Ba = (Mat_SeqAIJ *)a->B->data; 17382d1451d4SHong Zhang PetscInt i, d_nz = 0, o_nz = 0, m = A->rmap->N, n = A->cmap->N, lm = A->rmap->n, ln = A->cmap->n; 17392d1451d4SHong Zhang PetscInt *d_nnz, *o_nnz; 17402d1451d4SHong Zhang PetscCall(PetscMalloc2(lm, &d_nnz, lm, &o_nnz)); 17412d1451d4SHong Zhang for (i = 0; i < lm; i++) { 17422d1451d4SHong Zhang d_nnz[i] = Aa->i[i + 1] - Aa->i[i]; 17432d1451d4SHong Zhang o_nnz[i] = Ba->i[i + 1] - Ba->i[i]; 17442d1451d4SHong Zhang if (d_nnz[i] > d_nz) d_nz = d_nnz[i]; 17452d1451d4SHong Zhang if (o_nnz[i] > o_nz) o_nz = o_nnz[i]; 17462d1451d4SHong Zhang } 17479566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 17489566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPISELL)); 17492d1451d4SHong Zhang PetscCall(MatSetSizes(B, lm, ln, m, n)); 17509566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 17512d1451d4SHong Zhang PetscCall(MatSeqSELLSetPreallocation(B, d_nz, d_nnz)); 17522d1451d4SHong Zhang PetscCall(MatMPISELLSetPreallocation(B, d_nz, d_nnz, o_nz, o_nnz)); 17532d1451d4SHong Zhang PetscCall(PetscFree2(d_nnz, o_nnz)); 175494a8b381SRichard Tran Mills } 1755d4002b98SHong Zhang b = (Mat_MPISELL *)B->data; 175694a8b381SRichard Tran Mills 175794a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 17589566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A)); 17599566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B)); 176094a8b381SRichard Tran Mills } else { 17619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 17629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 17639566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A)); 17649566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B)); 17659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 17672d1451d4SHong Zhang PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 17682d1451d4SHong Zhang PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 176994a8b381SRichard Tran Mills } 1770d4002b98SHong Zhang 1771d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 17729566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1773d4002b98SHong Zhang } else { 1774d4002b98SHong Zhang *newmat = B; 1775d4002b98SHong Zhang } 17763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1777d4002b98SHong Zhang } 1778d4002b98SHong Zhang 1779d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_MPISELL(Mat matin, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) 1780d71ae5a4SJacob Faibussowitsch { 1781d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 1782f4259b30SLisandro Dalcin Vec bb1 = NULL; 1783d4002b98SHong Zhang 1784d4002b98SHong Zhang PetscFunctionBegin; 1785d4002b98SHong Zhang if (flag == SOR_APPLY_UPPER) { 17869566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 17873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1788d4002b98SHong Zhang } 1789d4002b98SHong Zhang 179048a46eb9SPierre Jolivet if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) PetscCall(VecDuplicate(bb, &bb1)); 1791d4002b98SHong Zhang 1792d4002b98SHong Zhang if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) { 1793d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17949566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1795d4002b98SHong Zhang its--; 1796d4002b98SHong Zhang } 1797d4002b98SHong Zhang 1798d4002b98SHong Zhang while (its--) { 17999566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 18009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1801d4002b98SHong Zhang 1802d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 18039566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 18049566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1805d4002b98SHong Zhang 1806d4002b98SHong Zhang /* local sweep */ 18079566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_SYMMETRIC_SWEEP, fshift, lits, 1, xx)); 1808d4002b98SHong Zhang } 1809d4002b98SHong Zhang } else if (flag & SOR_LOCAL_FORWARD_SWEEP) { 1810d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 18119566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1812d4002b98SHong Zhang its--; 1813d4002b98SHong Zhang } 1814d4002b98SHong Zhang while (its--) { 18159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 18169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1817d4002b98SHong Zhang 1818d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 18199566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 18209566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1821d4002b98SHong Zhang 1822d4002b98SHong Zhang /* local sweep */ 18239566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_FORWARD_SWEEP, fshift, lits, 1, xx)); 1824d4002b98SHong Zhang } 1825d4002b98SHong Zhang } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) { 1826d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 18279566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1828d4002b98SHong Zhang its--; 1829d4002b98SHong Zhang } 1830d4002b98SHong Zhang while (its--) { 18319566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 18329566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1833d4002b98SHong Zhang 1834d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 18359566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 18369566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1837d4002b98SHong Zhang 1838d4002b98SHong Zhang /* local sweep */ 18399566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_BACKWARD_SWEEP, fshift, lits, 1, xx)); 1840d4002b98SHong Zhang } 1841d4002b98SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)matin), PETSC_ERR_SUP, "Parallel SOR not supported"); 1842d4002b98SHong Zhang 18439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb1)); 1844d4002b98SHong Zhang 1845d4002b98SHong Zhang matin->factorerrortype = mat->A->factorerrortype; 18463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1847d4002b98SHong Zhang } 1848d4002b98SHong Zhang 1849b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA) 1850b5917f1bSHong Zhang PETSC_INTERN PetscErrorCode MatConvert_MPISELL_MPISELLCUDA(Mat, MatType, MatReuse, Mat *); 1851b5917f1bSHong Zhang #endif 1852b5917f1bSHong Zhang 1853d4002b98SHong Zhang /*MC 1854d4002b98SHong Zhang MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices. 1855d4002b98SHong Zhang 1856d4002b98SHong Zhang Options Database Keys: 185711a5261eSBarry Smith . -mat_type mpisell - sets the matrix type to `MATMPISELL` during a call to `MatSetFromOptions()` 1858d4002b98SHong Zhang 1859d4002b98SHong Zhang Level: beginner 1860d4002b98SHong Zhang 186167be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MATSEQSELL` `MatCreateSELL()` 1862d4002b98SHong Zhang M*/ 1863d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B) 1864d71ae5a4SJacob Faibussowitsch { 1865d4002b98SHong Zhang Mat_MPISELL *b; 1866d4002b98SHong Zhang PetscMPIInt size; 1867d4002b98SHong Zhang 1868d4002b98SHong Zhang PetscFunctionBegin; 18699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 18704dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1871d4002b98SHong Zhang B->data = (void *)b; 1872aea10558SJacob Faibussowitsch B->ops[0] = MatOps_Values; 1873d4002b98SHong Zhang B->assembled = PETSC_FALSE; 1874d4002b98SHong Zhang B->insertmode = NOT_SET_VALUES; 1875d4002b98SHong Zhang b->size = size; 18769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B), &b->rank)); 1877d4002b98SHong Zhang /* build cache for off array entries formed */ 18789566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 1879d4002b98SHong Zhang 1880d4002b98SHong Zhang b->donotstash = PETSC_FALSE; 1881f4259b30SLisandro Dalcin b->colmap = NULL; 1882f4259b30SLisandro Dalcin b->garray = NULL; 1883d4002b98SHong Zhang b->roworiented = PETSC_TRUE; 1884d4002b98SHong Zhang 1885d4002b98SHong Zhang /* stuff used for matrix vector multiply */ 1886d4002b98SHong Zhang b->lvec = NULL; 1887d4002b98SHong Zhang b->Mvctx = NULL; 1888d4002b98SHong Zhang 1889d4002b98SHong Zhang /* stuff for MatGetRow() */ 1890f4259b30SLisandro Dalcin b->rowindices = NULL; 1891f4259b30SLisandro Dalcin b->rowvalues = NULL; 1892d4002b98SHong Zhang b->getrowactive = PETSC_FALSE; 1893d4002b98SHong Zhang 18949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_MPISELL)); 18959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_MPISELL)); 18969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_MPISELL)); 18979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMPISELLSetPreallocation_C", MatMPISELLSetPreallocation_MPISELL)); 18989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpiaij_C", MatConvert_MPISELL_MPIAIJ)); 1899b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA) 1900b5917f1bSHong Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpisellcuda_C", MatConvert_MPISELL_MPISELLCUDA)); 1901b5917f1bSHong Zhang #endif 19029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDiagonalScaleLocal_C", MatDiagonalScaleLocal_MPISELL)); 19039566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPISELL)); 19043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1905d4002b98SHong Zhang } 1906