#include /*I "petscmat.h" I*/ PetscErrorCode MatConvert_Shell(Mat oldmat,MatType newtype,MatReuse reuse,Mat *newmat) { Mat mat; Vec in,out; PetscScalar *array; PetscInt *dnnz,*onnz,*dnnzu,*onnzu; PetscInt cst,Nbs,mbs,nbs,rbs,cbs; PetscInt im,i,m,n,M,N,*rows,start; PetscFunctionBegin; CHKERRQ(MatGetOwnershipRange(oldmat,&start,NULL)); CHKERRQ(MatGetOwnershipRangeColumn(oldmat,&cst,NULL)); CHKERRQ(MatCreateVecs(oldmat,&in,&out)); CHKERRQ(MatGetLocalSize(oldmat,&m,&n)); CHKERRQ(MatGetSize(oldmat,&M,&N)); CHKERRQ(PetscMalloc1(m,&rows)); if (reuse != MAT_REUSE_MATRIX) { CHKERRQ(MatCreate(PetscObjectComm((PetscObject)oldmat),&mat)); CHKERRQ(MatSetSizes(mat,m,n,M,N)); CHKERRQ(MatSetType(mat,newtype)); CHKERRQ(MatSetBlockSizesFromMats(mat,oldmat,oldmat)); CHKERRQ(MatGetBlockSizes(mat,&rbs,&cbs)); mbs = m/rbs; nbs = n/cbs; Nbs = N/cbs; cst = cst/cbs; CHKERRQ(PetscMalloc4(mbs,&dnnz,mbs,&onnz,mbs,&dnnzu,mbs,&onnzu)); for (i=0; iuserdestroy) { CHKERRQ((*mmcfdata->userdestroy)(mmcfdata->userdata)); } CHKERRQ(MatDestroy(&mmcfdata->Dwork)); CHKERRQ(PetscFree(mmcfdata)); PetscFunctionReturn(0); } static PetscErrorCode MatProductNumericPhase_CF(Mat A, Mat B, Mat C, void *data) { MatMatCF *mmcfdata = (MatMatCF*)data; PetscFunctionBegin; PetscCheck(mmcfdata,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing data"); PetscCheck(mmcfdata->numeric,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric operation"); /* the MATSHELL interface allows us to play with the product data */ CHKERRQ(PetscNew(&C->product)); C->product->type = mmcfdata->ptype; C->product->data = mmcfdata->userdata; C->product->Dwork = mmcfdata->Dwork; CHKERRQ(MatShellGetContext(A,&C->product->A)); C->product->B = B; CHKERRQ((*mmcfdata->numeric)(C)); CHKERRQ(PetscFree(C->product)); PetscFunctionReturn(0); } static PetscErrorCode MatProductSymbolicPhase_CF(Mat A, Mat B, Mat C, void **data) { MatMatCF *mmcfdata; PetscFunctionBegin; CHKERRQ(MatShellGetContext(A,&C->product->A)); CHKERRQ(MatProductSetFromOptions(C)); CHKERRQ(MatProductSymbolic(C)); /* the MATSHELL interface does not allow non-empty product data */ CHKERRQ(PetscNew(&mmcfdata)); mmcfdata->numeric = C->ops->productnumeric; mmcfdata->ptype = C->product->type; mmcfdata->userdata = C->product->data; mmcfdata->userdestroy = C->product->destroy; mmcfdata->Dwork = C->product->Dwork; C->product->Dwork = NULL; C->product->data = NULL; C->product->destroy = NULL; C->product->A = A; *data = mmcfdata; PetscFunctionReturn(0); } /* only for A of type shell, mainly used for MatMat operations of shells with AXPYs */ static PetscErrorCode MatProductSetFromOptions_CF(Mat D) { Mat A,B,Ain; void (*Af)(void) = NULL; PetscBool flg; PetscFunctionBegin; MatCheckProduct(D,1); if (D->product->type == MATPRODUCT_ABC) PetscFunctionReturn(0); A = D->product->A; B = D->product->B; CHKERRQ(MatIsShell(A,&flg)); if (!flg) PetscFunctionReturn(0); CHKERRQ(PetscObjectQueryFunction((PetscObject)A,"MatProductSetFromOptions_anytype_C",&Af)); if (Af == (void(*)(void))MatProductSetFromOptions_CF) { CHKERRQ(MatShellGetContext(A,&Ain)); } else PetscFunctionReturn(0); D->product->A = Ain; CHKERRQ(MatProductSetFromOptions(D)); D->product->A = A; if (D->ops->productsymbolic) { /* we have a symbolic match, now populate the MATSHELL operations */ CHKERRQ(MatShellSetMatProductOperation(A,D->product->type,MatProductSymbolicPhase_CF,MatProductNumericPhase_CF,MatProductDestroy_CF,((PetscObject)B)->type_name,NULL)); CHKERRQ(MatProductSetFromOptions(D)); } PetscFunctionReturn(0); } PetscErrorCode MatConvertFrom_Shell(Mat A,MatType newtype,MatReuse reuse,Mat *B) { Mat M; PetscBool flg; PetscFunctionBegin; CHKERRQ(PetscStrcmp(newtype,MATSHELL,&flg)); PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only conversion to MATSHELL"); if (reuse == MAT_INITIAL_MATRIX) { CHKERRQ(PetscObjectReference((PetscObject)A)); CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject)A),A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,A,&M)); CHKERRQ(MatSetBlockSizesFromMats(M,A,A)); CHKERRQ(MatShellSetOperation(M,MATOP_MULT, (void (*)(void))MatMult_CF)); CHKERRQ(MatShellSetOperation(M,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_CF)); CHKERRQ(MatShellSetOperation(M,MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_CF)); CHKERRQ(MatShellSetOperation(M,MATOP_DESTROY, (void (*)(void))MatDestroy_CF)); CHKERRQ(PetscObjectComposeFunction((PetscObject)M,"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_CF)); CHKERRQ(PetscFree(M->defaultvectype)); CHKERRQ(PetscStrallocpy(A->defaultvectype,&M->defaultvectype)); #if defined(PETSC_HAVE_DEVICE) CHKERRQ(MatBindToCPU(M,A->boundtocpu)); #endif *B = M; } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented"); PetscFunctionReturn(0); }