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