1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 26098dc10SBarry Smith 3b3d09e86SJed Brown PetscErrorCode MatConvert_Shell(Mat oldmat,MatType newtype,MatReuse reuse,Mat *newmat) 4dfbe8321SBarry Smith { 5676c34cdSKris Buschelman Mat mat; 66098dc10SBarry Smith Vec in,out; 76696f472SJed Brown PetscScalar *array; 841319c1dSStefano Zampini PetscInt *dnnz,*onnz,*dnnzu,*onnzu; 941319c1dSStefano Zampini PetscInt cst,Nbs,mbs,nbs,rbs,cbs; 1041319c1dSStefano Zampini PetscInt im,i,m,n,M,N,*rows,start; 116098dc10SBarry Smith 123a40ed3dSBarry Smith PetscFunctionBegin; 135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(oldmat,&start,NULL)); 145f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRangeColumn(oldmat,&cst,NULL)); 155f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(oldmat,&in,&out)); 165f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(oldmat,&m,&n)); 175f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(oldmat,&M,&N)); 185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m,&rows)); 198af18dd8SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 205f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)oldmat),&mat)); 215f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(mat,m,n,M,N)); 225f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(mat,newtype)); 235f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSizesFromMats(mat,oldmat,oldmat)); 245f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSizes(mat,&rbs,&cbs)); 2541319c1dSStefano Zampini mbs = m/rbs; 2641319c1dSStefano Zampini nbs = n/cbs; 2741319c1dSStefano Zampini Nbs = N/cbs; 2841319c1dSStefano Zampini cst = cst/cbs; 295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(mbs,&dnnz,mbs,&onnz,mbs,&dnnzu,mbs,&onnzu)); 3041319c1dSStefano Zampini for (i=0; i<mbs; i++) { 3141319c1dSStefano Zampini dnnz[i] = nbs; 3241319c1dSStefano Zampini onnz[i] = Nbs - nbs; 3341319c1dSStefano Zampini dnnzu[i] = PetscMax(nbs - i,0); 3441319c1dSStefano Zampini onnzu[i] = PetscMax(Nbs - (cst + nbs),0); 3541319c1dSStefano Zampini } 365f80ce2aSJacob Faibussowitsch CHKERRQ(MatXAIJSetPreallocation(mat,PETSC_DECIDE,dnnz,onnz,dnnzu,onnzu)); 375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(dnnz,onnz,dnnzu,onnzu)); 385f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOption(in,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE)); 395f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(mat)); 408af18dd8SStefano Zampini } else { 418af18dd8SStefano Zampini mat = *newmat; 425f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(mat)); 438af18dd8SStefano Zampini } 446696f472SJed Brown for (i=0; i<N; i++) { 4541319c1dSStefano Zampini PetscInt j; 4641319c1dSStefano Zampini 475f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(in)); 485f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(in,i,1.,INSERT_VALUES)); 495f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(in)); 505f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(in)); 515f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(oldmat,in,out)); 525f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(out,&array)); 5341319c1dSStefano Zampini for (j=0, im = 0; j<m; j++) { 5441319c1dSStefano Zampini if (PetscAbsScalar(array[j]) == 0.0) continue; 5541319c1dSStefano Zampini rows[im] = j+start; 5641319c1dSStefano Zampini array[im] = array[j]; 5741319c1dSStefano Zampini im++; 5841319c1dSStefano Zampini } 595f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,im,rows,1,&i,array,INSERT_VALUES)); 605f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(out,&array)); 616098dc10SBarry Smith } 625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rows)); 635f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&in)); 645f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&out)); 655f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 665f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 67511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 685f80ce2aSJacob Faibussowitsch CHKERRQ(MatHeaderReplace(oldmat,&mat)); 69c3d102feSKris Buschelman } else { 70676c34cdSKris Buschelman *newmat = mat; 71c3d102feSKris Buschelman } 723a40ed3dSBarry Smith PetscFunctionReturn(0); 736098dc10SBarry Smith } 74251fad3fSStefano Zampini 75251fad3fSStefano Zampini static PetscErrorCode MatGetDiagonal_CF(Mat A,Vec X) 76251fad3fSStefano Zampini { 77251fad3fSStefano Zampini Mat B; 78251fad3fSStefano Zampini 79251fad3fSStefano Zampini PetscFunctionBegin; 805f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&B)); 81*28b400f6SJacob Faibussowitsch PetscCheck(B,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 825f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDiagonal(B,X)); 83251fad3fSStefano Zampini PetscFunctionReturn(0); 84251fad3fSStefano Zampini } 85251fad3fSStefano Zampini 86251fad3fSStefano Zampini static PetscErrorCode MatMult_CF(Mat A,Vec X,Vec Y) 87251fad3fSStefano Zampini { 88251fad3fSStefano Zampini Mat B; 89251fad3fSStefano Zampini 90251fad3fSStefano Zampini PetscFunctionBegin; 915f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&B)); 92*28b400f6SJacob Faibussowitsch PetscCheck(B,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 935f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(B,X,Y)); 94251fad3fSStefano Zampini PetscFunctionReturn(0); 95251fad3fSStefano Zampini } 96251fad3fSStefano Zampini 97251fad3fSStefano Zampini static PetscErrorCode MatMultTranspose_CF(Mat A,Vec X,Vec Y) 98251fad3fSStefano Zampini { 99251fad3fSStefano Zampini Mat B; 100251fad3fSStefano Zampini 101251fad3fSStefano Zampini PetscFunctionBegin; 1025f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&B)); 103*28b400f6SJacob Faibussowitsch PetscCheck(B,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(B,X,Y)); 105251fad3fSStefano Zampini PetscFunctionReturn(0); 106251fad3fSStefano Zampini } 107251fad3fSStefano Zampini 108251fad3fSStefano Zampini static PetscErrorCode MatDestroy_CF(Mat A) 109251fad3fSStefano Zampini { 110251fad3fSStefano Zampini Mat B; 111251fad3fSStefano Zampini 112251fad3fSStefano Zampini PetscFunctionBegin; 1135f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&B)); 114*28b400f6SJacob Faibussowitsch PetscCheck(B,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 1155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 1165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_anytype_C",NULL)); 117b77ba244SStefano Zampini PetscFunctionReturn(0); 118b77ba244SStefano Zampini } 119b77ba244SStefano Zampini 120b77ba244SStefano Zampini typedef struct { 121b77ba244SStefano Zampini void *userdata; 122b77ba244SStefano Zampini PetscErrorCode (*userdestroy)(void*); 123b77ba244SStefano Zampini PetscErrorCode (*numeric)(Mat); 124b77ba244SStefano Zampini MatProductType ptype; 125b77ba244SStefano Zampini Mat Dwork; 126b77ba244SStefano Zampini } MatMatCF; 127b77ba244SStefano Zampini 128b77ba244SStefano Zampini static PetscErrorCode MatProductDestroy_CF(void *data) 129b77ba244SStefano Zampini { 130b77ba244SStefano Zampini MatMatCF *mmcfdata = (MatMatCF*)data; 131b77ba244SStefano Zampini 132b77ba244SStefano Zampini PetscFunctionBegin; 133b77ba244SStefano Zampini if (mmcfdata->userdestroy) { 1345f80ce2aSJacob Faibussowitsch CHKERRQ((*mmcfdata->userdestroy)(mmcfdata->userdata)); 135b77ba244SStefano Zampini } 1365f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&mmcfdata->Dwork)); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mmcfdata)); 138b77ba244SStefano Zampini PetscFunctionReturn(0); 139b77ba244SStefano Zampini } 140b77ba244SStefano Zampini 141b77ba244SStefano Zampini static PetscErrorCode MatProductNumericPhase_CF(Mat A, Mat B, Mat C, void *data) 142b77ba244SStefano Zampini { 143b77ba244SStefano Zampini MatMatCF *mmcfdata = (MatMatCF*)data; 144b77ba244SStefano Zampini 145b77ba244SStefano Zampini PetscFunctionBegin; 146*28b400f6SJacob Faibussowitsch PetscCheck(mmcfdata,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing data"); 147*28b400f6SJacob Faibussowitsch PetscCheck(mmcfdata->numeric,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric operation"); 148b77ba244SStefano Zampini /* the MATSHELL interface allows us to play with the product data */ 1495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&C->product)); 150b77ba244SStefano Zampini C->product->type = mmcfdata->ptype; 151b77ba244SStefano Zampini C->product->data = mmcfdata->userdata; 152b77ba244SStefano Zampini C->product->Dwork = mmcfdata->Dwork; 1535f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&C->product->A)); 154b77ba244SStefano Zampini C->product->B = B; 1555f80ce2aSJacob Faibussowitsch CHKERRQ((*mmcfdata->numeric)(C)); 1565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(C->product)); 157b77ba244SStefano Zampini PetscFunctionReturn(0); 158b77ba244SStefano Zampini } 159b77ba244SStefano Zampini 160b77ba244SStefano Zampini static PetscErrorCode MatProductSymbolicPhase_CF(Mat A, Mat B, Mat C, void **data) 161b77ba244SStefano Zampini { 162b77ba244SStefano Zampini MatMatCF *mmcfdata; 163b77ba244SStefano Zampini 164b77ba244SStefano Zampini PetscFunctionBegin; 1655f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&C->product->A)); 1665f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(C)); 1675f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSymbolic(C)); 168b77ba244SStefano Zampini /* the MATSHELL interface does not allow non-empty product data */ 1695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&mmcfdata)); 170b77ba244SStefano Zampini 171b77ba244SStefano Zampini mmcfdata->numeric = C->ops->productnumeric; 172b77ba244SStefano Zampini mmcfdata->ptype = C->product->type; 173b77ba244SStefano Zampini mmcfdata->userdata = C->product->data; 174b77ba244SStefano Zampini mmcfdata->userdestroy = C->product->destroy; 175b77ba244SStefano Zampini mmcfdata->Dwork = C->product->Dwork; 176b77ba244SStefano Zampini 177b77ba244SStefano Zampini C->product->Dwork = NULL; 178b77ba244SStefano Zampini C->product->data = NULL; 179b77ba244SStefano Zampini C->product->destroy = NULL; 180b77ba244SStefano Zampini C->product->A = A; 181b77ba244SStefano Zampini 182b77ba244SStefano Zampini *data = mmcfdata; 183b77ba244SStefano Zampini PetscFunctionReturn(0); 184b77ba244SStefano Zampini } 185b77ba244SStefano Zampini 186b77ba244SStefano Zampini /* only for A of type shell, mainly used for MatMat operations of shells with AXPYs */ 187b77ba244SStefano Zampini static PetscErrorCode MatProductSetFromOptions_CF(Mat D) 188b77ba244SStefano Zampini { 189b77ba244SStefano Zampini Mat A,B,Ain; 190b77ba244SStefano Zampini void (*Af)(void) = NULL; 191b77ba244SStefano Zampini PetscBool flg; 192b77ba244SStefano Zampini 193b77ba244SStefano Zampini PetscFunctionBegin; 194b77ba244SStefano Zampini MatCheckProduct(D,1); 195b77ba244SStefano Zampini if (D->product->type == MATPRODUCT_ABC) PetscFunctionReturn(0); 196b77ba244SStefano Zampini A = D->product->A; 197b77ba244SStefano Zampini B = D->product->B; 1985f80ce2aSJacob Faibussowitsch CHKERRQ(MatIsShell(A,&flg)); 199b77ba244SStefano Zampini if (!flg) PetscFunctionReturn(0); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQueryFunction((PetscObject)A,"MatProductSetFromOptions_anytype_C",&Af)); 201b77ba244SStefano Zampini if (Af == (void(*)(void))MatProductSetFromOptions_CF) { 2025f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&Ain)); 203b77ba244SStefano Zampini } else PetscFunctionReturn(0); 204b77ba244SStefano Zampini D->product->A = Ain; 2055f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(D)); 206b77ba244SStefano Zampini D->product->A = A; 207b77ba244SStefano Zampini if (D->ops->productsymbolic) { /* we have a symbolic match, now populate the MATSHELL operations */ 2085f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetMatProductOperation(A,D->product->type,MatProductSymbolicPhase_CF,MatProductNumericPhase_CF,MatProductDestroy_CF,((PetscObject)B)->type_name,NULL)); 2095f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(D)); 210b77ba244SStefano Zampini } 211251fad3fSStefano Zampini PetscFunctionReturn(0); 212251fad3fSStefano Zampini } 213251fad3fSStefano Zampini 214251fad3fSStefano Zampini PetscErrorCode MatConvertFrom_Shell(Mat A,MatType newtype,MatReuse reuse,Mat *B) 215251fad3fSStefano Zampini { 216251fad3fSStefano Zampini Mat M; 217251fad3fSStefano Zampini PetscBool flg; 218251fad3fSStefano Zampini 219251fad3fSStefano Zampini PetscFunctionBegin; 2205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(newtype,MATSHELL,&flg)); 221*28b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only conversion to MATSHELL"); 222251fad3fSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 2235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A)); 2245f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject)A),A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,A,&M)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSizesFromMats(M,A,A)); 2265f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(M,MATOP_MULT, (void (*)(void))MatMult_CF)); 2275f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(M,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_CF)); 2285f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(M,MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_CF)); 2295f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(M,MATOP_DESTROY, (void (*)(void))MatDestroy_CF)); 2305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)M,"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_CF)); 2315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(M->defaultvectype)); 2325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrallocpy(A->defaultvectype,&M->defaultvectype)); 2332487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 2345f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(M,A->boundtocpu)); 2352487f3f2SStefano Zampini #endif 236251fad3fSStefano Zampini *B = M; 237251fad3fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented"); 238251fad3fSStefano Zampini PetscFunctionReturn(0); 239251fad3fSStefano Zampini } 240