xref: /petsc/src/mat/interface/matproduct.c (revision 7a3c3d58f0dc30013810dc66cc68344148a68c77)
14222ddf1SHong Zhang 
24222ddf1SHong Zhang /*
34222ddf1SHong Zhang     Routines for matrix products. Calling procedure:
44222ddf1SHong Zhang 
54222ddf1SHong Zhang     MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D);
64222ddf1SHong Zhang     MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC);
74222ddf1SHong Zhang     MatProductSetAlgorithm(D, alg);
84222ddf1SHong Zhang     MatProductSetFill(D,fill);
94222ddf1SHong Zhang     MatProductSetFromOptions(D);
104222ddf1SHong Zhang       -> MatProductSetFromOptions_producttype(D):
114222ddf1SHong Zhang            # Check matrix global sizes
124222ddf1SHong Zhang            -> MatProductSetFromOptions_Atype_Btype_Ctype(D);
134222ddf1SHong Zhang                 ->MatProductSetFromOptions_Atype_Btype_Ctype_productype(D):
144222ddf1SHong Zhang                     # Check matrix local sizes for mpi matrices
154222ddf1SHong Zhang                     # Set default algorithm
164222ddf1SHong Zhang                     # Get runtime option
174222ddf1SHong Zhang                     # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype;
184222ddf1SHong Zhang 
194222ddf1SHong Zhang     PetscLogEventBegin()
204222ddf1SHong Zhang     MatProductSymbolic(D):
214222ddf1SHong Zhang       # Call MatxxxSymbolic_Atype_Btype_Ctype();
224222ddf1SHong Zhang       # Set D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype;
234222ddf1SHong Zhang     PetscLogEventEnd()
244222ddf1SHong Zhang 
254222ddf1SHong Zhang     PetscLogEventBegin()
264222ddf1SHong Zhang     MatProductNumeric(D);
274222ddf1SHong Zhang       # Call (D->ops->matxxxnumeric)();
284222ddf1SHong Zhang     PetscLogEventEnd()
294222ddf1SHong Zhang */
304222ddf1SHong Zhang 
314222ddf1SHong Zhang #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
324222ddf1SHong Zhang 
33544a5e07SHong Zhang const char *const MatProductTypes[] = {"AB","AtB","ABt","PtAP","RARt","ABC","MatProductType","MAT_Product_",0};
34544a5e07SHong Zhang 
354222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C)
364222ddf1SHong Zhang {
374222ddf1SHong Zhang   PetscErrorCode ierr;
384222ddf1SHong Zhang   Mat_Product    *product = C->product;
394222ddf1SHong Zhang   Mat            P = product->B,AP = product->Dwork;
404222ddf1SHong Zhang 
414222ddf1SHong Zhang   PetscFunctionBegin;
424222ddf1SHong Zhang   /* AP = A*P */
434222ddf1SHong Zhang   ierr = MatProductNumeric(AP);CHKERRQ(ierr);
444222ddf1SHong Zhang   /* C = P^T*AP */
45*7a3c3d58SStefano Zampini   if (!C->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
46*7a3c3d58SStefano Zampini   ierr = (*C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr);
474222ddf1SHong Zhang   PetscFunctionReturn(0);
484222ddf1SHong Zhang }
494222ddf1SHong Zhang 
504222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C)
514222ddf1SHong Zhang {
524222ddf1SHong Zhang   PetscErrorCode ierr;
534222ddf1SHong Zhang   Mat_Product    *product = C->product;
544222ddf1SHong Zhang   Mat            A=product->A,P=product->B,AP;
554222ddf1SHong Zhang   PetscReal      fill=product->fill;
564222ddf1SHong Zhang 
574222ddf1SHong Zhang   PetscFunctionBegin;
584222ddf1SHong Zhang   /* AP = A*P */
594222ddf1SHong Zhang   ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr);
604222ddf1SHong Zhang   ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr);
61*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(AP,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
624222ddf1SHong Zhang   ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr);
634222ddf1SHong Zhang   ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr);
644222ddf1SHong Zhang   ierr = MatProductSymbolic(AP);CHKERRQ(ierr);
654222ddf1SHong Zhang 
664222ddf1SHong Zhang   /* C = P^T*AP */
674222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr);
68*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
694222ddf1SHong Zhang   product->A = P;
704222ddf1SHong Zhang   product->B = AP;
714222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
724222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
734222ddf1SHong Zhang 
744222ddf1SHong Zhang   /* resume user's original input matrix setting for A and B */
754222ddf1SHong Zhang   product->A     = A;
764222ddf1SHong Zhang   product->B     = P;
774222ddf1SHong Zhang   product->Dwork = AP;
784222ddf1SHong Zhang 
794222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP_Basic;
804222ddf1SHong Zhang   PetscFunctionReturn(0);
814222ddf1SHong Zhang }
824222ddf1SHong Zhang 
834222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C)
844222ddf1SHong Zhang {
854222ddf1SHong Zhang   PetscErrorCode ierr;
864222ddf1SHong Zhang   Mat_Product    *product = C->product;
874222ddf1SHong Zhang   Mat            R=product->B,RA=product->Dwork;
884222ddf1SHong Zhang 
894222ddf1SHong Zhang   PetscFunctionBegin;
904222ddf1SHong Zhang   /* RA = R*A */
914222ddf1SHong Zhang   ierr = MatProductNumeric(RA);CHKERRQ(ierr);
924222ddf1SHong Zhang   /* C = RA*R^T */
93*7a3c3d58SStefano Zampini   if (!C->ops->mattransposemultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
94*7a3c3d58SStefano Zampini   ierr = (*C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr);
954222ddf1SHong Zhang   PetscFunctionReturn(0);
964222ddf1SHong Zhang }
974222ddf1SHong Zhang 
984222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C)
994222ddf1SHong Zhang {
1004222ddf1SHong Zhang   PetscErrorCode ierr;
1014222ddf1SHong Zhang   Mat_Product    *product = C->product;
1024222ddf1SHong Zhang   Mat            A=product->A,R=product->B,RA;
1034222ddf1SHong Zhang   PetscReal      fill=product->fill;
1044222ddf1SHong Zhang 
1054222ddf1SHong Zhang   PetscFunctionBegin;
1064222ddf1SHong Zhang   /* RA = R*A */
1074222ddf1SHong Zhang   ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr);
1084222ddf1SHong Zhang   ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr);
109*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(RA,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1104222ddf1SHong Zhang   ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr);
1114222ddf1SHong Zhang   ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr);
1124222ddf1SHong Zhang   ierr = MatProductSymbolic(RA);CHKERRQ(ierr);
1134222ddf1SHong Zhang 
1144222ddf1SHong Zhang   /* C = RA*R^T */
1154222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr);
116*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1174222ddf1SHong Zhang   product->A = RA;
1184222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
1194222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
1204222ddf1SHong Zhang 
1214222ddf1SHong Zhang   /* resume user's original input matrix setting for A */
1224222ddf1SHong Zhang   product->A     = A;
1234222ddf1SHong Zhang   product->Dwork = RA; /* save here so it will be destroyed with product C */
1244222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_RARt_Basic;
1254222ddf1SHong Zhang   PetscFunctionReturn(0);
1264222ddf1SHong Zhang }
1274222ddf1SHong Zhang 
1284222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat)
1294222ddf1SHong Zhang {
1304222ddf1SHong Zhang   PetscErrorCode ierr;
1314222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1324222ddf1SHong Zhang   Mat            A=product->A,BC=product->Dwork;
1334222ddf1SHong Zhang 
1344222ddf1SHong Zhang   PetscFunctionBegin;
1354222ddf1SHong Zhang   /* Numeric BC = B*C */
1364222ddf1SHong Zhang   ierr = MatProductNumeric(BC);CHKERRQ(ierr);
1374222ddf1SHong Zhang   /* Numeric mat = A*BC */
138*7a3c3d58SStefano Zampini   if (!mat->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage");
139*7a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr);
1404222ddf1SHong Zhang   PetscFunctionReturn(0);
1414222ddf1SHong Zhang }
1424222ddf1SHong Zhang 
1434222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat)
1444222ddf1SHong Zhang {
1454222ddf1SHong Zhang   PetscErrorCode ierr;
1464222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1474222ddf1SHong Zhang   Mat            B=product->B,C=product->C,BC;
1484222ddf1SHong Zhang   PetscReal      fill=product->fill;
1494222ddf1SHong Zhang 
1504222ddf1SHong Zhang   PetscFunctionBegin;
1514222ddf1SHong Zhang   /* Symbolic BC = B*C */
1524222ddf1SHong Zhang   ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr);
1534222ddf1SHong Zhang   ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr);
154*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1554222ddf1SHong Zhang   ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr);
1564222ddf1SHong Zhang   ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr);
1574222ddf1SHong Zhang   ierr = MatProductSymbolic(BC);CHKERRQ(ierr);
1584222ddf1SHong Zhang 
1594222ddf1SHong Zhang   /* Symbolic mat = A*BC */
1604222ddf1SHong Zhang   ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr);
161*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(mat,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1624222ddf1SHong Zhang   product->B     = BC;
1634222ddf1SHong Zhang   product->Dwork = BC;
1644222ddf1SHong Zhang   ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr);
1654222ddf1SHong Zhang   ierr = MatProductSymbolic(mat);CHKERRQ(ierr);
1664222ddf1SHong Zhang 
1674222ddf1SHong Zhang   /* resume user's original input matrix setting for B */
1684222ddf1SHong Zhang   product->B = B;
1694222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC_Basic;
1704222ddf1SHong Zhang   PetscFunctionReturn(0);
1714222ddf1SHong Zhang }
1724222ddf1SHong Zhang 
1734222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_Basic(Mat mat)
1744222ddf1SHong Zhang {
1754222ddf1SHong Zhang   PetscErrorCode ierr;
1764222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1774222ddf1SHong Zhang 
1784222ddf1SHong Zhang   PetscFunctionBegin;
1794222ddf1SHong Zhang   switch (product->type) {
1804222ddf1SHong Zhang   case MATPRODUCT_PtAP:
181*7a3c3d58SStefano Zampini     ierr = PetscInfo2((PetscObject)mat, "MatProduct_Basic_PtAP() for A %s, P %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr);
1824222ddf1SHong Zhang     ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr);
1834222ddf1SHong Zhang     break;
1844222ddf1SHong Zhang   case MATPRODUCT_RARt:
185*7a3c3d58SStefano Zampini     ierr = PetscInfo2((PetscObject)mat, "MatProduct_Basic_RARt() for A %s, R %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr);
1864222ddf1SHong Zhang     ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr);
1874222ddf1SHong Zhang     break;
1884222ddf1SHong Zhang   case MATPRODUCT_ABC:
189*7a3c3d58SStefano Zampini     ierr = PetscInfo3((PetscObject)mat, "MatProduct_Basic_ABC() for A %s, B %s, C %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name,((PetscObject)product->C)->type_name);CHKERRQ(ierr);
1904222ddf1SHong Zhang     ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr);
1914222ddf1SHong Zhang     break;
1924222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported");
1934222ddf1SHong Zhang   }
1944222ddf1SHong Zhang   PetscFunctionReturn(0);
1954222ddf1SHong Zhang }
1964222ddf1SHong Zhang 
1974222ddf1SHong Zhang /* ----------------------------------------------- */
1984222ddf1SHong Zhang /*@C
1994222ddf1SHong Zhang    MatProductReplaceMats - Replace input matrices for a matrix product.
2004222ddf1SHong Zhang 
2014222ddf1SHong Zhang    Collective on Mat
2024222ddf1SHong Zhang 
2034222ddf1SHong Zhang    Input Parameters:
2044222ddf1SHong Zhang +  A - the matrix or NULL if not being replaced
2054222ddf1SHong Zhang .  B - the matrix or NULL if not being replaced
2064222ddf1SHong Zhang .  C - the matrix or NULL if not being replaced
2074222ddf1SHong Zhang -  D - the matrix product
2084222ddf1SHong Zhang 
2094222ddf1SHong Zhang    Level: intermediate
2104222ddf1SHong Zhang 
2114222ddf1SHong Zhang    Notes:
2124222ddf1SHong Zhang      Input matrix must have exactly same data structure as replaced one.
2134222ddf1SHong Zhang 
2144222ddf1SHong Zhang .seealso: MatProductCreate()
2154222ddf1SHong Zhang @*/
2164222ddf1SHong Zhang PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D)
2174222ddf1SHong Zhang {
2184417c5e8SHong Zhang   PetscErrorCode ierr;
2194222ddf1SHong Zhang   Mat_Product    *product=D->product;
2204222ddf1SHong Zhang 
2214222ddf1SHong Zhang   PetscFunctionBegin;
222*7a3c3d58SStefano Zampini   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
223*7a3c3d58SStefano Zampini   if (!product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ORDER,"Mat D does not have struct 'product'. Call MatProductReplaceProduct()");
2244222ddf1SHong Zhang   if (A) {
225*7a3c3d58SStefano Zampini     PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2264222ddf1SHong Zhang     if (!product->Areplaced) {
2274417c5e8SHong Zhang       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); /* take ownership of input */
2284417c5e8SHong Zhang       ierr = MatDestroy(&product->A);CHKERRQ(ierr); /* release old reference */
2294222ddf1SHong Zhang       product->A = A;
2304222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix A was changed by a PETSc internal routine, cannot be replaced");
2314222ddf1SHong Zhang   }
2324222ddf1SHong Zhang   if (B) {
233*7a3c3d58SStefano Zampini     PetscValidHeaderSpecific(B,MAT_CLASSID,2);
2344222ddf1SHong Zhang     if (!product->Breplaced) {
2354417c5e8SHong Zhang       ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); /* take ownership of input */
2364417c5e8SHong Zhang       ierr = MatDestroy(&product->B);CHKERRQ(ierr); /* release old reference */
2374222ddf1SHong Zhang       product->B = B;
2384222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix B was changed by a PETSc internal routine, cannot be replaced");
2394222ddf1SHong Zhang   }
2404417c5e8SHong Zhang   if (C) {
241*7a3c3d58SStefano Zampini     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
2424417c5e8SHong Zhang     ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); /* take ownership of input */
2434417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr); /* release old reference */
2444417c5e8SHong Zhang     product->C = C;
2454417c5e8SHong Zhang   }
2464222ddf1SHong Zhang   PetscFunctionReturn(0);
2474222ddf1SHong Zhang }
2484222ddf1SHong Zhang 
249*7a3c3d58SStefano Zampini static PetscErrorCode MatProductNumeric_X_Dense(Mat C)
250*7a3c3d58SStefano Zampini {
251*7a3c3d58SStefano Zampini   PetscErrorCode ierr;
252*7a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
253*7a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
254*7a3c3d58SStefano Zampini   PetscInt       k, K = B->cmap->N;
255*7a3c3d58SStefano Zampini   PetscBool      t = PETSC_TRUE,iscuda = PETSC_FALSE;
256*7a3c3d58SStefano Zampini   PetscBool      Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE;
257*7a3c3d58SStefano Zampini   char           *Btype = NULL,*Ctype = NULL;
258*7a3c3d58SStefano Zampini 
259*7a3c3d58SStefano Zampini   PetscFunctionBegin;
260*7a3c3d58SStefano Zampini   switch (product->type) {
261*7a3c3d58SStefano Zampini   case MATPRODUCT_AB:
262*7a3c3d58SStefano Zampini     t = PETSC_FALSE;
263*7a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
264*7a3c3d58SStefano Zampini     break;
265*7a3c3d58SStefano Zampini   default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProductNumeric type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name);
266*7a3c3d58SStefano Zampini   }
267*7a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
268*7a3c3d58SStefano Zampini     VecType vtype;
269*7a3c3d58SStefano Zampini 
270*7a3c3d58SStefano Zampini     ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr);
271*7a3c3d58SStefano Zampini     ierr = PetscStrcmp(vtype,VECCUDA,&iscuda);CHKERRQ(ierr);
272*7a3c3d58SStefano Zampini     if (!iscuda) {
273*7a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
274*7a3c3d58SStefano Zampini     }
275*7a3c3d58SStefano Zampini     if (!iscuda) {
276*7a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECMPICUDA,&iscuda);CHKERRQ(ierr);
277*7a3c3d58SStefano Zampini     }
278*7a3c3d58SStefano Zampini     if (iscuda) { /* Make sure we have up-to-date data on the GPU */
279*7a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)B)->type_name,&Btype);CHKERRQ(ierr);
280*7a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)C)->type_name,&Ctype);CHKERRQ(ierr);
281*7a3c3d58SStefano Zampini       ierr = MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
282*7a3c3d58SStefano Zampini       if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */
283*7a3c3d58SStefano Zampini         ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
284*7a3c3d58SStefano Zampini         ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
285*7a3c3d58SStefano Zampini       }
286*7a3c3d58SStefano Zampini       ierr = MatConvert(C,MATDENSECUDA,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
287*7a3c3d58SStefano Zampini     } else { /* Make sure we have up-to-date data on the CPU */
288*7a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
289*7a3c3d58SStefano Zampini       Bcpu = B->boundtocpu;
290*7a3c3d58SStefano Zampini       Ccpu = C->boundtocpu;
291*7a3c3d58SStefano Zampini #endif
292*7a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,PETSC_TRUE);CHKERRQ(ierr);
293*7a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,PETSC_TRUE);CHKERRQ(ierr);
294*7a3c3d58SStefano Zampini     }
295*7a3c3d58SStefano Zampini   }
296*7a3c3d58SStefano Zampini   for (k=0;k<K;k++) {
297*7a3c3d58SStefano Zampini     Vec x,y;
298*7a3c3d58SStefano Zampini 
299*7a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecRead(B,k,&x);CHKERRQ(ierr);
300*7a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecWrite(C,k,&y);CHKERRQ(ierr);
301*7a3c3d58SStefano Zampini     if (t) {
302*7a3c3d58SStefano Zampini       ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr);
303*7a3c3d58SStefano Zampini     } else {
304*7a3c3d58SStefano Zampini       ierr = MatMult(A,x,y);CHKERRQ(ierr);
305*7a3c3d58SStefano Zampini     }
306*7a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecRead(B,k,&x);CHKERRQ(ierr);
307*7a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecWrite(C,k,&y);CHKERRQ(ierr);
308*7a3c3d58SStefano Zampini   }
309*7a3c3d58SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
310*7a3c3d58SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
311*7a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
312*7a3c3d58SStefano Zampini     if (iscuda) {
313*7a3c3d58SStefano Zampini       ierr = MatConvert(B,Btype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
314*7a3c3d58SStefano Zampini       ierr = MatConvert(C,Ctype,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
315*7a3c3d58SStefano Zampini     } else {
316*7a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,Bcpu);CHKERRQ(ierr);
317*7a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,Ccpu);CHKERRQ(ierr);
318*7a3c3d58SStefano Zampini     }
319*7a3c3d58SStefano Zampini   }
320*7a3c3d58SStefano Zampini   ierr = PetscFree(Btype);CHKERRQ(ierr);
321*7a3c3d58SStefano Zampini   ierr = PetscFree(Ctype);CHKERRQ(ierr);
322*7a3c3d58SStefano Zampini   PetscFunctionReturn(0);
323*7a3c3d58SStefano Zampini }
324*7a3c3d58SStefano Zampini 
325*7a3c3d58SStefano Zampini static PetscErrorCode MatProductSymbolic_X_Dense(Mat C)
326*7a3c3d58SStefano Zampini {
327*7a3c3d58SStefano Zampini   PetscErrorCode ierr;
328*7a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
329*7a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
330*7a3c3d58SStefano Zampini   PetscBool      isdense;
331*7a3c3d58SStefano Zampini 
332*7a3c3d58SStefano Zampini   PetscFunctionBegin;
333*7a3c3d58SStefano Zampini   switch (product->type) {
334*7a3c3d58SStefano Zampini   case MATPRODUCT_AB:
335*7a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,A->rmap->N,B->cmap->N);CHKERRQ(ierr);
336*7a3c3d58SStefano Zampini     break;
337*7a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
338*7a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,B->cmap->n,A->cmap->N,B->cmap->N);CHKERRQ(ierr);
339*7a3c3d58SStefano Zampini     break;
340*7a3c3d58SStefano Zampini   default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProductSymbolic type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name);
341*7a3c3d58SStefano Zampini   }
342*7a3c3d58SStefano Zampini   ierr = PetscObjectBaseTypeCompareAny((PetscObject)C,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
343*7a3c3d58SStefano Zampini   if (!isdense) {
344*7a3c3d58SStefano Zampini     ierr = MatSetType(C,((PetscObject)B)->type_name);CHKERRQ(ierr);
345*7a3c3d58SStefano Zampini     /* If matrix type of C was not set or not dense, we need to reset this pointers */
346*7a3c3d58SStefano Zampini     C->ops->productsymbolic = MatProductSymbolic_X_Dense;
347*7a3c3d58SStefano Zampini     C->ops->productnumeric  = MatProductNumeric_X_Dense;
348*7a3c3d58SStefano Zampini   }
349*7a3c3d58SStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
350*7a3c3d58SStefano Zampini   PetscFunctionReturn(0);
351*7a3c3d58SStefano Zampini }
352*7a3c3d58SStefano Zampini 
353*7a3c3d58SStefano Zampini static PetscErrorCode MatProductSetFromOptions_X_Dense(Mat C)
354*7a3c3d58SStefano Zampini {
355*7a3c3d58SStefano Zampini   Mat_Product *product = C->product;
356*7a3c3d58SStefano Zampini   Mat         A = product->A, B = product->B;
357*7a3c3d58SStefano Zampini 
358*7a3c3d58SStefano Zampini   PetscFunctionBegin;
359*7a3c3d58SStefano Zampini   C->ops->productsymbolic = NULL;
360*7a3c3d58SStefano Zampini   C->ops->productnumeric  = NULL;
361*7a3c3d58SStefano Zampini   switch (product->type) {
362*7a3c3d58SStefano Zampini   case MATPRODUCT_AB:
363*7a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
364*7a3c3d58SStefano Zampini     C->ops->productsymbolic = MatProductSymbolic_X_Dense;
365*7a3c3d58SStefano Zampini     C->ops->productnumeric  = MatProductNumeric_X_Dense;
366*7a3c3d58SStefano Zampini     break;
367*7a3c3d58SStefano Zampini   default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProduct type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name);
368*7a3c3d58SStefano Zampini   }
369*7a3c3d58SStefano Zampini   PetscFunctionReturn(0);
370*7a3c3d58SStefano Zampini }
371*7a3c3d58SStefano Zampini 
3724222ddf1SHong Zhang /* ----------------------------------------------- */
3734222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AB(Mat mat)
3744222ddf1SHong Zhang {
3754222ddf1SHong Zhang   PetscErrorCode ierr;
3764222ddf1SHong Zhang   Mat_Product    *product = mat->product;
3774222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
3784222ddf1SHong Zhang   PetscBool      sametype;
3794222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
3804222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
3814222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
3824222ddf1SHong Zhang   PetscBool      A_istrans,B_istrans;
3834222ddf1SHong Zhang 
3844222ddf1SHong Zhang   PetscFunctionBegin;
3854222ddf1SHong Zhang   /* Check matrix global sizes */
3864222ddf1SHong Zhang   if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
3874222ddf1SHong Zhang 
3884222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
3894222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
3904222ddf1SHong Zhang 
3914222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
3924222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&A_istrans);CHKERRQ(ierr);
3934222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&B_istrans);CHKERRQ(ierr);
3946896283bSStefano Zampini   ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
3954222ddf1SHong Zhang 
3964222ddf1SHong Zhang   if (fB == fA && sametype && (!A_istrans || !B_istrans)) {
3976896283bSStefano Zampini     ierr = PetscInfo(mat,"  sametype and matching op\n");CHKERRQ(ierr);
3984222ddf1SHong Zhang     f = fB;
3994222ddf1SHong Zhang   } else {
4004222ddf1SHong Zhang     char      mtypes[256];
4014222ddf1SHong Zhang     PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE;
4024222ddf1SHong Zhang     Mat       At = NULL,Bt = NULL;
4034222ddf1SHong Zhang 
4044222ddf1SHong Zhang     if (A_istrans && !B_istrans) {
4054222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
4064222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
4074222ddf1SHong Zhang       if (At_istrans) { /* mat = ATT * B */
4084222ddf1SHong Zhang         Mat Att = NULL;
4094222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
4104417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
4114417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
4124222ddf1SHong Zhang         A                  = Att;
4134222ddf1SHong Zhang         product->A         = Att; /* use Att for matproduct */
4144222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */
4154222ddf1SHong Zhang       } else { /* !At_istrans: mat = At^T*B */
4164417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)At);CHKERRQ(ierr);
4174417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
4184222ddf1SHong Zhang         A                  = At;
4194222ddf1SHong Zhang         product->A         = At;
4204222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE;
4214222ddf1SHong Zhang         product->type      = MATPRODUCT_AtB;
4224222ddf1SHong Zhang       }
4234222ddf1SHong Zhang     } else if (!A_istrans && B_istrans) {
4244222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
4254222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
4264222ddf1SHong Zhang       if (Bt_istrans) { /* mat = A * BTT */
4274222ddf1SHong Zhang         Mat Btt = NULL;
4284222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
4294417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
4304417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
4314222ddf1SHong Zhang         B                  = Btt;
4324222ddf1SHong Zhang         product->B         = Btt; /* use Btt for matproduct */
4334222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
4344222ddf1SHong Zhang       } else { /* !Bt_istrans */
4354222ddf1SHong Zhang         /* mat = A*Bt^T */
4364417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Bt);CHKERRQ(ierr);
4374417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
4384222ddf1SHong Zhang         B                  = Bt;
4394222ddf1SHong Zhang         product->B         = Bt;
4404222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
4414222ddf1SHong Zhang         product->type = MATPRODUCT_ABt;
4424222ddf1SHong Zhang       }
4434222ddf1SHong Zhang     } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */
4444222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
4454222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
4464222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
4474222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
4484222ddf1SHong Zhang       if (At_istrans && Bt_istrans) {
4494222ddf1SHong Zhang         Mat Att= NULL,Btt = NULL;
4504222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
4514222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
4524417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
4534417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
4544417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
4554417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
4564222ddf1SHong Zhang         A             = Att;
4574222ddf1SHong Zhang         product->A    = Att; product->Areplaced = PETSC_TRUE;
4584222ddf1SHong Zhang         B             = Btt;
4594222ddf1SHong Zhang         product->B    = Btt; product->Breplaced = PETSC_TRUE;
4604222ddf1SHong Zhang       } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet");
4614222ddf1SHong Zhang     }
4624222ddf1SHong Zhang 
4634222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
4644222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4654222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4664222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4674222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4684222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4694222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
470*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
4714222ddf1SHong Zhang     if (!f) {
4724222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
473*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
4744222ddf1SHong Zhang     }
4754222ddf1SHong Zhang   }
4764222ddf1SHong Zhang 
477*7a3c3d58SStefano Zampini   /* last chance, we can still compute the product if B is of type dense */
478*7a3c3d58SStefano Zampini   if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) {
479*7a3c3d58SStefano Zampini     PetscBool isdense;
480*7a3c3d58SStefano Zampini 
481*7a3c3d58SStefano Zampini     ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
482*7a3c3d58SStefano Zampini     if (isdense) {
483*7a3c3d58SStefano Zampini       f    = MatProductSetFromOptions_X_Dense;
484*7a3c3d58SStefano Zampini       ierr = PetscInfo(mat,"  using basic looping over columns of a dense matrix\n");CHKERRQ(ierr);
485*7a3c3d58SStefano Zampini     }
486*7a3c3d58SStefano Zampini   }
487*7a3c3d58SStefano Zampini 
488*7a3c3d58SStefano Zampini   if (f) {
4894222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
490*7a3c3d58SStefano Zampini   } else { /* reset pointers since the matrix types combination is not available */
491*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
492*7a3c3d58SStefano Zampini     mat->ops->productsymbolic = NULL;
493*7a3c3d58SStefano Zampini     mat->ops->productnumeric  = NULL;
494*7a3c3d58SStefano Zampini   }
4954222ddf1SHong Zhang   PetscFunctionReturn(0);
4964222ddf1SHong Zhang }
4974222ddf1SHong Zhang 
4984222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat)
4994222ddf1SHong Zhang {
5004222ddf1SHong Zhang   PetscErrorCode ierr;
5014222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5024222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5034222ddf1SHong Zhang   PetscBool      sametype;
5044222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5054222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5064222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5074222ddf1SHong Zhang 
5084222ddf1SHong Zhang   PetscFunctionBegin;
5094222ddf1SHong Zhang   /* Check matrix global sizes */
5104222ddf1SHong Zhang   if (B->rmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->rmap->N);
5114222ddf1SHong Zhang 
5124222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5134222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5144222ddf1SHong Zhang 
5154222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
5166896283bSStefano Zampini   ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
5174222ddf1SHong Zhang 
5184222ddf1SHong Zhang   if (fB == fA && sametype) {
5196896283bSStefano Zampini     ierr = PetscInfo(mat,"  sametype and matching op\n");CHKERRQ(ierr);
5204222ddf1SHong Zhang     f = fB;
5214222ddf1SHong Zhang   } else {
5224222ddf1SHong Zhang     char      mtypes[256];
5234222ddf1SHong Zhang     PetscBool istrans;
5244222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
5254222ddf1SHong Zhang     if (!istrans) {
5264222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
5274222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5284222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5294222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5304222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5314222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5324222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
533*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
5344222ddf1SHong Zhang     } else {
5354222ddf1SHong Zhang       Mat T = NULL;
5364222ddf1SHong Zhang       SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AtB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
5374222ddf1SHong Zhang 
5384222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
5394222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5404222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5414222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5424222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5434222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5444222ddf1SHong Zhang 
5454222ddf1SHong Zhang       product->type = MATPRODUCT_AtB;
5464222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
547*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
5484222ddf1SHong Zhang     }
5494222ddf1SHong Zhang 
5504222ddf1SHong Zhang     if (!f) {
5514222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
552*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
5534222ddf1SHong Zhang     }
5544222ddf1SHong Zhang   }
5554222ddf1SHong Zhang 
556*7a3c3d58SStefano Zampini   /* last chance, we can still compute the product if B is of type dense */
557*7a3c3d58SStefano Zampini   if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) {
558*7a3c3d58SStefano Zampini     PetscBool isdense;
559*7a3c3d58SStefano Zampini 
560*7a3c3d58SStefano Zampini     ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
561*7a3c3d58SStefano Zampini     if (isdense) {
562*7a3c3d58SStefano Zampini       f    = MatProductSetFromOptions_X_Dense;
563*7a3c3d58SStefano Zampini       ierr = PetscInfo(mat,"  using basic looping over columns of a dense matrix\n");CHKERRQ(ierr);
564*7a3c3d58SStefano Zampini     }
565*7a3c3d58SStefano Zampini   }
566*7a3c3d58SStefano Zampini 
567*7a3c3d58SStefano Zampini   if (f) {
5684222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
569*7a3c3d58SStefano Zampini   } else { /* reset pointers since the matrix types combination is not available */
570*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
571*7a3c3d58SStefano Zampini     mat->ops->productsymbolic = NULL;
572*7a3c3d58SStefano Zampini     mat->ops->productnumeric  = NULL;
573*7a3c3d58SStefano Zampini   }
5744222ddf1SHong Zhang   PetscFunctionReturn(0);
5754222ddf1SHong Zhang }
5764222ddf1SHong Zhang 
5774222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat)
5784222ddf1SHong Zhang {
5794222ddf1SHong Zhang   PetscErrorCode ierr;
5804222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5814222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5824222ddf1SHong Zhang   PetscBool      sametype;
5834222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5844222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5854222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5864222ddf1SHong Zhang 
5874222ddf1SHong Zhang   PetscFunctionBegin;
5884222ddf1SHong Zhang   /* Check matrix global sizes */
5894222ddf1SHong Zhang   if (B->cmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, AN %D != BN %D",A->cmap->N,B->cmap->N);
5904222ddf1SHong Zhang 
5914222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5924222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5934222ddf1SHong Zhang 
5944222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
5956896283bSStefano Zampini   ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
5964222ddf1SHong Zhang   if (fB == fA && sametype) {
5976896283bSStefano Zampini     ierr = PetscInfo(mat,"  sametype and matching op\n");CHKERRQ(ierr);
5984222ddf1SHong Zhang     f = fB;
5994222ddf1SHong Zhang   } else {
6004222ddf1SHong Zhang     char      mtypes[256];
6014222ddf1SHong Zhang     PetscBool istrans;
6024222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
6034222ddf1SHong Zhang     if (!istrans) {
6044222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
6054222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
6064222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6074222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
6084222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6094222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
6104222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
611*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
6124222ddf1SHong Zhang     } else {
6134222ddf1SHong Zhang       Mat T = NULL;
6144222ddf1SHong Zhang       SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_ABt for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
6154222ddf1SHong Zhang 
6164222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
6174222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
6184222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6194222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
6204222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6214222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
6224222ddf1SHong Zhang 
6234222ddf1SHong Zhang       product->type = MATPRODUCT_ABt;
6244222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
625*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s (ABt)? %p\n",mtypes,f);CHKERRQ(ierr);
6264222ddf1SHong Zhang     }
6274222ddf1SHong Zhang 
6284222ddf1SHong Zhang     if (!f) {
6294222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
630*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s (ABt)? %p\n",mtypes,f);CHKERRQ(ierr);
6314222ddf1SHong Zhang     }
6324222ddf1SHong Zhang   }
6334222ddf1SHong Zhang 
634*7a3c3d58SStefano Zampini   /* last chance, we can still compute the product if B is of type dense */
635*7a3c3d58SStefano Zampini   if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) {
636*7a3c3d58SStefano Zampini     PetscBool isdense;
637*7a3c3d58SStefano Zampini 
638*7a3c3d58SStefano Zampini     ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
639*7a3c3d58SStefano Zampini     if (isdense) {
640*7a3c3d58SStefano Zampini       f    = MatProductSetFromOptions_X_Dense;
641*7a3c3d58SStefano Zampini       ierr = PetscInfo(mat,"  using basic looping over columns of a dense matrix\n");CHKERRQ(ierr);
642*7a3c3d58SStefano Zampini     }
643*7a3c3d58SStefano Zampini   }
644*7a3c3d58SStefano Zampini 
645*7a3c3d58SStefano Zampini   if (f) {
6464222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
647*7a3c3d58SStefano Zampini   } else { /* reset pointers since the matrix types combination is not available */
648*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
649*7a3c3d58SStefano Zampini     mat->ops->productsymbolic = NULL;
650*7a3c3d58SStefano Zampini     mat->ops->productnumeric  = NULL;
651*7a3c3d58SStefano Zampini   }
6524222ddf1SHong Zhang   PetscFunctionReturn(0);
6534222ddf1SHong Zhang }
6544222ddf1SHong Zhang 
6554222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat)
6564222ddf1SHong Zhang {
6574222ddf1SHong Zhang   PetscErrorCode ierr;
6584222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6594222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6604222ddf1SHong Zhang   PetscBool      sametype;
6614222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
6624222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
6634222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
6644222ddf1SHong Zhang 
6654222ddf1SHong Zhang   PetscFunctionBegin;
6664222ddf1SHong Zhang   /* Check matrix global sizes */
6674222ddf1SHong Zhang   if (A->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N);
6684222ddf1SHong Zhang   if (B->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
6694222ddf1SHong Zhang 
6704222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
6714222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
6724222ddf1SHong Zhang 
6736896283bSStefano Zampini   ierr = PetscInfo2(mat,"for A %s, P %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
6744222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
6754222ddf1SHong Zhang   if (fB == fA && sametype) {
6766896283bSStefano Zampini     ierr = PetscInfo(mat,"  sametype and matching op\n");CHKERRQ(ierr);
6774222ddf1SHong Zhang     f = fB;
6784222ddf1SHong Zhang   } else {
6794222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
6804222ddf1SHong Zhang     char  mtypes[256];
6814222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
6824222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6834222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
6844222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
6854222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
6864222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
687*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
6884222ddf1SHong Zhang 
6894222ddf1SHong Zhang     if (!f) {
6904222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
691*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
6924222ddf1SHong Zhang     }
6934222ddf1SHong Zhang   }
6944222ddf1SHong Zhang 
6954222ddf1SHong Zhang   if (f) {
6964222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
6974222ddf1SHong Zhang   } else {
698*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  for A %s, P %s uses MatProduct_Basic() implementation\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
6994222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
7004222ddf1SHong Zhang   }
7014222ddf1SHong Zhang   PetscFunctionReturn(0);
7024222ddf1SHong Zhang }
7034222ddf1SHong Zhang 
7044222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat)
7054222ddf1SHong Zhang {
7064222ddf1SHong Zhang   PetscErrorCode ierr;
7074222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7084222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7094222ddf1SHong Zhang   PetscBool      sametype;
7104222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
7114222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
7124222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
7134222ddf1SHong Zhang 
7144222ddf1SHong Zhang   PetscFunctionBegin;
7154222ddf1SHong Zhang   /* Check matrix global sizes */
7164222ddf1SHong Zhang   if (A->rmap->N != B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N);
7174222ddf1SHong Zhang   if (B->cmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->cmap->N,A->cmap->N);
7184222ddf1SHong Zhang 
7194222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
7204222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
7214222ddf1SHong Zhang 
7224222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
7236896283bSStefano Zampini   ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
7244222ddf1SHong Zhang   if (fB == fA && sametype) {
7256896283bSStefano Zampini     ierr = PetscInfo(mat,"  sametype and matching op\n");CHKERRQ(ierr);
7264222ddf1SHong Zhang     f = fB;
7274222ddf1SHong Zhang   } else {
7284222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
7294222ddf1SHong Zhang     char  mtypes[256];
7304222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
7314222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
7324222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
7334222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
7344222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
7354222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
736*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
7374222ddf1SHong Zhang 
7384222ddf1SHong Zhang     if (!f) {
7394222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
740*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
7414222ddf1SHong Zhang     }
7424222ddf1SHong Zhang   }
7434222ddf1SHong Zhang 
7444222ddf1SHong Zhang   if (f) {
7454222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
7464222ddf1SHong Zhang   } else {
747*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  for A %s, P %s uses MatProduct_Basic() implementation\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr);
7484222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
7494222ddf1SHong Zhang   }
7504222ddf1SHong Zhang   PetscFunctionReturn(0);
7514222ddf1SHong Zhang }
7524222ddf1SHong Zhang 
7534222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat)
7544222ddf1SHong Zhang {
7554222ddf1SHong Zhang   PetscErrorCode ierr;
7564222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7574222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
7584222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
7594222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
7604222ddf1SHong Zhang   PetscErrorCode (*fC)(Mat);
7614222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
7624222ddf1SHong Zhang 
7634222ddf1SHong Zhang   PetscFunctionBegin;
7644222ddf1SHong Zhang   /* Check matrix global sizes */
7654222ddf1SHong Zhang   if (B->rmap->N!= A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
7664222ddf1SHong Zhang   if (C->rmap->N!= B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",C->rmap->N,B->cmap->N);
7674222ddf1SHong Zhang 
7684222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
7694222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
7704222ddf1SHong Zhang   fC = C->ops->productsetfromoptions;
7716896283bSStefano Zampini   ierr = PetscInfo3(mat,"for A %s, B %s and C %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr);
7724222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
7736896283bSStefano Zampini     ierr = PetscInfo(mat,"  matching op\n");CHKERRQ(ierr);
7744222ddf1SHong Zhang     f = fA;
7754222ddf1SHong Zhang   } else {
7764222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype_Ctype */
7774222ddf1SHong Zhang     char  mtypes[256];
7784222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
7794222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
7804222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
7814222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
7824222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
7834222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
7844222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
7854222ddf1SHong Zhang 
7864222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
787*7a3c3d58SStefano Zampini     ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
7884222ddf1SHong Zhang     if (!f) {
7894222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
790*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
7914222ddf1SHong Zhang     }
7924222ddf1SHong Zhang     if (!f) {
7934222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
794*7a3c3d58SStefano Zampini       ierr = PetscInfo2(mat,"  querying %s? %p\n",mtypes,f);CHKERRQ(ierr);
7954222ddf1SHong Zhang     }
7964222ddf1SHong Zhang   }
7974222ddf1SHong Zhang 
7984222ddf1SHong Zhang   if (f) {
7994222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
8004222ddf1SHong Zhang   } else { /* use MatProductSymbolic/Numeric_Basic() */
8016896283bSStefano Zampini     ierr = PetscInfo3(mat,"  for A %s, B %s and C %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr);
8024222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
8034222ddf1SHong Zhang   }
8044222ddf1SHong Zhang   PetscFunctionReturn(0);
8054222ddf1SHong Zhang }
8064222ddf1SHong Zhang 
8074222ddf1SHong Zhang /*@C
8084222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
8094222ddf1SHong Zhang 
8104222ddf1SHong Zhang    Logically Collective on Mat
8114222ddf1SHong Zhang 
8124222ddf1SHong Zhang    Input Parameter:
8134222ddf1SHong Zhang .  mat - the matrix
8144222ddf1SHong Zhang 
8154222ddf1SHong Zhang    Level: beginner
8164222ddf1SHong Zhang 
8174222ddf1SHong Zhang .seealso: MatSetFromOptions()
8184222ddf1SHong Zhang @*/
8194222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
8204222ddf1SHong Zhang {
8214222ddf1SHong Zhang   PetscErrorCode ierr;
8224222ddf1SHong Zhang 
8234222ddf1SHong Zhang   PetscFunctionBegin;
8244222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8254222ddf1SHong Zhang   if (mat->ops->productsetfromoptions) {
8264222ddf1SHong Zhang     ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr);
827*7a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetType() first");
8284222ddf1SHong Zhang   PetscFunctionReturn(0);
8294222ddf1SHong Zhang }
8304222ddf1SHong Zhang 
8314222ddf1SHong Zhang /* ----------------------------------------------- */
8324222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
8334222ddf1SHong Zhang {
8344222ddf1SHong Zhang   PetscErrorCode ierr;
8354222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8364222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
8374222ddf1SHong Zhang 
8384222ddf1SHong Zhang   PetscFunctionBegin;
839*7a3c3d58SStefano Zampini   if (!mat->ops->matmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
8404222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
841*7a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
8424222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
8434222ddf1SHong Zhang   PetscFunctionReturn(0);
8444222ddf1SHong Zhang }
8454222ddf1SHong Zhang 
8464222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(Mat mat)
8474222ddf1SHong Zhang {
8484222ddf1SHong Zhang   PetscErrorCode ierr;
8494222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8504222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
8514222ddf1SHong Zhang 
8524222ddf1SHong Zhang   PetscFunctionBegin;
853*7a3c3d58SStefano Zampini   if (!mat->ops->transposematmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
8544222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
855*7a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
8564222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
8574222ddf1SHong Zhang   PetscFunctionReturn(0);
8584222ddf1SHong Zhang }
8594222ddf1SHong Zhang 
8604222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
8614222ddf1SHong Zhang {
8624222ddf1SHong Zhang   PetscErrorCode ierr;
8634222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8644222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
8654222ddf1SHong Zhang 
8664222ddf1SHong Zhang   PetscFunctionBegin;
867*7a3c3d58SStefano Zampini   if (!mat->ops->mattransposemultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
8684222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
869*7a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
8704222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
8714222ddf1SHong Zhang   PetscFunctionReturn(0);
8724222ddf1SHong Zhang }
8734222ddf1SHong Zhang 
8744222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
8754222ddf1SHong Zhang {
8764222ddf1SHong Zhang   PetscErrorCode ierr;
8774222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8784222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
8794222ddf1SHong Zhang 
8804222ddf1SHong Zhang   PetscFunctionBegin;
881*7a3c3d58SStefano Zampini   if (!mat->ops->ptapnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
8824222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
883*7a3c3d58SStefano Zampini   ierr = (*mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
8844222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
8854222ddf1SHong Zhang   PetscFunctionReturn(0);
8864222ddf1SHong Zhang }
8874222ddf1SHong Zhang 
8884222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
8894222ddf1SHong Zhang {
8904222ddf1SHong Zhang   PetscErrorCode ierr;
8914222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8924222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
8934222ddf1SHong Zhang 
8944222ddf1SHong Zhang   PetscFunctionBegin;
895*7a3c3d58SStefano Zampini   if (!mat->ops->rartnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
8964222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
897*7a3c3d58SStefano Zampini   ierr = (*mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
8984222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
8994222ddf1SHong Zhang   PetscFunctionReturn(0);
9004222ddf1SHong Zhang }
9014222ddf1SHong Zhang 
9024222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
9034222ddf1SHong Zhang {
9044222ddf1SHong Zhang   PetscErrorCode ierr;
9054222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9064222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
9074222ddf1SHong Zhang 
9084222ddf1SHong Zhang   PetscFunctionBegin;
909*7a3c3d58SStefano Zampini   if (!mat->ops->matmatmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name);
9104222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
911*7a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
9124222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
9134222ddf1SHong Zhang   PetscFunctionReturn(0);
9144222ddf1SHong Zhang }
9154222ddf1SHong Zhang 
9164222ddf1SHong Zhang /*@
9174222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
9184222ddf1SHong Zhang 
9194222ddf1SHong Zhang    Collective on Mat
9204222ddf1SHong Zhang 
9214222ddf1SHong Zhang    Input Parameters:
9224222ddf1SHong Zhang .  mat - the matrix to hold a product
9234222ddf1SHong Zhang 
9244222ddf1SHong Zhang    Output Parameters:
9254222ddf1SHong Zhang .  mat - the matrix product
9264222ddf1SHong Zhang 
9274222ddf1SHong Zhang    Level: intermediate
9284222ddf1SHong Zhang 
9294222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType()
9304222ddf1SHong Zhang @*/
9314222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
9324222ddf1SHong Zhang {
9334222ddf1SHong Zhang   PetscErrorCode ierr;
9344222ddf1SHong Zhang 
9354222ddf1SHong Zhang   PetscFunctionBegin;
9364222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9374222ddf1SHong Zhang   if (mat->ops->productnumeric) {
9384222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
939*7a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSymbolic() first");
9404222ddf1SHong Zhang   PetscFunctionReturn(0);
9414222ddf1SHong Zhang }
9424222ddf1SHong Zhang 
9434222ddf1SHong Zhang /* ----------------------------------------------- */
9444222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
9454222ddf1SHong Zhang {
9464222ddf1SHong Zhang   PetscErrorCode ierr;
9474222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9484222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
9494222ddf1SHong Zhang 
9504222ddf1SHong Zhang   PetscFunctionBegin;
951*7a3c3d58SStefano Zampini   if (!mat->ops->matmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
952*7a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
9534222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
9544222ddf1SHong Zhang   PetscFunctionReturn(0);
9554222ddf1SHong Zhang }
9564222ddf1SHong Zhang 
9574222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
9584222ddf1SHong Zhang {
9594222ddf1SHong Zhang   PetscErrorCode ierr;
9604222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9614222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
9624222ddf1SHong Zhang 
9634222ddf1SHong Zhang   PetscFunctionBegin;
964*7a3c3d58SStefano Zampini   if (!mat->ops->transposematmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
965*7a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
9664222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
9674222ddf1SHong Zhang   PetscFunctionReturn(0);
9684222ddf1SHong Zhang }
9694222ddf1SHong Zhang 
9704222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
9714222ddf1SHong Zhang {
9724222ddf1SHong Zhang   PetscErrorCode ierr;
9734222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9744222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
9754222ddf1SHong Zhang 
9764222ddf1SHong Zhang   PetscFunctionBegin;
977*7a3c3d58SStefano Zampini   if (!mat->ops->mattransposemultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
978*7a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
9794222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
9804222ddf1SHong Zhang   PetscFunctionReturn(0);
9814222ddf1SHong Zhang }
9824222ddf1SHong Zhang 
9834222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
9844222ddf1SHong Zhang {
9854222ddf1SHong Zhang   PetscErrorCode ierr;
9864222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9874222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
9884222ddf1SHong Zhang 
9894222ddf1SHong Zhang   PetscFunctionBegin;
990*7a3c3d58SStefano Zampini   if (!mat->ops->matmatmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
991*7a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
9924222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
9934222ddf1SHong Zhang   PetscFunctionReturn(0);
9944222ddf1SHong Zhang }
9954222ddf1SHong Zhang 
9964222ddf1SHong Zhang /*@
9974222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
9984222ddf1SHong Zhang 
9994222ddf1SHong Zhang    Collective on Mat
10004222ddf1SHong Zhang 
10014222ddf1SHong Zhang    Input Parameters:
10024222ddf1SHong Zhang .  mat - the matrix to hold a product
10034222ddf1SHong Zhang 
10044222ddf1SHong Zhang    Output Parameters:
10054222ddf1SHong Zhang .  mat - the matrix product data structure
10064222ddf1SHong Zhang 
10074222ddf1SHong Zhang    Level: intermediate
10084222ddf1SHong Zhang 
10094222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm
10104222ddf1SHong Zhang @*/
10114222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
10124222ddf1SHong Zhang {
10134222ddf1SHong Zhang   PetscErrorCode ierr;
10144222ddf1SHong Zhang   Mat_Product    *product = mat->product;
10154222ddf1SHong Zhang   MatProductType productype = product->type;
10164222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
10174222ddf1SHong Zhang 
10184222ddf1SHong Zhang   PetscFunctionBegin;
10194222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
10204222ddf1SHong Zhang 
10214222ddf1SHong Zhang   /* log event */
10224222ddf1SHong Zhang   switch (productype) {
10234222ddf1SHong Zhang   case MATPRODUCT_AB:
10244222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
10254222ddf1SHong Zhang     break;
10264222ddf1SHong Zhang   case MATPRODUCT_AtB:
10274222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
10284222ddf1SHong Zhang     break;
10294222ddf1SHong Zhang   case MATPRODUCT_ABt:
10304222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
10314222ddf1SHong Zhang     break;
10324222ddf1SHong Zhang   case MATPRODUCT_PtAP:
10334222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
10344222ddf1SHong Zhang     break;
10354222ddf1SHong Zhang   case MATPRODUCT_RARt:
10364222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
10374222ddf1SHong Zhang     break;
10384222ddf1SHong Zhang   case MATPRODUCT_ABC:
10394222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
10404222ddf1SHong Zhang     break;
10414222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported");
10424222ddf1SHong Zhang   }
10434222ddf1SHong Zhang 
10444222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
10454222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
10464222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
10474222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
1048*7a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetFromOptions() first");
10494222ddf1SHong Zhang   PetscFunctionReturn(0);
10504222ddf1SHong Zhang }
10514222ddf1SHong Zhang 
10524222ddf1SHong Zhang /*@
10534222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
10544222ddf1SHong Zhang 
10554222ddf1SHong Zhang    Collective on Mat
10564222ddf1SHong Zhang 
10574222ddf1SHong Zhang    Input Parameters:
10584222ddf1SHong Zhang +  mat - the matrix product
10594222ddf1SHong Zhang -  fill - expected fill as ratio of nnz(mat)/(nnz(A) + nnz(B) + nnz(C)); use PETSC_DEFAULT if you do not have a good estimate. If the product is a dense matrix, this is irrelevent.
10604222ddf1SHong Zhang 
10614222ddf1SHong Zhang    Level: intermediate
10624222ddf1SHong Zhang 
10634222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
10644222ddf1SHong Zhang @*/
10654222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
10664222ddf1SHong Zhang {
10674222ddf1SHong Zhang   Mat_Product *product = mat->product;
10684222ddf1SHong Zhang 
10694222ddf1SHong Zhang   PetscFunctionBegin;
10704222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1071*7a3c3d58SStefano Zampini   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first");
1072*7a3c3d58SStefano Zampini   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) product->fill = 2.0;
1073*7a3c3d58SStefano Zampini   else product->fill = fill;
10744222ddf1SHong Zhang   PetscFunctionReturn(0);
10754222ddf1SHong Zhang }
10764222ddf1SHong Zhang 
10774222ddf1SHong Zhang /*@
10784222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
10794222ddf1SHong Zhang 
10804222ddf1SHong Zhang    Collective on Mat
10814222ddf1SHong Zhang 
10824222ddf1SHong Zhang    Input Parameters:
10834222ddf1SHong Zhang +  mat - the matrix product
10844222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
10854222ddf1SHong Zhang 
10864222ddf1SHong Zhang    Level: intermediate
10874222ddf1SHong Zhang 
10884222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate()
10894222ddf1SHong Zhang @*/
10904222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
10914222ddf1SHong Zhang {
1092*7a3c3d58SStefano Zampini   PetscErrorCode ierr;
10934222ddf1SHong Zhang   Mat_Product    *product = mat->product;
10944222ddf1SHong Zhang 
10954222ddf1SHong Zhang   PetscFunctionBegin;
10964222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1097*7a3c3d58SStefano Zampini   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first");
1098*7a3c3d58SStefano Zampini   ierr = PetscFree(product->alg);CHKERRQ(ierr);
1099*7a3c3d58SStefano Zampini   ierr = PetscStrallocpy(alg,&product->alg);CHKERRQ(ierr);
11004222ddf1SHong Zhang   PetscFunctionReturn(0);
11014222ddf1SHong Zhang }
11024222ddf1SHong Zhang 
11034222ddf1SHong Zhang /*@
11044222ddf1SHong Zhang    MatProductSetType - Sets a particular matrix product type, for example Mat*Mat.
11054222ddf1SHong Zhang 
11064222ddf1SHong Zhang    Collective on Mat
11074222ddf1SHong Zhang 
11084222ddf1SHong Zhang    Input Parameters:
11094222ddf1SHong Zhang +  mat - the matrix
11104222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
11114222ddf1SHong Zhang 
11124222ddf1SHong Zhang    Level: intermediate
11134222ddf1SHong Zhang 
11144222ddf1SHong Zhang .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm
11154222ddf1SHong Zhang @*/
11164222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
11174222ddf1SHong Zhang {
11184222ddf1SHong Zhang   Mat_Product *product = mat->product;
11194222ddf1SHong Zhang 
11204222ddf1SHong Zhang   PetscFunctionBegin;
11214222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1122*7a3c3d58SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,productype,2);
1123*7a3c3d58SStefano Zampini   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first");
11244222ddf1SHong Zhang   product->type = productype;
11254222ddf1SHong Zhang 
11264222ddf1SHong Zhang   switch (productype) {
11274222ddf1SHong Zhang   case MATPRODUCT_AB:
11284222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AB;
11294222ddf1SHong Zhang     break;
11304222ddf1SHong Zhang   case MATPRODUCT_AtB:
11314222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB;
11324222ddf1SHong Zhang     break;
11334222ddf1SHong Zhang   case MATPRODUCT_ABt:
11344222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt;
11354222ddf1SHong Zhang     break;
11364222ddf1SHong Zhang   case MATPRODUCT_PtAP:
11374222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP;
11384222ddf1SHong Zhang     break;
11394222ddf1SHong Zhang   case MATPRODUCT_RARt:
11404222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt;
11414222ddf1SHong Zhang     break;
11424222ddf1SHong Zhang   case MATPRODUCT_ABC:
11434222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC;
11444222ddf1SHong Zhang     break;
1145544a5e07SHong Zhang   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]);
11464222ddf1SHong Zhang   }
11474222ddf1SHong Zhang   PetscFunctionReturn(0);
11484222ddf1SHong Zhang }
11494222ddf1SHong Zhang 
11504417c5e8SHong Zhang /*@
11514417c5e8SHong Zhang    MatProductClear - Clears matrix product internal structure.
11524417c5e8SHong Zhang 
11534417c5e8SHong Zhang    Collective on Mat
11544417c5e8SHong Zhang 
11554417c5e8SHong Zhang    Input Parameters:
11564417c5e8SHong Zhang .  mat - the product matrix
11574417c5e8SHong Zhang 
11584417c5e8SHong Zhang    Level: intermediate
11594417c5e8SHong Zhang @*/
11604417c5e8SHong Zhang PetscErrorCode MatProductClear(Mat mat)
11614417c5e8SHong Zhang {
11624417c5e8SHong Zhang   PetscErrorCode ierr;
11634417c5e8SHong Zhang   Mat_Product    *product = mat->product;
11644417c5e8SHong Zhang 
11654417c5e8SHong Zhang   PetscFunctionBegin;
1166*7a3c3d58SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
11674417c5e8SHong Zhang   if (product) {
11684417c5e8SHong Zhang     /* release reference */
11694417c5e8SHong Zhang     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
11704417c5e8SHong Zhang     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
11714417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
1172*7a3c3d58SStefano Zampini     ierr = PetscFree(product->alg);CHKERRQ(ierr);
11734417c5e8SHong Zhang     ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr);
11744417c5e8SHong Zhang     ierr = PetscFree(mat->product);CHKERRQ(ierr);
11754417c5e8SHong Zhang   }
11764417c5e8SHong Zhang   PetscFunctionReturn(0);
11774417c5e8SHong Zhang }
11784417c5e8SHong Zhang 
11794222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
11804417c5e8SHong Zhang PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
11814222ddf1SHong Zhang {
11824222ddf1SHong Zhang   PetscErrorCode ierr;
11834222ddf1SHong Zhang   Mat_Product    *product=NULL;
11844222ddf1SHong Zhang 
11854222ddf1SHong Zhang   PetscFunctionBegin;
11864222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
11874222ddf1SHong Zhang   product->A        = A;
11884222ddf1SHong Zhang   product->B        = B;
11894222ddf1SHong Zhang   product->C        = C;
11904222ddf1SHong Zhang   product->Dwork    = NULL;
11914222ddf1SHong Zhang   product->fill     = 2.0; /* PETSC_DEFAULT */
11924222ddf1SHong Zhang   product->Areplaced = PETSC_FALSE;
11934222ddf1SHong Zhang   product->Breplaced = PETSC_FALSE;
11944222ddf1SHong Zhang   product->api_user  = PETSC_FALSE;
11954222ddf1SHong Zhang   D->product         = product;
11964417c5e8SHong Zhang 
1197*7a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(D,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1198*7a3c3d58SStefano Zampini 
11994417c5e8SHong Zhang   /* take ownership */
12004417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
12014417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
12024417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
12034222ddf1SHong Zhang   PetscFunctionReturn(0);
12044222ddf1SHong Zhang }
12054222ddf1SHong Zhang 
12064222ddf1SHong Zhang /*@
12074222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
12084222ddf1SHong Zhang 
12094222ddf1SHong Zhang    Collective on Mat
12104222ddf1SHong Zhang 
12114222ddf1SHong Zhang    Input Parameters:
12124222ddf1SHong Zhang +  A - the first matrix
12134222ddf1SHong Zhang .  B - the second matrix
12144222ddf1SHong Zhang .  C - the third matrix (optional)
12154222ddf1SHong Zhang -  D - the matrix which will be used as a product
12164222ddf1SHong Zhang 
12174222ddf1SHong Zhang    Output Parameters:
12184222ddf1SHong Zhang .  D - the product matrix
12194222ddf1SHong Zhang 
12204222ddf1SHong Zhang    Level: intermediate
12214222ddf1SHong Zhang 
12224222ddf1SHong Zhang .seealso: MatProductCreate()
12234222ddf1SHong Zhang @*/
12244222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
12254222ddf1SHong Zhang {
12264222ddf1SHong Zhang   PetscErrorCode ierr;
12274222ddf1SHong Zhang 
12284222ddf1SHong Zhang   PetscFunctionBegin;
12294222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
12304222ddf1SHong Zhang   PetscValidType(A,1);
12314222ddf1SHong Zhang   MatCheckPreallocated(A,1);
12324222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12334222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12344222ddf1SHong Zhang 
12354222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
12364222ddf1SHong Zhang   PetscValidType(B,2);
12374222ddf1SHong Zhang   MatCheckPreallocated(B,2);
12384222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12394222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12404222ddf1SHong Zhang 
12414222ddf1SHong Zhang   if (C) {
12424222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
12434222ddf1SHong Zhang     PetscValidType(C,3);
12444222ddf1SHong Zhang     MatCheckPreallocated(C,3);
12454222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12464222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12474222ddf1SHong Zhang   }
12484222ddf1SHong Zhang 
12494222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
12504222ddf1SHong Zhang   PetscValidType(D,4);
12514222ddf1SHong Zhang   MatCheckPreallocated(D,4);
12524222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12534222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12544222ddf1SHong Zhang 
12554222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
12564222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
12574222ddf1SHong Zhang   PetscFunctionReturn(0);
12584222ddf1SHong Zhang }
12594222ddf1SHong Zhang 
12604222ddf1SHong Zhang /*@
12614222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
12624222ddf1SHong Zhang 
12634222ddf1SHong Zhang    Collective on Mat
12644222ddf1SHong Zhang 
12654222ddf1SHong Zhang    Input Parameters:
12664222ddf1SHong Zhang +  A - the first matrix
12674222ddf1SHong Zhang .  B - the second matrix
12684222ddf1SHong Zhang -  C - the third matrix (optional)
12694222ddf1SHong Zhang 
12704222ddf1SHong Zhang    Output Parameters:
12714222ddf1SHong Zhang .  D - the product matrix
12724222ddf1SHong Zhang 
12734222ddf1SHong Zhang    Level: intermediate
12744222ddf1SHong Zhang 
12754222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
12764222ddf1SHong Zhang @*/
12774222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
12784222ddf1SHong Zhang {
12794222ddf1SHong Zhang   PetscErrorCode ierr;
12804222ddf1SHong Zhang 
12814222ddf1SHong Zhang   PetscFunctionBegin;
12824222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
12834222ddf1SHong Zhang   PetscValidType(A,1);
12844222ddf1SHong Zhang   MatCheckPreallocated(A,1);
12854222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12864222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12874222ddf1SHong Zhang 
12884222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
12894222ddf1SHong Zhang   PetscValidType(B,2);
12904222ddf1SHong Zhang   MatCheckPreallocated(B,2);
12914222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12924222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
12934222ddf1SHong Zhang 
12944222ddf1SHong Zhang   if (C) {
12954222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
12964222ddf1SHong Zhang     PetscValidType(C,3);
12974222ddf1SHong Zhang     MatCheckPreallocated(C,3);
12984222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
12994222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
13004222ddf1SHong Zhang   }
13014222ddf1SHong Zhang 
13024222ddf1SHong Zhang   PetscValidPointer(D,4);
13034222ddf1SHong Zhang 
13044222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
13054222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
13064222ddf1SHong Zhang   PetscFunctionReturn(0);
13074222ddf1SHong Zhang }
1308