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; 1141319c1dSStefano Zampini PetscErrorCode ierr; 126098dc10SBarry Smith 133a40ed3dSBarry Smith PetscFunctionBegin; 146696f472SJed Brown ierr = MatGetOwnershipRange(oldmat,&start,NULL);CHKERRQ(ierr); 1541319c1dSStefano Zampini ierr = MatGetOwnershipRangeColumn(oldmat,&cst,NULL);CHKERRQ(ierr); 166696f472SJed Brown ierr = MatCreateVecs(oldmat,&in,&out);CHKERRQ(ierr); 176696f472SJed Brown ierr = MatGetLocalSize(oldmat,&m,&n);CHKERRQ(ierr); 186696f472SJed Brown ierr = MatGetSize(oldmat,&M,&N);CHKERRQ(ierr); 196696f472SJed Brown ierr = PetscMalloc1(m,&rows);CHKERRQ(ierr); 20*8af18dd8SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 21*8af18dd8SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)oldmat),&mat);CHKERRQ(ierr); 226696f472SJed Brown ierr = MatSetSizes(mat,m,n,M,N);CHKERRQ(ierr); 234a6a16e5SBarry Smith ierr = MatSetType(mat,newtype);CHKERRQ(ierr); 2433d57670SJed Brown ierr = MatSetBlockSizesFromMats(mat,oldmat,oldmat);CHKERRQ(ierr); 2541319c1dSStefano Zampini ierr = MatGetBlockSizes(mat,&rbs,&cbs);CHKERRQ(ierr); 2641319c1dSStefano Zampini mbs = m/rbs; 2741319c1dSStefano Zampini nbs = n/cbs; 2841319c1dSStefano Zampini Nbs = N/cbs; 2941319c1dSStefano Zampini cst = cst/cbs; 3041319c1dSStefano Zampini ierr = PetscMalloc4(mbs,&dnnz,mbs,&onnz,mbs,&dnnzu,mbs,&onnzu);CHKERRQ(ierr); 3141319c1dSStefano Zampini for (i=0; i<mbs; i++) { 3241319c1dSStefano Zampini dnnz[i] = nbs; 3341319c1dSStefano Zampini onnz[i] = Nbs - nbs; 3441319c1dSStefano Zampini dnnzu[i] = PetscMax(nbs - i,0); 3541319c1dSStefano Zampini onnzu[i] = PetscMax(Nbs - (cst + nbs),0); 3641319c1dSStefano Zampini } 3741319c1dSStefano Zampini ierr = MatXAIJSetPreallocation(mat,PETSC_DECIDE,dnnz,onnz,dnnzu,onnzu);CHKERRQ(ierr); 3841319c1dSStefano Zampini ierr = PetscFree4(dnnz,onnz,dnnzu,onnzu);CHKERRQ(ierr); 396696f472SJed Brown ierr = VecSetOption(in,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 4041319c1dSStefano Zampini ierr = MatSetUp(mat);CHKERRQ(ierr); 41*8af18dd8SStefano Zampini } else { 42*8af18dd8SStefano Zampini mat = *newmat; 43*8af18dd8SStefano Zampini ierr = MatZeroEntries(mat);CHKERRQ(ierr); 44*8af18dd8SStefano Zampini } 456696f472SJed Brown for (i=0; i<N; i++) { 4641319c1dSStefano Zampini PetscInt j; 4741319c1dSStefano Zampini 486696f472SJed Brown ierr = VecZeroEntries(in);CHKERRQ(ierr); 496696f472SJed Brown ierr = VecSetValue(in,i,1.,INSERT_VALUES);CHKERRQ(ierr); 506098dc10SBarry Smith ierr = VecAssemblyBegin(in);CHKERRQ(ierr); 516098dc10SBarry Smith ierr = VecAssemblyEnd(in);CHKERRQ(ierr); 526098dc10SBarry Smith ierr = MatMult(oldmat,in,out);CHKERRQ(ierr); 536098dc10SBarry Smith ierr = VecGetArray(out,&array);CHKERRQ(ierr); 5441319c1dSStefano Zampini for (j=0, im = 0; j<m; j++) { 5541319c1dSStefano Zampini if (PetscAbsScalar(array[j]) == 0.0) continue; 5641319c1dSStefano Zampini rows[im] = j+start; 5741319c1dSStefano Zampini array[im] = array[j]; 5841319c1dSStefano Zampini im++; 5941319c1dSStefano Zampini } 6041319c1dSStefano Zampini ierr = MatSetValues(mat,im,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 616098dc10SBarry Smith ierr = VecRestoreArray(out,&array);CHKERRQ(ierr); 626098dc10SBarry Smith } 63606d414cSSatish Balay ierr = PetscFree(rows);CHKERRQ(ierr); 646bf464f9SBarry Smith ierr = VecDestroy(&in);CHKERRQ(ierr); 656bf464f9SBarry Smith ierr = VecDestroy(&out);CHKERRQ(ierr); 66676c34cdSKris Buschelman ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 67676c34cdSKris Buschelman ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 68511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 6928be2f97SBarry Smith ierr = MatHeaderReplace(oldmat,&mat);CHKERRQ(ierr); 70c3d102feSKris Buschelman } else { 71676c34cdSKris Buschelman *newmat = mat; 72c3d102feSKris Buschelman } 733a40ed3dSBarry Smith PetscFunctionReturn(0); 746098dc10SBarry Smith } 75251fad3fSStefano Zampini 76251fad3fSStefano Zampini static PetscErrorCode MatGetDiagonal_CF(Mat A,Vec X) 77251fad3fSStefano Zampini { 78251fad3fSStefano Zampini Mat B; 79251fad3fSStefano Zampini PetscErrorCode ierr; 80251fad3fSStefano Zampini 81251fad3fSStefano Zampini PetscFunctionBegin; 82251fad3fSStefano Zampini ierr = MatShellGetContext(A,&B);CHKERRQ(ierr); 83251fad3fSStefano Zampini if (!B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 84251fad3fSStefano Zampini ierr = MatGetDiagonal(B,X);CHKERRQ(ierr); 85251fad3fSStefano Zampini PetscFunctionReturn(0); 86251fad3fSStefano Zampini } 87251fad3fSStefano Zampini 88251fad3fSStefano Zampini static PetscErrorCode MatMult_CF(Mat A,Vec X,Vec Y) 89251fad3fSStefano Zampini { 90251fad3fSStefano Zampini Mat B; 91251fad3fSStefano Zampini PetscErrorCode ierr; 92251fad3fSStefano Zampini 93251fad3fSStefano Zampini PetscFunctionBegin; 94251fad3fSStefano Zampini ierr = MatShellGetContext(A,&B);CHKERRQ(ierr); 95251fad3fSStefano Zampini if (!B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 96251fad3fSStefano Zampini ierr = MatMult(B,X,Y);CHKERRQ(ierr); 97251fad3fSStefano Zampini PetscFunctionReturn(0); 98251fad3fSStefano Zampini } 99251fad3fSStefano Zampini 100251fad3fSStefano Zampini static PetscErrorCode MatMultTranspose_CF(Mat A,Vec X,Vec Y) 101251fad3fSStefano Zampini { 102251fad3fSStefano Zampini Mat B; 103251fad3fSStefano Zampini PetscErrorCode ierr; 104251fad3fSStefano Zampini 105251fad3fSStefano Zampini PetscFunctionBegin; 106251fad3fSStefano Zampini ierr = MatShellGetContext(A,&B);CHKERRQ(ierr); 107251fad3fSStefano Zampini if (!B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 108251fad3fSStefano Zampini ierr = MatMultTranspose(B,X,Y);CHKERRQ(ierr); 109251fad3fSStefano Zampini PetscFunctionReturn(0); 110251fad3fSStefano Zampini } 111251fad3fSStefano Zampini 112251fad3fSStefano Zampini static PetscErrorCode MatDestroy_CF(Mat A) 113251fad3fSStefano Zampini { 114251fad3fSStefano Zampini Mat B; 115251fad3fSStefano Zampini PetscErrorCode ierr; 116251fad3fSStefano Zampini 117251fad3fSStefano Zampini PetscFunctionBegin; 118251fad3fSStefano Zampini ierr = MatShellGetContext(A,&B);CHKERRQ(ierr); 119251fad3fSStefano Zampini if (!B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing user matrix"); 120251fad3fSStefano Zampini ierr = MatDestroy(&B);CHKERRQ(ierr); 121b77ba244SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_anytype_C",NULL);CHKERRQ(ierr); 122b77ba244SStefano Zampini PetscFunctionReturn(0); 123b77ba244SStefano Zampini } 124b77ba244SStefano Zampini 125b77ba244SStefano Zampini typedef struct { 126b77ba244SStefano Zampini void *userdata; 127b77ba244SStefano Zampini PetscErrorCode (*userdestroy)(void*); 128b77ba244SStefano Zampini PetscErrorCode (*numeric)(Mat); 129b77ba244SStefano Zampini MatProductType ptype; 130b77ba244SStefano Zampini Mat Dwork; 131b77ba244SStefano Zampini } MatMatCF; 132b77ba244SStefano Zampini 133b77ba244SStefano Zampini static PetscErrorCode MatProductDestroy_CF(void *data) 134b77ba244SStefano Zampini { 135b77ba244SStefano Zampini PetscErrorCode ierr; 136b77ba244SStefano Zampini MatMatCF *mmcfdata = (MatMatCF*)data; 137b77ba244SStefano Zampini 138b77ba244SStefano Zampini PetscFunctionBegin; 139b77ba244SStefano Zampini if (mmcfdata->userdestroy) { 140b77ba244SStefano Zampini ierr = (*mmcfdata->userdestroy)(mmcfdata->userdata);CHKERRQ(ierr); 141b77ba244SStefano Zampini } 142b77ba244SStefano Zampini ierr = MatDestroy(&mmcfdata->Dwork);CHKERRQ(ierr); 143b77ba244SStefano Zampini ierr = PetscFree(mmcfdata);CHKERRQ(ierr); 144b77ba244SStefano Zampini PetscFunctionReturn(0); 145b77ba244SStefano Zampini } 146b77ba244SStefano Zampini 147b77ba244SStefano Zampini static PetscErrorCode MatProductNumericPhase_CF(Mat A, Mat B, Mat C, void *data) 148b77ba244SStefano Zampini { 149b77ba244SStefano Zampini PetscErrorCode ierr; 150b77ba244SStefano Zampini MatMatCF *mmcfdata = (MatMatCF*)data; 151b77ba244SStefano Zampini 152b77ba244SStefano Zampini PetscFunctionBegin; 153b77ba244SStefano Zampini if (!mmcfdata) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing data"); 154b77ba244SStefano Zampini if (!mmcfdata->numeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric operation"); 155b77ba244SStefano Zampini /* the MATSHELL interface allows us to play with the product data */ 156b77ba244SStefano Zampini ierr = PetscNew(&C->product);CHKERRQ(ierr); 157b77ba244SStefano Zampini C->product->type = mmcfdata->ptype; 158b77ba244SStefano Zampini C->product->data = mmcfdata->userdata; 159b77ba244SStefano Zampini C->product->Dwork = mmcfdata->Dwork; 160b77ba244SStefano Zampini ierr = MatShellGetContext(A,&C->product->A);CHKERRQ(ierr); 161b77ba244SStefano Zampini C->product->B = B; 162b77ba244SStefano Zampini ierr = (*mmcfdata->numeric)(C);CHKERRQ(ierr); 163b77ba244SStefano Zampini ierr = PetscFree(C->product);CHKERRQ(ierr); 164b77ba244SStefano Zampini PetscFunctionReturn(0); 165b77ba244SStefano Zampini } 166b77ba244SStefano Zampini 167b77ba244SStefano Zampini static PetscErrorCode MatProductSymbolicPhase_CF(Mat A, Mat B, Mat C, void **data) 168b77ba244SStefano Zampini { 169b77ba244SStefano Zampini PetscErrorCode ierr; 170b77ba244SStefano Zampini MatMatCF *mmcfdata; 171b77ba244SStefano Zampini 172b77ba244SStefano Zampini PetscFunctionBegin; 173b77ba244SStefano Zampini ierr = MatShellGetContext(A,&C->product->A);CHKERRQ(ierr); 174b77ba244SStefano Zampini ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 175b77ba244SStefano Zampini ierr = MatProductSymbolic(C);CHKERRQ(ierr); 176b77ba244SStefano Zampini /* the MATSHELL interface does not allow non-empty product data */ 177b77ba244SStefano Zampini ierr = PetscNew(&mmcfdata);CHKERRQ(ierr); 178b77ba244SStefano Zampini 179b77ba244SStefano Zampini mmcfdata->numeric = C->ops->productnumeric; 180b77ba244SStefano Zampini mmcfdata->ptype = C->product->type; 181b77ba244SStefano Zampini mmcfdata->userdata = C->product->data; 182b77ba244SStefano Zampini mmcfdata->userdestroy = C->product->destroy; 183b77ba244SStefano Zampini mmcfdata->Dwork = C->product->Dwork; 184b77ba244SStefano Zampini 185b77ba244SStefano Zampini C->product->Dwork = NULL; 186b77ba244SStefano Zampini C->product->data = NULL; 187b77ba244SStefano Zampini C->product->destroy = NULL; 188b77ba244SStefano Zampini C->product->A = A; 189b77ba244SStefano Zampini 190b77ba244SStefano Zampini *data = mmcfdata; 191b77ba244SStefano Zampini PetscFunctionReturn(0); 192b77ba244SStefano Zampini } 193b77ba244SStefano Zampini 194b77ba244SStefano Zampini /* only for A of type shell, mainly used for MatMat operations of shells with AXPYs */ 195b77ba244SStefano Zampini static PetscErrorCode MatProductSetFromOptions_CF(Mat D) 196b77ba244SStefano Zampini { 197b77ba244SStefano Zampini Mat A,B,Ain; 198b77ba244SStefano Zampini void (*Af)(void) = NULL; 199b77ba244SStefano Zampini PetscBool flg; 200b77ba244SStefano Zampini PetscErrorCode ierr; 201b77ba244SStefano Zampini 202b77ba244SStefano Zampini PetscFunctionBegin; 203b77ba244SStefano Zampini MatCheckProduct(D,1); 204b77ba244SStefano Zampini if (D->product->type == MATPRODUCT_ABC) PetscFunctionReturn(0); 205b77ba244SStefano Zampini A = D->product->A; 206b77ba244SStefano Zampini B = D->product->B; 207b77ba244SStefano Zampini ierr = MatIsShell(A,&flg);CHKERRQ(ierr); 208b77ba244SStefano Zampini if (!flg) PetscFunctionReturn(0); 209b77ba244SStefano Zampini ierr = PetscObjectQueryFunction((PetscObject)A,"MatProductSetFromOptions_anytype_C",&Af);CHKERRQ(ierr); 210b77ba244SStefano Zampini if (Af == (void(*)(void))MatProductSetFromOptions_CF) { 211b77ba244SStefano Zampini ierr = MatShellGetContext(A,&Ain);CHKERRQ(ierr); 212b77ba244SStefano Zampini } else PetscFunctionReturn(0); 213b77ba244SStefano Zampini D->product->A = Ain; 214b77ba244SStefano Zampini ierr = MatProductSetFromOptions(D);CHKERRQ(ierr); 215b77ba244SStefano Zampini D->product->A = A; 216b77ba244SStefano Zampini if (D->ops->productsymbolic) { /* we have a symbolic match, now populate the MATSHELL operations */ 217b77ba244SStefano Zampini ierr = MatShellSetMatProductOperation(A,D->product->type,MatProductSymbolicPhase_CF,MatProductNumericPhase_CF,MatProductDestroy_CF,((PetscObject)B)->type_name,NULL);CHKERRQ(ierr); 218b77ba244SStefano Zampini ierr = MatProductSetFromOptions(D);CHKERRQ(ierr); 219b77ba244SStefano Zampini } 220251fad3fSStefano Zampini PetscFunctionReturn(0); 221251fad3fSStefano Zampini } 222251fad3fSStefano Zampini 223251fad3fSStefano Zampini PetscErrorCode MatConvertFrom_Shell(Mat A, MatType newtype,MatReuse reuse,Mat *B) 224251fad3fSStefano Zampini { 225251fad3fSStefano Zampini Mat M; 226251fad3fSStefano Zampini PetscBool flg; 227251fad3fSStefano Zampini PetscErrorCode ierr; 228251fad3fSStefano Zampini 229251fad3fSStefano Zampini PetscFunctionBegin; 230251fad3fSStefano Zampini ierr = PetscStrcmp(newtype,MATSHELL,&flg);CHKERRQ(ierr); 231251fad3fSStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only conversion to MATSHELL"); 232251fad3fSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 233251fad3fSStefano Zampini ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 234251fad3fSStefano Zampini ierr = MatCreateShell(PetscObjectComm((PetscObject)A),A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,A,&M);CHKERRQ(ierr); 2351d9d9a34SStefano Zampini ierr = MatSetBlockSizesFromMats(M,A,A);CHKERRQ(ierr); 236251fad3fSStefano Zampini ierr = MatShellSetOperation(M,MATOP_MULT, (void (*)(void))MatMult_CF);CHKERRQ(ierr); 237251fad3fSStefano Zampini ierr = MatShellSetOperation(M,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_CF);CHKERRQ(ierr); 238251fad3fSStefano Zampini ierr = MatShellSetOperation(M,MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_CF);CHKERRQ(ierr); 239251fad3fSStefano Zampini ierr = MatShellSetOperation(M,MATOP_DESTROY, (void (*)(void))MatDestroy_CF);CHKERRQ(ierr); 240b77ba244SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)M,"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_CF);CHKERRQ(ierr); 2413d392a07SStefano Zampini ierr = PetscFree(M->defaultvectype);CHKERRQ(ierr); 2423d392a07SStefano Zampini ierr = PetscStrallocpy(A->defaultvectype,&M->defaultvectype);CHKERRQ(ierr); 2432487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 2442487f3f2SStefano Zampini ierr = MatBindToCPU(M,A->boundtocpu);CHKERRQ(ierr); 2452487f3f2SStefano Zampini #endif 246251fad3fSStefano Zampini *B = M; 247251fad3fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented"); 248251fad3fSStefano Zampini PetscFunctionReturn(0); 249251fad3fSStefano Zampini } 250