From d8059fa1506ffa16d338c5cdb41bb94ce8cf66e6 Mon Sep 17 00:00:00 2001 From: Lawrence Mitchell Date: Thu, 2 Jun 2016 16:17:18 +0100 Subject: [PATCH] WIP: Support pulling arbitrary subblocks out of MATNEST --- src/mat/impls/nest/matnest.c | 122 ++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 3 deletions(-) diff --git a/src/mat/impls/nest/matnest.c b/src/mat/impls/nest/matnest.c index 0a57057a11..f688c76f07 100644 --- a/src/mat/impls/nest/matnest.c +++ b/src/mat/impls/nest/matnest.c @@ -311,6 +311,72 @@ static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,Petsc PetscFunctionReturn(0); } +#undef __FUNCT__ +#define __FUNCT__ "MatNestFindISs" +static PetscErrorCode MatNestFindISs(Mat A, const PetscInt n, const IS list[], IS is, PetscInt *nfound, + PetscInt **found) +{ + PetscErrorCode ierr; + PetscInt i, offset, size; + IS candidate; + PetscInt candidateSize; + const PetscInt *indices; + PetscBool flg; + + PetscFunctionBegin; + + PetscValidPointer(list,3); + PetscValidHeaderSpecific(is,IS_CLASSID,4); + PetscValidPointer(nfound,5); + PetscValidPointer(found,6); + *nfound = 0; + ierr = PetscMalloc1(n,found);CHKERRQ(ierr); + + ierr = ISGetIndices(is,&indices);CHKERRQ(ierr); + ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); + offset = 0; + while (1) { + flg = PETSC_FALSE; + /* Walk over the ISes of A */ + for (i=0; i size) continue; + /* Build the candidate. */ + ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is), + candSize, isIndices + off, PETSC_USE_POINTER, &candidate);CHKERRQ(ierr); + ierr = ISEqual(list[i],candidate,&match);CHKERRQ(ierr); + ierr = ISDestroy(&candidate);CHKERRQ(ierr); + if (match) { + /* Found it, record so. */ + (*indices)[*nidx] = i; + (*nidx)++; + flg = PETSC_TRUE; + offset += candidateSize; + } + } + /* We walked over all the remaining ISes and didn't match, we're done. */ + if (!flg) { + break; + } + } + /* The target IS has some remaining indices, IOW, we failed to find a full match. */ + if (offset < size) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Could not find index set"); + + PetscFunctionReturn(0); +} + #undef __FUNCT__ #define __FUNCT__ "MatNestGetRow" /* Get a block row as a new MatNest */ @@ -335,6 +401,52 @@ static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B) PetscFunctionReturn(0); } +#undef __FUNCT__ +#define __FUNCT__ "MatNestGetSubBlock" +static PetscErrorCode MatNestGetSubBlock(Mat A,PetscInt nr, PetscInt *rows,PetscInt nc, PetscInt *cols,Mat *B) +{ + Mat_Nest *vs = (Mat_Nest*)A->data; + Mat block[nr*nc]; + char keyname[256]; + PetscInt i, j, off; + size_t count; + PetscErrorCode ierr; + + PetscFunctionBegin; + *B = NULL; + if (nr == 1 && nc == 1) { + *B = vs->m[rows[0]][cols[0]]; + PetscFunctionReturn(0); + } + off = 0; + count = 0; + ierr = PetscSNPrintfCount(keyname + off,sizeof(keyname) - off,"NestBlock",&count);CHKERRQ(ierr); + off += count; + for (i=0;im[rows[i]][cols[j]]; + } + } + ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nr,NULL,nc,NULL,block,B);CHKERRQ(ierr); + (*B)->assembled = A->assembled; + ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr); + ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */ + PetscFunctionReturn(0); +} + #undef __FUNCT__ #define __FUNCT__ "MatNestFindSubMat" static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) @@ -368,9 +480,13 @@ static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow, ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr); } else { - ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); - ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr); - *B = vs->m[row][col]; + PetscInt nr, nc; + PetscInt *rows, *cols; + ierr = MatNestFindISs(A,vs->nr,is->row,isrow,&nr,&rows);CHKERRQ(ierr); + ierr = MatNestFindISs(A,vs->nc,is->col,iscol,&nc,&cols);CHKERRQ(ierr); + ierr = MatNestGetSubBlock(A,nr,rows,nc,cols,B);CHKERRQ(ierr); + ierr = PetscFree(rows);CHKERRQ(ierr); + ierr = PetscFree(cols);CHKERRQ(ierr); } PetscFunctionReturn(0); } -- 2.19.1