xref: /petsc/src/mat/impls/shell/shellcnv.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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