xref: /petsc/src/mat/impls/localref/mlocalref.c (revision 0b46e949f18ac28417071477034640c76a0832a0)
1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
22c0dbf93SJed Brown 
32c0dbf93SJed Brown typedef struct {
42c0dbf93SJed Brown   Mat       Top;
589f730bfSLawrence Mitchell   PetscBool rowisblock;
689f730bfSLawrence Mitchell   PetscBool colisblock;
72c0dbf93SJed Brown   PetscErrorCode (*SetValues)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
82c0dbf93SJed Brown   PetscErrorCode (*SetValuesBlocked)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
92c0dbf93SJed Brown } Mat_LocalRef;
102c0dbf93SJed Brown 
112c0dbf93SJed Brown /* These need to be macros because they use sizeof */
129371c9d4SSatish Balay #define IndexSpaceGet(buf, nrow, ncol, irowm, icolm) \
139371c9d4SSatish Balay   do { \
14dd39110bSPierre Jolivet     if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { \
159566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(nrow, &irowm, ncol, &icolm)); \
162c0dbf93SJed Brown     } else { \
172c0dbf93SJed Brown       irowm = &buf[0]; \
182c0dbf93SJed Brown       icolm = &buf[nrow]; \
192c0dbf93SJed Brown     } \
202c0dbf93SJed Brown   } while (0)
212c0dbf93SJed Brown 
229371c9d4SSatish Balay #define IndexSpaceRestore(buf, nrow, ncol, irowm, icolm) \
239371c9d4SSatish Balay   do { \
2448a46eb9SPierre Jolivet     if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) PetscCall(PetscFree2(irowm, icolm)); \
252c0dbf93SJed Brown   } while (0)
262c0dbf93SJed Brown 
BlockIndicesExpand(PetscInt n,const PetscInt idx[],PetscInt bs,PetscInt idxm[])27d71ae5a4SJacob Faibussowitsch static void BlockIndicesExpand(PetscInt n, const PetscInt idx[], PetscInt bs, PetscInt idxm[])
28d71ae5a4SJacob Faibussowitsch {
292c0dbf93SJed Brown   PetscInt i, j;
302c0dbf93SJed Brown   for (i = 0; i < n; i++) {
31ad540459SPierre Jolivet     for (j = 0; j < bs; j++) idxm[i * bs + j] = idx[i] * bs + j;
322c0dbf93SJed Brown   }
332c0dbf93SJed Brown }
342c0dbf93SJed Brown 
MatSetValuesBlockedLocal_LocalRef_Block(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)35d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Block(Mat A, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
36d71ae5a4SJacob Faibussowitsch {
372c0dbf93SJed Brown   Mat_LocalRef *lr = (Mat_LocalRef *)A->data;
38a497884dSSatish Balay   PetscInt      buf[4096], *irowm = NULL, *icolm; /* suppress maybe-uninitialized warning */
392c0dbf93SJed Brown 
402c0dbf93SJed Brown   PetscFunctionBegin;
413ba16761SJacob Faibussowitsch   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS);
422c0dbf93SJed Brown   IndexSpaceGet(buf, nrow, ncol, irowm, icolm);
439566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, nrow, irow, irowm));
449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, ncol, icol, icolm));
459566063dSJacob Faibussowitsch   PetscCall((*lr->SetValuesBlocked)(lr->Top, nrow, irowm, ncol, icolm, y, addv));
462c0dbf93SJed Brown   IndexSpaceRestore(buf, nrow, ncol, irowm, icolm);
473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
482c0dbf93SJed Brown }
492c0dbf93SJed Brown 
MatSetValuesBlockedLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)50d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Scalar(Mat A, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
51d71ae5a4SJacob Faibussowitsch {
522c0dbf93SJed Brown   Mat_LocalRef *lr = (Mat_LocalRef *)A->data;
536e191704SLawrence Mitchell   PetscInt      rbs, cbs, buf[4096], *irowm, *icolm;
542c0dbf93SJed Brown 
552c0dbf93SJed Brown   PetscFunctionBegin;
569566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &rbs, &cbs));
576e191704SLawrence Mitchell   IndexSpaceGet(buf, nrow * rbs, ncol * cbs, irowm, icolm);
586e191704SLawrence Mitchell   BlockIndicesExpand(nrow, irow, rbs, irowm);
596e191704SLawrence Mitchell   BlockIndicesExpand(ncol, icol, cbs, icolm);
609566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, nrow * rbs, irowm, irowm));
619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, ncol * cbs, icolm, icolm));
629566063dSJacob Faibussowitsch   PetscCall((*lr->SetValues)(lr->Top, nrow * rbs, irowm, ncol * cbs, icolm, y, addv));
636e191704SLawrence Mitchell   IndexSpaceRestore(buf, nrow * rbs, ncol * cbs, irowm, icolm);
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
652c0dbf93SJed Brown }
662c0dbf93SJed Brown 
MatSetValuesLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)67d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_LocalRef_Scalar(Mat A, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
68d71ae5a4SJacob Faibussowitsch {
692c0dbf93SJed Brown   Mat_LocalRef *lr = (Mat_LocalRef *)A->data;
702c0dbf93SJed Brown   PetscInt      buf[4096], *irowm, *icolm;
712c0dbf93SJed Brown 
722c0dbf93SJed Brown   PetscFunctionBegin;
732c0dbf93SJed Brown   IndexSpaceGet(buf, nrow, ncol, irowm, icolm);
7489f730bfSLawrence Mitchell   /* If the row IS defining this submatrix was an ISBLOCK, then the unblocked LGMapApply is the right one to use.  If
7589f730bfSLawrence Mitchell    * instead it was (say) an ISSTRIDE with a block size > 1, then we need to use LGMapApplyBlock */
7689f730bfSLawrence Mitchell   if (lr->rowisblock) {
779566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, nrow, irow, irowm));
7889f730bfSLawrence Mitchell   } else {
799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, nrow, irow, irowm));
8089f730bfSLawrence Mitchell   }
8189f730bfSLawrence Mitchell   /* As above, but for the column IS. */
8289f730bfSLawrence Mitchell   if (lr->colisblock) {
839566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, ncol, icol, icolm));
8489f730bfSLawrence Mitchell   } else {
859566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, ncol, icol, icolm));
8689f730bfSLawrence Mitchell   }
879566063dSJacob Faibussowitsch   PetscCall((*lr->SetValues)(lr->Top, nrow, irowm, ncol, icolm, y, addv));
882c0dbf93SJed Brown   IndexSpaceRestore(buf, nrow, ncol, irowm, icolm);
893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
902c0dbf93SJed Brown }
912c0dbf93SJed Brown 
922265a299SJed Brown /* Compose an IS with an ISLocalToGlobalMapping to map from IS source indices to global indices */
ISL2GCompose(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping * cltog)93d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISL2GCompose(IS is, ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *cltog)
94d71ae5a4SJacob Faibussowitsch {
952c0dbf93SJed Brown   const PetscInt *idx;
962c0dbf93SJed Brown   PetscInt        m, *idxm;
9712e05225SLawrence Mitchell   PetscInt        bs;
98565245c5SBarry Smith   PetscBool       isblock;
992c0dbf93SJed Brown 
1002c0dbf93SJed Brown   PetscFunctionBegin;
101b3e8af9fSJed Brown   PetscValidHeaderSpecific(is, IS_CLASSID, 1);
102b3e8af9fSJed Brown   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 2);
1034f572ea9SToby Isaac   PetscAssertPointer(cltog, 3);
1049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)is, ISBLOCK, &isblock));
105565245c5SBarry Smith   if (isblock) {
10612e05225SLawrence Mitchell     PetscInt lbs;
107565245c5SBarry Smith 
1089566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(is, &bs));
1099566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &lbs));
110565245c5SBarry Smith     if (bs == lbs) {
1119566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(is, &m));
112565245c5SBarry Smith       m = m / bs;
1139566063dSJacob Faibussowitsch       PetscCall(ISBlockGetIndices(is, &idx));
1149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m, &idxm));
1159566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, m, idx, idxm));
1169566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is), bs, m, idxm, PETSC_OWN_POINTER, cltog));
1179566063dSJacob Faibussowitsch       PetscCall(ISBlockRestoreIndices(is, &idx));
1183ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
119565245c5SBarry Smith     }
120565245c5SBarry Smith   }
1219566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &m));
1229566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &idx));
1239566063dSJacob Faibussowitsch   PetscCall(ISGetBlockSize(is, &bs));
1249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &idxm));
1252c0dbf93SJed Brown   if (ltog) {
1269566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(ltog, m, idx, idxm));
1272c0dbf93SJed Brown   } else {
1289566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(idxm, idx, m));
1292c0dbf93SJed Brown   }
1309566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is), bs, m, idxm, PETSC_OWN_POINTER, cltog));
1319566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &idx));
1323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1332c0dbf93SJed Brown }
1342c0dbf93SJed Brown 
ISL2GComposeBlock(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping * cltog)135d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISL2GComposeBlock(IS is, ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *cltog)
136d71ae5a4SJacob Faibussowitsch {
1372c0dbf93SJed Brown   const PetscInt *idx;
13845b6f7e9SBarry Smith   PetscInt        m, *idxm, bs;
1392c0dbf93SJed Brown 
1402c0dbf93SJed Brown   PetscFunctionBegin;
141b3e8af9fSJed Brown   PetscValidHeaderSpecific(is, IS_CLASSID, 1);
142b3e8af9fSJed Brown   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 2);
1434f572ea9SToby Isaac   PetscAssertPointer(cltog, 3);
1449566063dSJacob Faibussowitsch   PetscCall(ISBlockGetLocalSize(is, &m));
1459566063dSJacob Faibussowitsch   PetscCall(ISBlockGetIndices(is, &idx));
1469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
1479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m, &idxm));
1482c0dbf93SJed Brown   if (ltog) {
1499566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, m, idx, idxm));
1502c0dbf93SJed Brown   } else {
1519566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(idxm, idx, m));
1522c0dbf93SJed Brown   }
1539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is), bs, m, idxm, PETSC_OWN_POINTER, cltog));
1549566063dSJacob Faibussowitsch   PetscCall(ISBlockRestoreIndices(is, &idx));
1553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1562c0dbf93SJed Brown }
1572c0dbf93SJed Brown 
MatZeroRowsLocal_LocalRef(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)158*06024a9cSStefano Zampini static PetscErrorCode MatZeroRowsLocal_LocalRef(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
159*06024a9cSStefano Zampini {
160*06024a9cSStefano Zampini   PetscInt     *rows_l;
161*06024a9cSStefano Zampini   Mat_LocalRef *lr = (Mat_LocalRef *)A->data;
162*06024a9cSStefano Zampini 
163*06024a9cSStefano Zampini   PetscFunctionBegin;
164*06024a9cSStefano Zampini   PetscCall(PetscMalloc1(n, &rows_l));
165*06024a9cSStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, n, rows, rows_l));
166*06024a9cSStefano Zampini   PetscCall(MatZeroRows(lr->Top, n, rows_l, diag, x, b));
167*06024a9cSStefano Zampini   PetscCall(PetscFree(rows_l));
168*06024a9cSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
169*06024a9cSStefano Zampini }
170*06024a9cSStefano Zampini 
MatZeroRowsColumnsLocal_LocalRef(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)171*06024a9cSStefano Zampini static PetscErrorCode MatZeroRowsColumnsLocal_LocalRef(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
172*06024a9cSStefano Zampini {
173*06024a9cSStefano Zampini   PetscInt     *rows_l;
174*06024a9cSStefano Zampini   Mat_LocalRef *lr = (Mat_LocalRef *)A->data;
175*06024a9cSStefano Zampini 
176*06024a9cSStefano Zampini   PetscFunctionBegin;
177*06024a9cSStefano Zampini   PetscCall(PetscMalloc1(n, &rows_l));
178*06024a9cSStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, n, rows, rows_l));
179*06024a9cSStefano Zampini   PetscCall(MatZeroRowsColumns(lr->Top, n, rows_l, diag, x, b));
180*06024a9cSStefano Zampini   PetscCall(PetscFree(rows_l));
181*06024a9cSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
182*06024a9cSStefano Zampini }
183*06024a9cSStefano Zampini 
MatDestroy_LocalRef(Mat B)184d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_LocalRef(Mat B)
185d71ae5a4SJacob Faibussowitsch {
1862c0dbf93SJed Brown   PetscFunctionBegin;
1879566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->data));
1883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1892c0dbf93SJed Brown }
1902c0dbf93SJed Brown 
1912c0dbf93SJed Brown /*@
19211a5261eSBarry Smith   MatCreateLocalRef - Gets a logical reference to a local submatrix, for use in assembly, that is to set values into the matrix
1932c0dbf93SJed Brown 
1942c0dbf93SJed Brown   Not Collective
1952c0dbf93SJed Brown 
1964165533cSJose E. Roman   Input Parameters:
1972ef1f0ffSBarry Smith + A     - full matrix, generally parallel
1982c0dbf93SJed Brown . isrow - Local index set for the rows
1992c0dbf93SJed Brown - iscol - Local index set for the columns
2002c0dbf93SJed Brown 
2014165533cSJose E. Roman   Output Parameter:
2022ef1f0ffSBarry Smith . newmat - new serial `Mat`
2032c0dbf93SJed Brown 
2042c0dbf93SJed Brown   Level: developer
2052c0dbf93SJed Brown 
2062c0dbf93SJed Brown   Notes:
20711a5261eSBarry Smith   Most will use `MatGetLocalSubMatrix()` which returns a real matrix corresponding to the local
2082c0dbf93SJed Brown   block if it available, such as with matrix formats that store these blocks separately.
2092c0dbf93SJed Brown 
21011a5261eSBarry Smith   The new matrix forwards `MatSetValuesLocal()` and `MatSetValuesBlockedLocal()` to the global system.
21111a5261eSBarry Smith   In general, it does not define `MatMult()` or any other functions.  Local submatrices can be nested.
2122c0dbf93SJed Brown 
213fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MATSUBMATRIX`, `MatCreateSubMatrixVirtual()`, `MatSetValuesLocal()`, `MatSetValuesBlockedLocal()`, `MatGetLocalSubMatrix()`, `MatCreateSubMatrix()`
2142c0dbf93SJed Brown @*/
MatCreateLocalRef(Mat A,IS isrow,IS iscol,Mat * newmat)215d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateLocalRef(Mat A, IS isrow, IS iscol, Mat *newmat)
216d71ae5a4SJacob Faibussowitsch {
2172c0dbf93SJed Brown   Mat_LocalRef *lr;
2182c0dbf93SJed Brown   Mat           B;
2192c0dbf93SJed Brown   PetscInt      m, n;
2202c0dbf93SJed Brown   PetscBool     islr;
2212c0dbf93SJed Brown 
2222c0dbf93SJed Brown   PetscFunctionBegin;
2232c0dbf93SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2242c0dbf93SJed Brown   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
2252c0dbf93SJed Brown   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
2264f572ea9SToby Isaac   PetscAssertPointer(newmat, 4);
22728b400f6SJacob Faibussowitsch   PetscCheck(A->rmap->mapping, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
228f4259b30SLisandro Dalcin   *newmat = NULL;
2292c0dbf93SJed Brown 
2309566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &B));
2319566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &m));
2329566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &n));
2339566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, m, n, m, n));
2349566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATLOCALREF));
2359566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
2362c0dbf93SJed Brown 
2372c0dbf93SJed Brown   B->ops->destroy = MatDestroy_LocalRef;
2382c0dbf93SJed Brown 
2394dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&lr));
2402c0dbf93SJed Brown   B->data = (void *)lr;
2412c0dbf93SJed Brown 
2429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATLOCALREF, &islr));
2432265a299SJed Brown   if (islr) {
2442265a299SJed Brown     Mat_LocalRef *alr = (Mat_LocalRef *)A->data;
2452265a299SJed Brown     lr->Top           = alr->Top;
2462265a299SJed Brown   } else {
2472265a299SJed Brown     /* This does not increase the reference count because MatLocalRef is not allowed to live longer than its parent */
2482265a299SJed Brown     lr->Top = A;
2492265a299SJed Brown   }
2502265a299SJed Brown   {
2512c0dbf93SJed Brown     ISLocalToGlobalMapping rltog, cltog;
2526e191704SLawrence Mitchell     PetscInt               arbs, acbs, rbs, cbs;
2532c0dbf93SJed Brown 
2542265a299SJed Brown     /* We will translate directly to global indices for the top level */
2552c0dbf93SJed Brown     lr->SetValues        = MatSetValues;
2562c0dbf93SJed Brown     lr->SetValuesBlocked = MatSetValuesBlocked;
2572c0dbf93SJed Brown 
2582c0dbf93SJed Brown     B->ops->setvalueslocal       = MatSetValuesLocal_LocalRef_Scalar;
259*06024a9cSStefano Zampini     B->ops->zerorowslocal        = MatZeroRowsLocal_LocalRef;
260*06024a9cSStefano Zampini     B->ops->zerorowscolumnslocal = MatZeroRowsColumnsLocal_LocalRef;
2612205254eSKarl Rupp 
2629566063dSJacob Faibussowitsch     PetscCall(ISL2GCompose(isrow, A->rmap->mapping, &rltog));
263992144d0SBarry Smith     if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) {
2649566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)rltog));
2652c0dbf93SJed Brown       cltog = rltog;
2662c0dbf93SJed Brown     } else {
2679566063dSJacob Faibussowitsch       PetscCall(ISL2GCompose(iscol, A->cmap->mapping, &cltog));
2682c0dbf93SJed Brown     }
26989f730bfSLawrence Mitchell     /* Remember if the ISes we used to pull out the submatrix are of type ISBLOCK.  Will be used later in
27089f730bfSLawrence Mitchell      * MatSetValuesLocal_LocalRef_Scalar. */
2719566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISBLOCK, &lr->rowisblock));
2729566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)iscol, ISBLOCK, &lr->colisblock));
2739566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B, rltog, cltog));
2749566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rltog));
2759566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cltog));
2762c0dbf93SJed Brown 
2779566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(A, &arbs, &acbs));
2789566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(isrow, &rbs));
2799566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(iscol, &cbs));
2806e191704SLawrence Mitchell     /* Always support block interface insertion on submatrix */
2819566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(B->rmap, rbs));
2829566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(B->cmap, cbs));
2836e191704SLawrence Mitchell     if (arbs != rbs || acbs != cbs || (arbs == 1 && acbs == 1)) {
2842c0dbf93SJed Brown       /* Top-level matrix has different block size, so we have to call its scalar insertion interface */
2852c0dbf93SJed Brown       B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Scalar;
2862c0dbf93SJed Brown     } else {
2872c0dbf93SJed Brown       /* Block sizes match so we can forward values to the top level using the block interface */
2882c0dbf93SJed Brown       B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Block;
28926fbe8dcSKarl Rupp 
2909566063dSJacob Faibussowitsch       PetscCall(ISL2GComposeBlock(isrow, A->rmap->mapping, &rltog));
29145b6f7e9SBarry Smith       if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) {
2929566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)rltog));
2932c0dbf93SJed Brown         cltog = rltog;
2942c0dbf93SJed Brown       } else {
2959566063dSJacob Faibussowitsch         PetscCall(ISL2GComposeBlock(iscol, A->cmap->mapping, &cltog));
2962c0dbf93SJed Brown       }
2979566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(B, rltog, cltog));
2989566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&rltog));
2999566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cltog));
3002c0dbf93SJed Brown     }
3012c0dbf93SJed Brown   }
3022c0dbf93SJed Brown   *newmat = B;
3033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3042c0dbf93SJed Brown }
305