xref: /petsc/src/mat/interface/matproduct.c (revision 6718818e67c4802797f2feae43fc3d52878b6955)
14222ddf1SHong Zhang 
24222ddf1SHong Zhang /*
34222ddf1SHong Zhang     Routines for matrix products. Calling procedure:
44222ddf1SHong Zhang 
5*6718818eSStefano Zampini     MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D)
6*6718818eSStefano Zampini     MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC)
7*6718818eSStefano Zampini     MatProductSetAlgorithm(D, alg)
8*6718818eSStefano Zampini     MatProductSetFill(D,fill)
9*6718818eSStefano Zampini     MatProductSetFromOptions(D)
10*6718818eSStefano Zampini       -> MatProductSetFromOptions_Private(D)
114222ddf1SHong Zhang            # Check matrix global sizes
12*6718818eSStefano Zampini            if the matrices have the same setfromoptions routine, use it
13*6718818eSStefano Zampini            if not, try:
14*6718818eSStefano Zampini              -> Query MatProductSetFromOptions_Atype_Btype_Ctype_C(D) from A, B and C (in order)
15*6718818eSStefano Zampini              if found -> run the specific setup that must set the symbolic operation (these callbacks should never fail)
16*6718818eSStefano Zampini            if callback not found or no symbolic operation set
17*6718818eSStefano Zampini              -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANPOSEMAT)
18*6718818eSStefano Zampini            if dispatch found but combination still not present do
19*6718818eSStefano Zampini              -> check if B is dense and product type AtB or AB -> if true, basic looping of dense columns
20*6718818eSStefano Zampini              -> check if triple product (PtAP, RARt or ABC) -> if true, set the Basic routines
21*6718818eSStefano Zampini 
22*6718818eSStefano Zampini     #  The setfromoptions calls MatProductSetFromOptions_Atype_Btype_Ctype should
234222ddf1SHong Zhang     #    Check matrix local sizes for mpi matrices
244222ddf1SHong Zhang     #    Set default algorithm
254222ddf1SHong Zhang     #    Get runtime option
26*6718818eSStefano Zampini     #    Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype if found
274222ddf1SHong Zhang 
284222ddf1SHong Zhang     PetscLogEventBegin()
29*6718818eSStefano Zampini     MatProductSymbolic(D)
30*6718818eSStefano Zampini       # Call MatProductSymbolic_productype_Atype_Btype_Ctype()
31*6718818eSStefano Zampini         the callback must set the numeric phase D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype
324222ddf1SHong Zhang     PetscLogEventEnd()
334222ddf1SHong Zhang 
344222ddf1SHong Zhang     PetscLogEventBegin()
35*6718818eSStefano Zampini     MatProductNumeric(D)
36*6718818eSStefano Zampini       # Call the numeric phase
374222ddf1SHong Zhang     PetscLogEventEnd()
38*6718818eSStefano Zampini 
39*6718818eSStefano Zampini     # The symbolic phases are allowed to set extra data structures and attach those to the product
40*6718818eSStefano Zampini     # this additional data can be reused between multiple numeric phases with the same matrices
41*6718818eSStefano Zampini     # if not needed, call
42*6718818eSStefano Zampini     MatProductClear(D)
434222ddf1SHong Zhang */
444222ddf1SHong Zhang 
454222ddf1SHong Zhang #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
464222ddf1SHong Zhang 
47*6718818eSStefano Zampini const char *const MatProductTypes[] = {"UNSPECIFIED","AB","AtB","ABt","PtAP","RARt","ABC"};
48544a5e07SHong Zhang 
49*6718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
50*6718818eSStefano Zampini  * they are dangerous and should be removed in the future */
514222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C)
524222ddf1SHong Zhang {
534222ddf1SHong Zhang   PetscErrorCode ierr;
544222ddf1SHong Zhang   Mat_Product    *product = C->product;
554222ddf1SHong Zhang   Mat            P = product->B,AP = product->Dwork;
564222ddf1SHong Zhang 
574222ddf1SHong Zhang   PetscFunctionBegin;
584222ddf1SHong Zhang   /* AP = A*P */
594222ddf1SHong Zhang   ierr = MatProductNumeric(AP);CHKERRQ(ierr);
604222ddf1SHong Zhang   /* C = P^T*AP */
617a3c3d58SStefano Zampini   if (!C->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
627a3c3d58SStefano Zampini   ierr = (*C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr);
634222ddf1SHong Zhang   PetscFunctionReturn(0);
644222ddf1SHong Zhang }
654222ddf1SHong Zhang 
664222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C)
674222ddf1SHong Zhang {
684222ddf1SHong Zhang   PetscErrorCode ierr;
694222ddf1SHong Zhang   Mat_Product    *product = C->product;
704222ddf1SHong Zhang   Mat            A=product->A,P=product->B,AP;
714222ddf1SHong Zhang   PetscReal      fill=product->fill;
724222ddf1SHong Zhang 
734222ddf1SHong Zhang   PetscFunctionBegin;
74*6718818eSStefano Zampini   ierr = PetscInfo2((PetscObject)C,"for A %s, P %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr);
754222ddf1SHong Zhang   /* AP = A*P */
764222ddf1SHong Zhang   ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr);
774222ddf1SHong Zhang   ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr);
787a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(AP,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
794222ddf1SHong Zhang   ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr);
804222ddf1SHong Zhang   ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr);
814222ddf1SHong Zhang   ierr = MatProductSymbolic(AP);CHKERRQ(ierr);
824222ddf1SHong Zhang 
834222ddf1SHong Zhang   /* C = P^T*AP */
844222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr);
857a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
864222ddf1SHong Zhang   product->A = P;
874222ddf1SHong Zhang   product->B = AP;
884222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
894222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
904222ddf1SHong Zhang 
914222ddf1SHong Zhang   /* resume user's original input matrix setting for A and B */
924222ddf1SHong Zhang   product->A     = A;
934222ddf1SHong Zhang   product->B     = P;
944222ddf1SHong Zhang   product->Dwork = AP;
954222ddf1SHong Zhang 
964222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP_Basic;
974222ddf1SHong Zhang   PetscFunctionReturn(0);
984222ddf1SHong Zhang }
994222ddf1SHong Zhang 
1004222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C)
1014222ddf1SHong Zhang {
1024222ddf1SHong Zhang   PetscErrorCode ierr;
1034222ddf1SHong Zhang   Mat_Product    *product = C->product;
1044222ddf1SHong Zhang   Mat            R=product->B,RA=product->Dwork;
1054222ddf1SHong Zhang 
1064222ddf1SHong Zhang   PetscFunctionBegin;
1074222ddf1SHong Zhang   /* RA = R*A */
1084222ddf1SHong Zhang   ierr = MatProductNumeric(RA);CHKERRQ(ierr);
1094222ddf1SHong Zhang   /* C = RA*R^T */
1107a3c3d58SStefano Zampini   if (!C->ops->mattransposemultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
1117a3c3d58SStefano Zampini   ierr = (*C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr);
1124222ddf1SHong Zhang   PetscFunctionReturn(0);
1134222ddf1SHong Zhang }
1144222ddf1SHong Zhang 
1154222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C)
1164222ddf1SHong Zhang {
1174222ddf1SHong Zhang   PetscErrorCode ierr;
1184222ddf1SHong Zhang   Mat_Product    *product = C->product;
1194222ddf1SHong Zhang   Mat            A=product->A,R=product->B,RA;
1204222ddf1SHong Zhang   PetscReal      fill=product->fill;
1214222ddf1SHong Zhang 
1224222ddf1SHong Zhang   PetscFunctionBegin;
123*6718818eSStefano Zampini   ierr = PetscInfo2((PetscObject)C,"for A %s, R %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr);
1244222ddf1SHong Zhang   /* RA = R*A */
1254222ddf1SHong Zhang   ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr);
1264222ddf1SHong Zhang   ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr);
1277a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(RA,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1284222ddf1SHong Zhang   ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr);
1294222ddf1SHong Zhang   ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr);
1304222ddf1SHong Zhang   ierr = MatProductSymbolic(RA);CHKERRQ(ierr);
1314222ddf1SHong Zhang 
1324222ddf1SHong Zhang   /* C = RA*R^T */
1334222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr);
1347a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1354222ddf1SHong Zhang   product->A = RA;
1364222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
1374222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
1384222ddf1SHong Zhang 
1394222ddf1SHong Zhang   /* resume user's original input matrix setting for A */
1404222ddf1SHong Zhang   product->A     = A;
1414222ddf1SHong Zhang   product->Dwork = RA; /* save here so it will be destroyed with product C */
1424222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_RARt_Basic;
1434222ddf1SHong Zhang   PetscFunctionReturn(0);
1444222ddf1SHong Zhang }
1454222ddf1SHong Zhang 
1464222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat)
1474222ddf1SHong Zhang {
1484222ddf1SHong Zhang   PetscErrorCode ierr;
1494222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1504222ddf1SHong Zhang   Mat            A=product->A,BC=product->Dwork;
1514222ddf1SHong Zhang 
1524222ddf1SHong Zhang   PetscFunctionBegin;
1534222ddf1SHong Zhang   /* Numeric BC = B*C */
1544222ddf1SHong Zhang   ierr = MatProductNumeric(BC);CHKERRQ(ierr);
1554222ddf1SHong Zhang   /* Numeric mat = A*BC */
1567a3c3d58SStefano Zampini   if (!mat->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage");
1577a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr);
1584222ddf1SHong Zhang   PetscFunctionReturn(0);
1594222ddf1SHong Zhang }
1604222ddf1SHong Zhang 
1614222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat)
1624222ddf1SHong Zhang {
1634222ddf1SHong Zhang   PetscErrorCode ierr;
1644222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1654222ddf1SHong Zhang   Mat            B=product->B,C=product->C,BC;
1664222ddf1SHong Zhang   PetscReal      fill=product->fill;
1674222ddf1SHong Zhang 
1684222ddf1SHong Zhang   PetscFunctionBegin;
169*6718818eSStefano Zampini   ierr = PetscInfo3((PetscObject)mat,"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);
1704222ddf1SHong Zhang   /* Symbolic BC = B*C */
1714222ddf1SHong Zhang   ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr);
1724222ddf1SHong Zhang   ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr);
1737a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1744222ddf1SHong Zhang   ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr);
1754222ddf1SHong Zhang   ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr);
1764222ddf1SHong Zhang   ierr = MatProductSymbolic(BC);CHKERRQ(ierr);
1774222ddf1SHong Zhang 
1784222ddf1SHong Zhang   /* Symbolic mat = A*BC */
1794222ddf1SHong Zhang   ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr);
1807a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(mat,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1814222ddf1SHong Zhang   product->B     = BC;
1824222ddf1SHong Zhang   product->Dwork = BC;
1834222ddf1SHong Zhang   ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr);
1844222ddf1SHong Zhang   ierr = MatProductSymbolic(mat);CHKERRQ(ierr);
1854222ddf1SHong Zhang 
1864222ddf1SHong Zhang   /* resume user's original input matrix setting for B */
1874222ddf1SHong Zhang   product->B = B;
1884222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC_Basic;
1894222ddf1SHong Zhang   PetscFunctionReturn(0);
1904222ddf1SHong Zhang }
1914222ddf1SHong Zhang 
192*6718818eSStefano Zampini static PetscErrorCode MatProductSymbolic_Basic(Mat mat)
1934222ddf1SHong Zhang {
1944222ddf1SHong Zhang   PetscErrorCode ierr;
1954222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1964222ddf1SHong Zhang 
1974222ddf1SHong Zhang   PetscFunctionBegin;
1984222ddf1SHong Zhang   switch (product->type) {
1994222ddf1SHong Zhang   case MATPRODUCT_PtAP:
2004222ddf1SHong Zhang     ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr);
2014222ddf1SHong Zhang     break;
2024222ddf1SHong Zhang   case MATPRODUCT_RARt:
2034222ddf1SHong Zhang     ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr);
2044222ddf1SHong Zhang     break;
2054222ddf1SHong Zhang   case MATPRODUCT_ABC:
2064222ddf1SHong Zhang     ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr);
2074222ddf1SHong Zhang     break;
208*6718818eSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]);
2094222ddf1SHong Zhang   }
2104222ddf1SHong Zhang   PetscFunctionReturn(0);
2114222ddf1SHong Zhang }
2124222ddf1SHong Zhang 
2134222ddf1SHong Zhang /* ----------------------------------------------- */
2144222ddf1SHong Zhang /*@C
2154222ddf1SHong Zhang    MatProductReplaceMats - Replace input matrices for a matrix product.
2164222ddf1SHong Zhang 
2174222ddf1SHong Zhang    Collective on Mat
2184222ddf1SHong Zhang 
2194222ddf1SHong Zhang    Input Parameters:
2204222ddf1SHong Zhang +  A - the matrix or NULL if not being replaced
2214222ddf1SHong Zhang .  B - the matrix or NULL if not being replaced
2224222ddf1SHong Zhang .  C - the matrix or NULL if not being replaced
2234222ddf1SHong Zhang -  D - the matrix product
2244222ddf1SHong Zhang 
2254222ddf1SHong Zhang    Level: intermediate
2264222ddf1SHong Zhang 
2274222ddf1SHong Zhang    Notes:
228*6718818eSStefano Zampini      To reuse the symbolic phase, input matrices must have exactly the same data structure as the replaced one.
229*6718818eSStefano Zampini      If the type of any of the input matrices is different than what previously used, the product is cleared and MatProductSetFromOptions()/MatProductSymbolic() are invoked again.
2304222ddf1SHong Zhang 
231*6718818eSStefano Zampini .seealso: MatProductCreate(), MatProductSetFromOptions(), MatProductSymbolic(). MatProductClear()
2324222ddf1SHong Zhang @*/
2334222ddf1SHong Zhang PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D)
2344222ddf1SHong Zhang {
2354417c5e8SHong Zhang   PetscErrorCode ierr;
236*6718818eSStefano Zampini   Mat_Product    *product;
237*6718818eSStefano Zampini   PetscBool      flgA = PETSC_TRUE,flgB = PETSC_TRUE,flgC = PETSC_TRUE;
2384222ddf1SHong Zhang 
2394222ddf1SHong Zhang   PetscFunctionBegin;
2407a3c3d58SStefano Zampini   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
241*6718818eSStefano Zampini   MatCheckProduct(D,4);
242*6718818eSStefano Zampini   product = D->product;
2434222ddf1SHong Zhang   if (A) {
2447a3c3d58SStefano Zampini     PetscValidHeaderSpecific(A,MAT_CLASSID,1);
245*6718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
246*6718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->A,((PetscObject)A)->type_name,&flgA);CHKERRQ(ierr);
247*6718818eSStefano Zampini     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2484222ddf1SHong Zhang     product->A = A;
2494222ddf1SHong Zhang   }
2504222ddf1SHong Zhang   if (B) {
2517a3c3d58SStefano Zampini     PetscValidHeaderSpecific(B,MAT_CLASSID,2);
252*6718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
253*6718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->B,((PetscObject)B)->type_name,&flgB);CHKERRQ(ierr);
254*6718818eSStefano Zampini     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
2554222ddf1SHong Zhang     product->B = B;
2564222ddf1SHong Zhang   }
2574417c5e8SHong Zhang   if (C) {
2587a3c3d58SStefano Zampini     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
259*6718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
260*6718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->C,((PetscObject)C)->type_name,&flgC);CHKERRQ(ierr);
261*6718818eSStefano Zampini     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
2624417c5e8SHong Zhang     product->C = C;
2634417c5e8SHong Zhang   }
264*6718818eSStefano Zampini   /* Any of the replaced mats is of a different type, reset */
265*6718818eSStefano Zampini   if (!flgA || !flgB || !flgC) {
266*6718818eSStefano Zampini     if (D->product->destroy) {
267*6718818eSStefano Zampini       ierr = (*D->product->destroy)(D->product->data);CHKERRQ(ierr);
268*6718818eSStefano Zampini     }
269*6718818eSStefano Zampini     D->product->destroy = NULL;
270*6718818eSStefano Zampini     D->product->data = NULL;
271*6718818eSStefano Zampini     if (D->ops->productnumeric || D->ops->productsymbolic) {
272*6718818eSStefano Zampini       ierr = MatProductSetFromOptions(D);CHKERRQ(ierr);
273*6718818eSStefano Zampini       ierr = MatProductSymbolic(D);CHKERRQ(ierr);
274*6718818eSStefano Zampini     }
275*6718818eSStefano Zampini   }
2764222ddf1SHong Zhang   PetscFunctionReturn(0);
2774222ddf1SHong Zhang }
2784222ddf1SHong Zhang 
2797a3c3d58SStefano Zampini static PetscErrorCode MatProductNumeric_X_Dense(Mat C)
2807a3c3d58SStefano Zampini {
2817a3c3d58SStefano Zampini   PetscErrorCode ierr;
2827a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
2837a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
2847a3c3d58SStefano Zampini   PetscInt       k, K = B->cmap->N;
2857a3c3d58SStefano Zampini   PetscBool      t = PETSC_TRUE,iscuda = PETSC_FALSE;
2867a3c3d58SStefano Zampini   PetscBool      Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE;
2877a3c3d58SStefano Zampini   char           *Btype = NULL,*Ctype = NULL;
2887a3c3d58SStefano Zampini 
2897a3c3d58SStefano Zampini   PetscFunctionBegin;
2907a3c3d58SStefano Zampini   switch (product->type) {
2917a3c3d58SStefano Zampini   case MATPRODUCT_AB:
2927a3c3d58SStefano Zampini     t = PETSC_FALSE;
2937a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
2947a3c3d58SStefano Zampini     break;
2957a3c3d58SStefano 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);
2967a3c3d58SStefano Zampini   }
2977a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
2987a3c3d58SStefano Zampini     VecType vtype;
2997a3c3d58SStefano Zampini 
3007a3c3d58SStefano Zampini     ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr);
3017a3c3d58SStefano Zampini     ierr = PetscStrcmp(vtype,VECCUDA,&iscuda);CHKERRQ(ierr);
3027a3c3d58SStefano Zampini     if (!iscuda) {
3037a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
3047a3c3d58SStefano Zampini     }
3057a3c3d58SStefano Zampini     if (!iscuda) {
3067a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECMPICUDA,&iscuda);CHKERRQ(ierr);
3077a3c3d58SStefano Zampini     }
3087a3c3d58SStefano Zampini     if (iscuda) { /* Make sure we have up-to-date data on the GPU */
3097a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)B)->type_name,&Btype);CHKERRQ(ierr);
3107a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)C)->type_name,&Ctype);CHKERRQ(ierr);
3117a3c3d58SStefano Zampini       ierr = MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
3127a3c3d58SStefano Zampini       if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */
3137a3c3d58SStefano Zampini         ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3147a3c3d58SStefano Zampini         ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3157a3c3d58SStefano Zampini       }
3167a3c3d58SStefano Zampini       ierr = MatConvert(C,MATDENSECUDA,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
3177a3c3d58SStefano Zampini     } else { /* Make sure we have up-to-date data on the CPU */
3187a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
3197a3c3d58SStefano Zampini       Bcpu = B->boundtocpu;
3207a3c3d58SStefano Zampini       Ccpu = C->boundtocpu;
3217a3c3d58SStefano Zampini #endif
3227a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,PETSC_TRUE);CHKERRQ(ierr);
3237a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,PETSC_TRUE);CHKERRQ(ierr);
3247a3c3d58SStefano Zampini     }
3257a3c3d58SStefano Zampini   }
3267a3c3d58SStefano Zampini   for (k=0;k<K;k++) {
3277a3c3d58SStefano Zampini     Vec x,y;
3287a3c3d58SStefano Zampini 
3297a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecRead(B,k,&x);CHKERRQ(ierr);
3307a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecWrite(C,k,&y);CHKERRQ(ierr);
3317a3c3d58SStefano Zampini     if (t) {
3327a3c3d58SStefano Zampini       ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr);
3337a3c3d58SStefano Zampini     } else {
3347a3c3d58SStefano Zampini       ierr = MatMult(A,x,y);CHKERRQ(ierr);
3357a3c3d58SStefano Zampini     }
3367a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecRead(B,k,&x);CHKERRQ(ierr);
3377a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecWrite(C,k,&y);CHKERRQ(ierr);
3387a3c3d58SStefano Zampini   }
3397a3c3d58SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3407a3c3d58SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3417a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
3427a3c3d58SStefano Zampini     if (iscuda) {
3437a3c3d58SStefano Zampini       ierr = MatConvert(B,Btype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
3447a3c3d58SStefano Zampini       ierr = MatConvert(C,Ctype,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
3457a3c3d58SStefano Zampini     } else {
3467a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,Bcpu);CHKERRQ(ierr);
3477a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,Ccpu);CHKERRQ(ierr);
3487a3c3d58SStefano Zampini     }
3497a3c3d58SStefano Zampini   }
3507a3c3d58SStefano Zampini   ierr = PetscFree(Btype);CHKERRQ(ierr);
3517a3c3d58SStefano Zampini   ierr = PetscFree(Ctype);CHKERRQ(ierr);
3527a3c3d58SStefano Zampini   PetscFunctionReturn(0);
3537a3c3d58SStefano Zampini }
3547a3c3d58SStefano Zampini 
3557a3c3d58SStefano Zampini static PetscErrorCode MatProductSymbolic_X_Dense(Mat C)
3567a3c3d58SStefano Zampini {
3577a3c3d58SStefano Zampini   PetscErrorCode ierr;
3587a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
3597a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
3607a3c3d58SStefano Zampini   PetscBool      isdense;
3617a3c3d58SStefano Zampini 
3627a3c3d58SStefano Zampini   PetscFunctionBegin;
3637a3c3d58SStefano Zampini   switch (product->type) {
3647a3c3d58SStefano Zampini   case MATPRODUCT_AB:
3657a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,A->rmap->N,B->cmap->N);CHKERRQ(ierr);
3667a3c3d58SStefano Zampini     break;
3677a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
3687a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,B->cmap->n,A->cmap->N,B->cmap->N);CHKERRQ(ierr);
3697a3c3d58SStefano Zampini     break;
3707a3c3d58SStefano 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);
3717a3c3d58SStefano Zampini   }
3727a3c3d58SStefano Zampini   ierr = PetscObjectBaseTypeCompareAny((PetscObject)C,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
3737a3c3d58SStefano Zampini   if (!isdense) {
3747a3c3d58SStefano Zampini     ierr = MatSetType(C,((PetscObject)B)->type_name);CHKERRQ(ierr);
375*6718818eSStefano Zampini     /* If matrix type of C was not set or not dense, we need to reset the pointer */
3767a3c3d58SStefano Zampini     C->ops->productsymbolic = MatProductSymbolic_X_Dense;
3777a3c3d58SStefano Zampini   }
378*6718818eSStefano Zampini   C->ops->productnumeric = MatProductNumeric_X_Dense;
3797a3c3d58SStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
3807a3c3d58SStefano Zampini   PetscFunctionReturn(0);
3817a3c3d58SStefano Zampini }
3827a3c3d58SStefano Zampini 
383*6718818eSStefano Zampini /* a single driver to query the dispatching */
384*6718818eSStefano Zampini static PetscErrorCode MatProductSetFromOptions_Private(Mat mat)
3854222ddf1SHong Zhang {
3864222ddf1SHong Zhang   PetscErrorCode    ierr;
3874222ddf1SHong Zhang   Mat_Product       *product = mat->product;
388*6718818eSStefano Zampini   PetscInt          Am,An,Bm,Bn,Cm,Cn;
3894222ddf1SHong Zhang   Mat               A = product->A,B = product->B,C = product->C;
390*6718818eSStefano Zampini   const char* const Bnames[] = { "B", "R", "P" };
391*6718818eSStefano Zampini   const char*       bname;
3924222ddf1SHong Zhang   PetscErrorCode    (*fA)(Mat);
3934222ddf1SHong Zhang   PetscErrorCode    (*fB)(Mat);
3944222ddf1SHong Zhang   PetscErrorCode    (*fC)(Mat);
3954222ddf1SHong Zhang   PetscErrorCode    (*f)(Mat)=NULL;
3964222ddf1SHong Zhang 
3974222ddf1SHong Zhang   PetscFunctionBegin;
398*6718818eSStefano Zampini   mat->ops->productsymbolic = NULL;
399*6718818eSStefano Zampini   mat->ops->productnumeric = NULL;
400*6718818eSStefano Zampini   if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(0);
401*6718818eSStefano Zampini   if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */
402*6718818eSStefano Zampini   if (product->type == MATPRODUCT_RARt) bname = Bnames[1];
403*6718818eSStefano Zampini   else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2];
404*6718818eSStefano Zampini   else bname = Bnames[0];
405*6718818eSStefano Zampini 
406*6718818eSStefano Zampini   /* Check matrices sizes */
407*6718818eSStefano Zampini   Am = A->rmap->N;
408*6718818eSStefano Zampini   An = A->cmap->N;
409*6718818eSStefano Zampini   Bm = B->rmap->N;
410*6718818eSStefano Zampini   Bn = B->cmap->N;
411*6718818eSStefano Zampini   Cm = C ? C->rmap->N : 0;
412*6718818eSStefano Zampini   Cn = C ? C->cmap->N : 0;
413*6718818eSStefano Zampini   if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { PetscInt t = Bn; Bn = Bm; Bm = t; }
414*6718818eSStefano Zampini   if (product->type == MATPRODUCT_AtB) { PetscInt t = An; An = Am; Am = t; }
415*6718818eSStefano Zampini   if (An != Bm) SETERRQ7(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions of A and %s are incompatible for MatProductType %s: A %Dx%D, %s %Dx%D",bname,MatProductTypes[product->type],A->rmap->N,A->cmap->N,bname,B->rmap->N,B->cmap->N);
416*6718818eSStefano Zampini   if (Cm && Cm != Bn) SETERRQ5(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions of B and C are incompatible for MatProductType %s: B %Dx%D, C %Dx%D",MatProductTypes[product->type],B->rmap->N,B->cmap->N,Cm,Cn);
4174222ddf1SHong Zhang 
4184222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4194222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
420*6718818eSStefano Zampini   fC = C ? C->ops->productsetfromoptions : fA;
421*6718818eSStefano Zampini   if (C) {
422*6718818eSStefano Zampini     ierr = PetscInfo5(mat,"MatProductType %s for A %s, %s %s, C %s\n",MatProductTypes[product->type],((PetscObject)A)->type_name,bname,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr);
423*6718818eSStefano Zampini   } else {
424*6718818eSStefano Zampini     ierr = PetscInfo4(mat,"MatProductType %s for A %s, %s %s\n",MatProductTypes[product->type],((PetscObject)A)->type_name,bname,((PetscObject)B)->type_name);CHKERRQ(ierr);
425*6718818eSStefano Zampini   }
4264222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
4276896283bSStefano Zampini     ierr = PetscInfo(mat,"  matching op\n");CHKERRQ(ierr);
428*6718818eSStefano Zampini     ierr = (*fA)(mat);CHKERRQ(ierr);
4294222ddf1SHong Zhang   } else {
4304222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype_Ctype */
4314222ddf1SHong Zhang     char  mtypes[256];
4324222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4334222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4344222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4354222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
436*6718818eSStefano Zampini     if (C) {
4374222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4384222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
439*6718818eSStefano Zampini     }
4404222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4414222ddf1SHong Zhang 
4424222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
443*6718818eSStefano Zampini     ierr = PetscInfo2(mat,"  querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr);
4444222ddf1SHong Zhang     if (!f) {
4454222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
446*6718818eSStefano Zampini       ierr = PetscInfo3(mat,"  querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr);
4474222ddf1SHong Zhang     }
448*6718818eSStefano Zampini     if (!f && C) {
4494222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
450*6718818eSStefano Zampini       ierr = PetscInfo2(mat,"  querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr);
4514222ddf1SHong Zhang     }
452*6718818eSStefano Zampini     if (f) { ierr = (*f)(mat);CHKERRQ(ierr); }
453*6718818eSStefano Zampini 
454*6718818eSStefano Zampini     /* We may have found f but it did not succeed */
455*6718818eSStefano Zampini     /* some matrices (i.e. MATTRANSPOSE, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */
456*6718818eSStefano Zampini     if (!mat->ops->productsymbolic) {
457*6718818eSStefano Zampini       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_anytype_C",sizeof(mtypes));CHKERRQ(ierr);
458*6718818eSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
459*6718818eSStefano Zampini       ierr = PetscInfo2(mat,"  querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr);
460*6718818eSStefano Zampini       if (!f) {
461*6718818eSStefano Zampini         ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
462*6718818eSStefano Zampini         ierr = PetscInfo3(mat,"  querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr);
463*6718818eSStefano Zampini       }
464*6718818eSStefano Zampini       if (!f && C) {
465*6718818eSStefano Zampini         ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
466*6718818eSStefano Zampini         ierr = PetscInfo2(mat,"  querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr);
467*6718818eSStefano Zampini       }
468*6718818eSStefano Zampini     }
469*6718818eSStefano Zampini     if (f) { ierr = (*f)(mat);CHKERRQ(ierr); }
4704222ddf1SHong Zhang   }
4714222ddf1SHong Zhang 
472*6718818eSStefano Zampini   /* We may have found f but it did not succeed */
473*6718818eSStefano Zampini   if (!mat->ops->productsymbolic) {
474*6718818eSStefano Zampini     /* we can still compute the product if B is of type dense */
475*6718818eSStefano Zampini     if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) {
476*6718818eSStefano Zampini       PetscBool isdense;
477*6718818eSStefano Zampini 
478*6718818eSStefano Zampini       ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
479*6718818eSStefano Zampini       if (isdense) {
480*6718818eSStefano Zampini 
481*6718818eSStefano Zampini         mat->ops->productsymbolic = MatProductSymbolic_X_Dense;
482*6718818eSStefano Zampini         ierr = PetscInfo(mat,"  using basic looping over columns of a dense matrix\n");CHKERRQ(ierr);
483*6718818eSStefano Zampini       }
484*6718818eSStefano Zampini     } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Basic() for triple products only */
485*6718818eSStefano Zampini       /*
486*6718818eSStefano Zampini          TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if
487*6718818eSStefano Zampini                the compination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result
488*6718818eSStefano Zampini                before computing the symbolic phase
489*6718818eSStefano Zampini       */
490*6718818eSStefano Zampini       ierr = PetscInfo(mat,"  symbolic product not supported, using MatProductSymbolic_Basic() implementation\n");CHKERRQ(ierr);
4914222ddf1SHong Zhang       mat->ops->productsymbolic = MatProductSymbolic_Basic;
4924222ddf1SHong Zhang     }
493*6718818eSStefano Zampini   }
494*6718818eSStefano Zampini   if (!mat->ops->productsymbolic) {
495*6718818eSStefano Zampini     ierr = PetscInfo(mat,"  symbolic product is not supported\n");CHKERRQ(ierr);
496*6718818eSStefano Zampini   }
4974222ddf1SHong Zhang   PetscFunctionReturn(0);
4984222ddf1SHong Zhang }
4994222ddf1SHong Zhang 
5004222ddf1SHong Zhang /*@C
5014222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
5024222ddf1SHong Zhang 
5034222ddf1SHong Zhang    Logically Collective on Mat
5044222ddf1SHong Zhang 
5054222ddf1SHong Zhang    Input Parameter:
5064222ddf1SHong Zhang .  mat - the matrix
5074222ddf1SHong Zhang 
508*6718818eSStefano Zampini    Options Database Keys:
509*6718818eSStefano Zampini .    -mat_product_clear - Clear intermediate data structures after MatProductNumeric() has been called
5104222ddf1SHong Zhang 
511*6718818eSStefano Zampini    Level: intermediate
512*6718818eSStefano Zampini 
513*6718818eSStefano Zampini .seealso: MatSetFromOptions(), MatProductCreate(), MatProductCreateWithMat()
5144222ddf1SHong Zhang @*/
5154222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
5164222ddf1SHong Zhang {
5174222ddf1SHong Zhang   PetscErrorCode ierr;
5184222ddf1SHong Zhang 
5194222ddf1SHong Zhang   PetscFunctionBegin;
5204222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
521*6718818eSStefano Zampini   MatCheckProduct(mat,1);
522*6718818eSStefano Zampini   if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot call MatProductSetFromOptions with already present data");
523*6718818eSStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)mat);CHKERRQ(ierr);
524*6718818eSStefano Zampini   ierr = PetscOptionsBool("-mat_product_clear","Clear intermediate data structures after MatProductNumeric() has been called","MatProductClear",mat->product->clear,&mat->product->clear,NULL);CHKERRQ(ierr);
525*6718818eSStefano Zampini   ierr = PetscOptionsDeprecated("-mat_freeintermediatedatastructures","-mat_product_clear","3.13","Or call MatProductClear() after MatProductNumeric()");CHKERRQ(ierr);
526*6718818eSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
527*6718818eSStefano Zampini   ierr = MatProductSetFromOptions_Private(mat);CHKERRQ(ierr);
528*6718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after setup phase");
529*6718818eSStefano Zampini   PetscFunctionReturn(0);
530*6718818eSStefano Zampini }
531*6718818eSStefano Zampini 
532*6718818eSStefano Zampini /*@C
533*6718818eSStefano Zampini    MatProductView - View a MatProduct
534*6718818eSStefano Zampini 
535*6718818eSStefano Zampini    Logically Collective on Mat
536*6718818eSStefano Zampini 
537*6718818eSStefano Zampini    Input Parameter:
538*6718818eSStefano Zampini .  mat - the matrix obtained with MatProductCreate() or MatProductCreateWithMat()
539*6718818eSStefano Zampini 
540*6718818eSStefano Zampini    Level: intermediate
541*6718818eSStefano Zampini 
542*6718818eSStefano Zampini .seealso: MatView(), MatProductCreate(), MatProductCreateWithMat()
543*6718818eSStefano Zampini @*/
544*6718818eSStefano Zampini PetscErrorCode MatProductView(Mat mat, PetscViewer viewer)
545*6718818eSStefano Zampini {
546*6718818eSStefano Zampini   PetscErrorCode ierr;
547*6718818eSStefano Zampini 
548*6718818eSStefano Zampini   PetscFunctionBegin;
549*6718818eSStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
550*6718818eSStefano Zampini   if (!mat->product) PetscFunctionReturn(0);
551*6718818eSStefano Zampini   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer);CHKERRQ(ierr);}
552*6718818eSStefano Zampini   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
553*6718818eSStefano Zampini   PetscCheckSameComm(mat,1,viewer,2);
554*6718818eSStefano Zampini   if (mat->product->view) {
555*6718818eSStefano Zampini     ierr = (*mat->product->view)(mat,viewer);CHKERRQ(ierr);
556*6718818eSStefano Zampini   }
5574222ddf1SHong Zhang   PetscFunctionReturn(0);
5584222ddf1SHong Zhang }
5594222ddf1SHong Zhang 
5604222ddf1SHong Zhang /* ----------------------------------------------- */
561*6718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
562*6718818eSStefano Zampini  * they are dangerous and should be removed in the future */
5634222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
5644222ddf1SHong Zhang {
5654222ddf1SHong Zhang   PetscErrorCode ierr;
5664222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5674222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5684222ddf1SHong Zhang 
5694222ddf1SHong Zhang   PetscFunctionBegin;
5707a3c3d58SStefano 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);
5714222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
5727a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
5734222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
5744222ddf1SHong Zhang   PetscFunctionReturn(0);
5754222ddf1SHong Zhang }
5764222ddf1SHong Zhang 
5774222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(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 
5834222ddf1SHong Zhang   PetscFunctionBegin;
5847a3c3d58SStefano 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);
5854222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
5867a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
5874222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
5884222ddf1SHong Zhang   PetscFunctionReturn(0);
5894222ddf1SHong Zhang }
5904222ddf1SHong Zhang 
5914222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
5924222ddf1SHong Zhang {
5934222ddf1SHong Zhang   PetscErrorCode ierr;
5944222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5954222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5964222ddf1SHong Zhang 
5974222ddf1SHong Zhang   PetscFunctionBegin;
5987a3c3d58SStefano 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);
5994222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6007a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
6014222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6024222ddf1SHong Zhang   PetscFunctionReturn(0);
6034222ddf1SHong Zhang }
6044222ddf1SHong Zhang 
6054222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
6064222ddf1SHong Zhang {
6074222ddf1SHong Zhang   PetscErrorCode ierr;
6084222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6094222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6104222ddf1SHong Zhang 
6114222ddf1SHong Zhang   PetscFunctionBegin;
6127a3c3d58SStefano 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);
6134222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6147a3c3d58SStefano Zampini   ierr = (*mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
6154222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6164222ddf1SHong Zhang   PetscFunctionReturn(0);
6174222ddf1SHong Zhang }
6184222ddf1SHong Zhang 
6194222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
6204222ddf1SHong Zhang {
6214222ddf1SHong Zhang   PetscErrorCode ierr;
6224222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6234222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6244222ddf1SHong Zhang 
6254222ddf1SHong Zhang   PetscFunctionBegin;
6267a3c3d58SStefano 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);
6274222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6287a3c3d58SStefano Zampini   ierr = (*mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
6294222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6304222ddf1SHong Zhang   PetscFunctionReturn(0);
6314222ddf1SHong Zhang }
6324222ddf1SHong Zhang 
6334222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
6344222ddf1SHong Zhang {
6354222ddf1SHong Zhang   PetscErrorCode ierr;
6364222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6374222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
6384222ddf1SHong Zhang 
6394222ddf1SHong Zhang   PetscFunctionBegin;
6407a3c3d58SStefano 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);
6414222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
6427a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
6434222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
6444222ddf1SHong Zhang   PetscFunctionReturn(0);
6454222ddf1SHong Zhang }
6464222ddf1SHong Zhang 
647*6718818eSStefano Zampini /* ----------------------------------------------- */
648*6718818eSStefano Zampini 
6494222ddf1SHong Zhang /*@
6504222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
6514222ddf1SHong Zhang 
6524222ddf1SHong Zhang    Collective on Mat
6534222ddf1SHong Zhang 
654*6718818eSStefano Zampini    Input/Output Parameter:
655*6718818eSStefano Zampini .  mat - the matrix holding the product
6564222ddf1SHong Zhang 
6574222ddf1SHong Zhang    Level: intermediate
6584222ddf1SHong Zhang 
659*6718818eSStefano Zampini    Notes: MatProductSymbolic() must have been called on mat before calling this function
660*6718818eSStefano Zampini 
661*6718818eSStefano Zampini .seealso: MatProductCreate(), MatSetType(), MatProductSymbolic()
6624222ddf1SHong Zhang @*/
6634222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
6644222ddf1SHong Zhang {
6654222ddf1SHong Zhang   PetscErrorCode ierr;
6664222ddf1SHong Zhang 
6674222ddf1SHong Zhang   PetscFunctionBegin;
6684222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
669*6718818eSStefano Zampini   MatCheckProduct(mat,1);
6704222ddf1SHong Zhang   if (mat->ops->productnumeric) {
6714222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
6727a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSymbolic() first");
673*6718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after numeric phase");
674*6718818eSStefano Zampini   if (mat->product->clear) {
675*6718818eSStefano Zampini     ierr = MatProductClear(mat);CHKERRQ(ierr);
676*6718818eSStefano Zampini   }
6774222ddf1SHong Zhang   PetscFunctionReturn(0);
6784222ddf1SHong Zhang }
6794222ddf1SHong Zhang 
6804222ddf1SHong Zhang /* ----------------------------------------------- */
681*6718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
682*6718818eSStefano Zampini  * they are dangerous and should be removed in the future */
6834222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
6844222ddf1SHong Zhang {
6854222ddf1SHong Zhang   PetscErrorCode ierr;
6864222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6874222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6884222ddf1SHong Zhang 
6894222ddf1SHong Zhang   PetscFunctionBegin;
6907a3c3d58SStefano Zampini   if (!mat->ops->matmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
6917a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
6924222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
6934222ddf1SHong Zhang   PetscFunctionReturn(0);
6944222ddf1SHong Zhang }
6954222ddf1SHong Zhang 
6964222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
6974222ddf1SHong Zhang {
6984222ddf1SHong Zhang   PetscErrorCode ierr;
6994222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7004222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7014222ddf1SHong Zhang 
7024222ddf1SHong Zhang   PetscFunctionBegin;
7037a3c3d58SStefano Zampini   if (!mat->ops->transposematmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7047a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7054222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
7064222ddf1SHong Zhang   PetscFunctionReturn(0);
7074222ddf1SHong Zhang }
7084222ddf1SHong Zhang 
7094222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
7104222ddf1SHong Zhang {
7114222ddf1SHong Zhang   PetscErrorCode ierr;
7124222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7134222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7144222ddf1SHong Zhang 
7154222ddf1SHong Zhang   PetscFunctionBegin;
7167a3c3d58SStefano Zampini   if (!mat->ops->mattransposemultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7177a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7184222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
7194222ddf1SHong Zhang   PetscFunctionReturn(0);
7204222ddf1SHong Zhang }
7214222ddf1SHong Zhang 
7224222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
7234222ddf1SHong Zhang {
7244222ddf1SHong Zhang   PetscErrorCode ierr;
7254222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7264222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
7274222ddf1SHong Zhang 
7284222ddf1SHong Zhang   PetscFunctionBegin;
7297a3c3d58SStefano Zampini   if (!mat->ops->matmatmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7307a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
7314222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
7324222ddf1SHong Zhang   PetscFunctionReturn(0);
7334222ddf1SHong Zhang }
7344222ddf1SHong Zhang 
735*6718818eSStefano Zampini /* ----------------------------------------------- */
736*6718818eSStefano Zampini 
7374222ddf1SHong Zhang /*@
7384222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
7394222ddf1SHong Zhang 
7404222ddf1SHong Zhang    Collective on Mat
7414222ddf1SHong Zhang 
742*6718818eSStefano Zampini    Input/Output Parameter:
7434222ddf1SHong Zhang .  mat - the matrix to hold a product
7444222ddf1SHong Zhang 
7454222ddf1SHong Zhang    Level: intermediate
7464222ddf1SHong Zhang 
747*6718818eSStefano Zampini    Notes: MatProductSetFromOptions() must have been called on mat before calling this function
748*6718818eSStefano Zampini 
749*6718818eSStefano Zampini .seealso: MatProductCreate(), MatProductCreateWithMat(), MatProductSetFromOptions(), MatProductNumeric(), MatProductSetType(), MatProductSetAlgorithm()
7504222ddf1SHong Zhang @*/
7514222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
7524222ddf1SHong Zhang {
7534222ddf1SHong Zhang   PetscErrorCode ierr;
7544222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
7554222ddf1SHong Zhang 
7564222ddf1SHong Zhang   PetscFunctionBegin;
7574222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
758*6718818eSStefano Zampini   MatCheckProduct(mat,1);
759*6718818eSStefano Zampini   if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot run symbolic phase. Product data not empty");
7604222ddf1SHong Zhang 
7614222ddf1SHong Zhang   /* log event */
762*6718818eSStefano Zampini   switch (mat->product->type) {
7634222ddf1SHong Zhang   case MATPRODUCT_AB:
7644222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
7654222ddf1SHong Zhang     break;
7664222ddf1SHong Zhang   case MATPRODUCT_AtB:
7674222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
7684222ddf1SHong Zhang     break;
7694222ddf1SHong Zhang   case MATPRODUCT_ABt:
7704222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
7714222ddf1SHong Zhang     break;
7724222ddf1SHong Zhang   case MATPRODUCT_PtAP:
7734222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
7744222ddf1SHong Zhang     break;
7754222ddf1SHong Zhang   case MATPRODUCT_RARt:
7764222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
7774222ddf1SHong Zhang     break;
7784222ddf1SHong Zhang   case MATPRODUCT_ABC:
7794222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
7804222ddf1SHong Zhang     break;
781*6718818eSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[mat->product->type]);
7824222ddf1SHong Zhang   }
7834222ddf1SHong Zhang 
784*6718818eSStefano Zampini   mat->ops->productnumeric = NULL;
7854222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
7864222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
7874222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
7884222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
7897a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetFromOptions() first");
790*6718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after symbolic phase");
791*6718818eSStefano Zampini   if (!mat->ops->productnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Symbolic phase did not specify the numeric phase");
7924222ddf1SHong Zhang   PetscFunctionReturn(0);
7934222ddf1SHong Zhang }
7944222ddf1SHong Zhang 
7954222ddf1SHong Zhang /*@
7964222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
7974222ddf1SHong Zhang 
7984222ddf1SHong Zhang    Collective on Mat
7994222ddf1SHong Zhang 
8004222ddf1SHong Zhang    Input Parameters:
8014222ddf1SHong Zhang +  mat - the matrix product
8024222ddf1SHong 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.
8034222ddf1SHong Zhang 
8044222ddf1SHong Zhang    Level: intermediate
8054222ddf1SHong Zhang 
8064222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
8074222ddf1SHong Zhang @*/
8084222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
8094222ddf1SHong Zhang {
8104222ddf1SHong Zhang   PetscFunctionBegin;
8114222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
812*6718818eSStefano Zampini   MatCheckProduct(mat,1);
813*6718818eSStefano Zampini   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0;
814*6718818eSStefano Zampini   else mat->product->fill = fill;
8154222ddf1SHong Zhang   PetscFunctionReturn(0);
8164222ddf1SHong Zhang }
8174222ddf1SHong Zhang 
8184222ddf1SHong Zhang /*@
8194222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
8204222ddf1SHong Zhang 
8214222ddf1SHong Zhang    Collective on Mat
8224222ddf1SHong Zhang 
8234222ddf1SHong Zhang    Input Parameters:
8244222ddf1SHong Zhang +  mat - the matrix product
8254222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
8264222ddf1SHong Zhang 
8274222ddf1SHong Zhang    Level: intermediate
8284222ddf1SHong Zhang 
829*6718818eSStefano Zampini .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate(), MatProductAlgorithm
8304222ddf1SHong Zhang @*/
8314222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
8324222ddf1SHong Zhang {
8337a3c3d58SStefano Zampini   PetscErrorCode ierr;
8344222ddf1SHong Zhang 
8354222ddf1SHong Zhang   PetscFunctionBegin;
8364222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
837*6718818eSStefano Zampini   MatCheckProduct(mat,1);
838*6718818eSStefano Zampini   ierr = PetscFree(mat->product->alg);CHKERRQ(ierr);
839*6718818eSStefano Zampini   ierr = PetscStrallocpy(alg,&mat->product->alg);CHKERRQ(ierr);
8404222ddf1SHong Zhang   PetscFunctionReturn(0);
8414222ddf1SHong Zhang }
8424222ddf1SHong Zhang 
8434222ddf1SHong Zhang /*@
844*6718818eSStefano Zampini    MatProductSetType - Sets a particular matrix product type
8454222ddf1SHong Zhang 
8464222ddf1SHong Zhang    Collective on Mat
8474222ddf1SHong Zhang 
8484222ddf1SHong Zhang    Input Parameters:
8494222ddf1SHong Zhang +  mat - the matrix
8504222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
8514222ddf1SHong Zhang 
8524222ddf1SHong Zhang    Level: intermediate
8534222ddf1SHong Zhang 
854*6718818eSStefano Zampini .seealso: MatProductCreate(), MatProductType
8554222ddf1SHong Zhang @*/
8564222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
8574222ddf1SHong Zhang {
858*6718818eSStefano Zampini   PetscErrorCode ierr;
8594222ddf1SHong Zhang 
8604222ddf1SHong Zhang   PetscFunctionBegin;
8614222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
862*6718818eSStefano Zampini   MatCheckProduct(mat,1);
8637a3c3d58SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,productype,2);
864*6718818eSStefano Zampini   if (productype != mat->product->type) {
865*6718818eSStefano Zampini     if (mat->product->destroy) {
866*6718818eSStefano Zampini       ierr = (*mat->product->destroy)(mat->product->data);CHKERRQ(ierr);
8674222ddf1SHong Zhang     }
868*6718818eSStefano Zampini     mat->product->destroy = NULL;
869*6718818eSStefano Zampini     mat->product->data = NULL;
870*6718818eSStefano Zampini     mat->ops->productsymbolic = NULL;
871*6718818eSStefano Zampini     mat->ops->productnumeric  = NULL;
872*6718818eSStefano Zampini   }
873*6718818eSStefano Zampini   mat->product->type = productype;
8744222ddf1SHong Zhang   PetscFunctionReturn(0);
8754222ddf1SHong Zhang }
8764222ddf1SHong Zhang 
8774417c5e8SHong Zhang /*@
8784417c5e8SHong Zhang    MatProductClear - Clears matrix product internal structure.
8794417c5e8SHong Zhang 
8804417c5e8SHong Zhang    Collective on Mat
8814417c5e8SHong Zhang 
8824417c5e8SHong Zhang    Input Parameters:
8834417c5e8SHong Zhang .  mat - the product matrix
8844417c5e8SHong Zhang 
8854417c5e8SHong Zhang    Level: intermediate
886*6718818eSStefano Zampini 
887*6718818eSStefano Zampini    Notes: this function should be called to remove any intermediate data used by the product
888*6718818eSStefano Zampini           After having called this function, MatProduct operations can no longer be used on mat
8894417c5e8SHong Zhang @*/
8904417c5e8SHong Zhang PetscErrorCode MatProductClear(Mat mat)
8914417c5e8SHong Zhang {
8924417c5e8SHong Zhang   PetscErrorCode ierr;
8934417c5e8SHong Zhang   Mat_Product    *product = mat->product;
8944417c5e8SHong Zhang 
8954417c5e8SHong Zhang   PetscFunctionBegin;
8967a3c3d58SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8974417c5e8SHong Zhang   if (product) {
8984417c5e8SHong Zhang     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
8994417c5e8SHong Zhang     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
9004417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
9017a3c3d58SStefano Zampini     ierr = PetscFree(product->alg);CHKERRQ(ierr);
9024417c5e8SHong Zhang     ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr);
903*6718818eSStefano Zampini     if (product->destroy) {
904*6718818eSStefano Zampini       ierr = (*product->destroy)(product->data);CHKERRQ(ierr);
9054417c5e8SHong Zhang     }
906*6718818eSStefano Zampini   }
907*6718818eSStefano Zampini   ierr = PetscFree(mat->product);CHKERRQ(ierr);
908*6718818eSStefano Zampini   mat->ops->productsymbolic = NULL;
909*6718818eSStefano Zampini   mat->ops->productnumeric = NULL;
9104417c5e8SHong Zhang   PetscFunctionReturn(0);
9114417c5e8SHong Zhang }
9124417c5e8SHong Zhang 
9134222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
9144417c5e8SHong Zhang PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
9154222ddf1SHong Zhang {
9164222ddf1SHong Zhang   PetscErrorCode ierr;
9174222ddf1SHong Zhang   Mat_Product    *product=NULL;
9184222ddf1SHong Zhang 
9194222ddf1SHong Zhang   PetscFunctionBegin;
920*6718818eSStefano Zampini   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
921*6718818eSStefano Zampini   if (D->product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"Product already present");
9224222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
9234222ddf1SHong Zhang   product->A        = A;
9244222ddf1SHong Zhang   product->B        = B;
9254222ddf1SHong Zhang   product->C        = C;
926*6718818eSStefano Zampini   product->type     = MATPRODUCT_UNSPECIFIED;
9274222ddf1SHong Zhang   product->Dwork    = NULL;
9284222ddf1SHong Zhang   product->api_user = PETSC_FALSE;
929*6718818eSStefano Zampini   product->clear    = PETSC_FALSE;
9304222ddf1SHong Zhang   D->product        = product;
9314417c5e8SHong Zhang 
9327a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(D,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
933*6718818eSStefano Zampini   ierr = MatProductSetFill(D,PETSC_DEFAULT);CHKERRQ(ierr);
9347a3c3d58SStefano Zampini 
9354417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
9364417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
9374417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
9384222ddf1SHong Zhang   PetscFunctionReturn(0);
9394222ddf1SHong Zhang }
9404222ddf1SHong Zhang 
9414222ddf1SHong Zhang /*@
9424222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
9434222ddf1SHong Zhang 
9444222ddf1SHong Zhang    Collective on Mat
9454222ddf1SHong Zhang 
9464222ddf1SHong Zhang    Input Parameters:
9474222ddf1SHong Zhang +  A - the first matrix
9484222ddf1SHong Zhang .  B - the second matrix
9494222ddf1SHong Zhang .  C - the third matrix (optional)
9504222ddf1SHong Zhang -  D - the matrix which will be used as a product
9514222ddf1SHong Zhang 
9524222ddf1SHong Zhang    Output Parameters:
9534222ddf1SHong Zhang .  D - the product matrix
9544222ddf1SHong Zhang 
955*6718818eSStefano Zampini    Notes:
956*6718818eSStefano Zampini      Any product data attached to D will be cleared
957*6718818eSStefano Zampini 
9584222ddf1SHong Zhang    Level: intermediate
9594222ddf1SHong Zhang 
960*6718818eSStefano Zampini .seealso: MatProductCreate(), MatProductClear()
9614222ddf1SHong Zhang @*/
9624222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
9634222ddf1SHong Zhang {
9644222ddf1SHong Zhang   PetscErrorCode ierr;
9654222ddf1SHong Zhang 
9664222ddf1SHong Zhang   PetscFunctionBegin;
9674222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9684222ddf1SHong Zhang   PetscValidType(A,1);
9694222ddf1SHong Zhang   MatCheckPreallocated(A,1);
9704222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9714222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9724222ddf1SHong Zhang 
9734222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
9744222ddf1SHong Zhang   PetscValidType(B,2);
9754222ddf1SHong Zhang   MatCheckPreallocated(B,2);
9764222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9774222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9784222ddf1SHong Zhang 
9794222ddf1SHong Zhang   if (C) {
9804222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
9814222ddf1SHong Zhang     PetscValidType(C,3);
9824222ddf1SHong Zhang     MatCheckPreallocated(C,3);
9834222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9844222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9854222ddf1SHong Zhang   }
9864222ddf1SHong Zhang 
9874222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
9884222ddf1SHong Zhang   PetscValidType(D,4);
9894222ddf1SHong Zhang   MatCheckPreallocated(D,4);
9904222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9914222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9924222ddf1SHong Zhang 
9934222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
994*6718818eSStefano Zampini   ierr = MatProductClear(D);CHKERRQ(ierr);
9954222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
9964222ddf1SHong Zhang   PetscFunctionReturn(0);
9974222ddf1SHong Zhang }
9984222ddf1SHong Zhang 
9994222ddf1SHong Zhang /*@
10004222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
10014222ddf1SHong Zhang 
10024222ddf1SHong Zhang    Collective on Mat
10034222ddf1SHong Zhang 
10044222ddf1SHong Zhang    Input Parameters:
10054222ddf1SHong Zhang +  A - the first matrix
10064222ddf1SHong Zhang .  B - the second matrix
10074222ddf1SHong Zhang -  C - the third matrix (optional)
10084222ddf1SHong Zhang 
10094222ddf1SHong Zhang    Output Parameters:
10104222ddf1SHong Zhang .  D - the product matrix
10114222ddf1SHong Zhang 
10124222ddf1SHong Zhang    Level: intermediate
10134222ddf1SHong Zhang 
10144222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
10154222ddf1SHong Zhang @*/
10164222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
10174222ddf1SHong Zhang {
10184222ddf1SHong Zhang   PetscErrorCode ierr;
10194222ddf1SHong Zhang 
10204222ddf1SHong Zhang   PetscFunctionBegin;
10214222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10224222ddf1SHong Zhang   PetscValidType(A,1);
10234222ddf1SHong Zhang   MatCheckPreallocated(A,1);
10244222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10254222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10264222ddf1SHong Zhang 
10274222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10284222ddf1SHong Zhang   PetscValidType(B,2);
10294222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10304222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10314222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10324222ddf1SHong Zhang 
10334222ddf1SHong Zhang   if (C) {
10344222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10354222ddf1SHong Zhang     PetscValidType(C,3);
10364222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10374222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10384222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10394222ddf1SHong Zhang   }
10404222ddf1SHong Zhang 
10414222ddf1SHong Zhang   PetscValidPointer(D,4);
10424222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
10434222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
10444222ddf1SHong Zhang   PetscFunctionReturn(0);
10454222ddf1SHong Zhang }
1046