xref: /petsc/src/mat/interface/matproduct.c (revision 8d7b260cab71c4b5b13ed763b13fce8991d43895)
14222ddf1SHong Zhang 
24222ddf1SHong Zhang /*
34222ddf1SHong Zhang     Routines for matrix products. Calling procedure:
44222ddf1SHong Zhang 
56718818eSStefano Zampini     MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D)
66718818eSStefano Zampini     MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC)
76718818eSStefano Zampini     MatProductSetAlgorithm(D, alg)
86718818eSStefano Zampini     MatProductSetFill(D,fill)
96718818eSStefano Zampini     MatProductSetFromOptions(D)
106718818eSStefano Zampini       -> MatProductSetFromOptions_Private(D)
114222ddf1SHong Zhang            # Check matrix global sizes
126718818eSStefano Zampini            if the matrices have the same setfromoptions routine, use it
136718818eSStefano Zampini            if not, try:
146718818eSStefano Zampini              -> Query MatProductSetFromOptions_Atype_Btype_Ctype_C(D) from A, B and C (in order)
156718818eSStefano Zampini              if found -> run the specific setup that must set the symbolic operation (these callbacks should never fail)
166718818eSStefano Zampini            if callback not found or no symbolic operation set
176718818eSStefano Zampini              -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANPOSEMAT)
186718818eSStefano Zampini            if dispatch found but combination still not present do
196718818eSStefano Zampini              -> check if B is dense and product type AtB or AB -> if true, basic looping of dense columns
206718818eSStefano Zampini              -> check if triple product (PtAP, RARt or ABC) -> if true, set the Basic routines
216718818eSStefano Zampini 
226718818eSStefano 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
266718818eSStefano Zampini     #    Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype if found
274222ddf1SHong Zhang 
286718818eSStefano Zampini     MatProductSymbolic(D)
296718818eSStefano Zampini       # Call MatProductSymbolic_productype_Atype_Btype_Ctype()
306718818eSStefano Zampini         the callback must set the numeric phase D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype
314222ddf1SHong Zhang 
326718818eSStefano Zampini     MatProductNumeric(D)
336718818eSStefano Zampini       # Call the numeric phase
346718818eSStefano Zampini 
356718818eSStefano Zampini     # The symbolic phases are allowed to set extra data structures and attach those to the product
366718818eSStefano Zampini     # this additional data can be reused between multiple numeric phases with the same matrices
376718818eSStefano Zampini     # if not needed, call
386718818eSStefano Zampini     MatProductClear(D)
394222ddf1SHong Zhang */
404222ddf1SHong Zhang 
414222ddf1SHong Zhang #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
424222ddf1SHong Zhang 
436718818eSStefano Zampini const char *const MatProductTypes[] = {"UNSPECIFIED","AB","AtB","ABt","PtAP","RARt","ABC"};
44544a5e07SHong Zhang 
456718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
466718818eSStefano Zampini  * they are dangerous and should be removed in the future */
475415d71bSStefano Zampini static PetscErrorCode MatProductNumeric_PtAP_Unsafe(Mat C)
484222ddf1SHong Zhang {
494222ddf1SHong Zhang   PetscErrorCode ierr;
504222ddf1SHong Zhang   Mat_Product    *product = C->product;
514222ddf1SHong Zhang   Mat            P = product->B,AP = product->Dwork;
524222ddf1SHong Zhang 
534222ddf1SHong Zhang   PetscFunctionBegin;
544222ddf1SHong Zhang   /* AP = A*P */
554222ddf1SHong Zhang   ierr = MatProductNumeric(AP);CHKERRQ(ierr);
564222ddf1SHong Zhang   /* C = P^T*AP */
577a3c3d58SStefano Zampini   if (!C->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
587a3c3d58SStefano Zampini   ierr = (*C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr);
594222ddf1SHong Zhang   PetscFunctionReturn(0);
604222ddf1SHong Zhang }
614222ddf1SHong Zhang 
625415d71bSStefano Zampini static PetscErrorCode MatProductSymbolic_PtAP_Unsafe(Mat C)
634222ddf1SHong Zhang {
644222ddf1SHong Zhang   PetscErrorCode ierr;
654222ddf1SHong Zhang   Mat_Product    *product = C->product;
664222ddf1SHong Zhang   Mat            A=product->A,P=product->B,AP;
674222ddf1SHong Zhang   PetscReal      fill=product->fill;
684222ddf1SHong Zhang 
694222ddf1SHong Zhang   PetscFunctionBegin;
706718818eSStefano 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);
714222ddf1SHong Zhang   /* AP = A*P */
724222ddf1SHong Zhang   ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr);
734222ddf1SHong Zhang   ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr);
747a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(AP,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
754222ddf1SHong Zhang   ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr);
764222ddf1SHong Zhang   ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr);
774222ddf1SHong Zhang   ierr = MatProductSymbolic(AP);CHKERRQ(ierr);
784222ddf1SHong Zhang 
794222ddf1SHong Zhang   /* C = P^T*AP */
804222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr);
817a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
824222ddf1SHong Zhang   product->A = P;
834222ddf1SHong Zhang   product->B = AP;
844222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
854222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
864222ddf1SHong Zhang 
874222ddf1SHong Zhang   /* resume user's original input matrix setting for A and B */
884222ddf1SHong Zhang   product->A     = A;
894222ddf1SHong Zhang   product->B     = P;
904222ddf1SHong Zhang   product->Dwork = AP;
914222ddf1SHong Zhang 
925415d71bSStefano Zampini   C->ops->productnumeric = MatProductNumeric_PtAP_Unsafe;
934222ddf1SHong Zhang   PetscFunctionReturn(0);
944222ddf1SHong Zhang }
954222ddf1SHong Zhang 
965415d71bSStefano Zampini static PetscErrorCode MatProductNumeric_RARt_Unsafe(Mat C)
974222ddf1SHong Zhang {
984222ddf1SHong Zhang   PetscErrorCode ierr;
994222ddf1SHong Zhang   Mat_Product    *product = C->product;
1004222ddf1SHong Zhang   Mat            R=product->B,RA=product->Dwork;
1014222ddf1SHong Zhang 
1024222ddf1SHong Zhang   PetscFunctionBegin;
1034222ddf1SHong Zhang   /* RA = R*A */
1044222ddf1SHong Zhang   ierr = MatProductNumeric(RA);CHKERRQ(ierr);
1054222ddf1SHong Zhang   /* C = RA*R^T */
1067a3c3d58SStefano Zampini   if (!C->ops->mattransposemultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage");
1077a3c3d58SStefano Zampini   ierr = (*C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr);
1084222ddf1SHong Zhang   PetscFunctionReturn(0);
1094222ddf1SHong Zhang }
1104222ddf1SHong Zhang 
1115415d71bSStefano Zampini static PetscErrorCode MatProductSymbolic_RARt_Unsafe(Mat C)
1124222ddf1SHong Zhang {
1134222ddf1SHong Zhang   PetscErrorCode ierr;
1144222ddf1SHong Zhang   Mat_Product    *product = C->product;
1154222ddf1SHong Zhang   Mat            A=product->A,R=product->B,RA;
1164222ddf1SHong Zhang   PetscReal      fill=product->fill;
1174222ddf1SHong Zhang 
1184222ddf1SHong Zhang   PetscFunctionBegin;
1196718818eSStefano 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);
1204222ddf1SHong Zhang   /* RA = R*A */
1214222ddf1SHong Zhang   ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr);
1224222ddf1SHong Zhang   ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr);
1237a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(RA,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1244222ddf1SHong Zhang   ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr);
1254222ddf1SHong Zhang   ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr);
1264222ddf1SHong Zhang   ierr = MatProductSymbolic(RA);CHKERRQ(ierr);
1274222ddf1SHong Zhang 
1284222ddf1SHong Zhang   /* C = RA*R^T */
1294222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr);
1307a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1314222ddf1SHong Zhang   product->A = RA;
1324222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
1334222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
1344222ddf1SHong Zhang 
1354222ddf1SHong Zhang   /* resume user's original input matrix setting for A */
1364222ddf1SHong Zhang   product->A     = A;
1374222ddf1SHong Zhang   product->Dwork = RA; /* save here so it will be destroyed with product C */
1385415d71bSStefano Zampini   C->ops->productnumeric = MatProductNumeric_RARt_Unsafe;
1394222ddf1SHong Zhang   PetscFunctionReturn(0);
1404222ddf1SHong Zhang }
1414222ddf1SHong Zhang 
1425415d71bSStefano Zampini static PetscErrorCode MatProductNumeric_ABC_Unsafe(Mat mat)
1434222ddf1SHong Zhang {
1444222ddf1SHong Zhang   PetscErrorCode ierr;
1454222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1464222ddf1SHong Zhang   Mat            A=product->A,BC=product->Dwork;
1474222ddf1SHong Zhang 
1484222ddf1SHong Zhang   PetscFunctionBegin;
1494222ddf1SHong Zhang   /* Numeric BC = B*C */
1504222ddf1SHong Zhang   ierr = MatProductNumeric(BC);CHKERRQ(ierr);
1514222ddf1SHong Zhang   /* Numeric mat = A*BC */
1527a3c3d58SStefano Zampini   if (!mat->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage");
1537a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr);
1544222ddf1SHong Zhang   PetscFunctionReturn(0);
1554222ddf1SHong Zhang }
1564222ddf1SHong Zhang 
1575415d71bSStefano Zampini static PetscErrorCode MatProductSymbolic_ABC_Unsafe(Mat mat)
1584222ddf1SHong Zhang {
1594222ddf1SHong Zhang   PetscErrorCode ierr;
1604222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1614222ddf1SHong Zhang   Mat            B=product->B,C=product->C,BC;
1624222ddf1SHong Zhang   PetscReal      fill=product->fill;
1634222ddf1SHong Zhang 
1644222ddf1SHong Zhang   PetscFunctionBegin;
1656718818eSStefano 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);
1664222ddf1SHong Zhang   /* Symbolic BC = B*C */
1674222ddf1SHong Zhang   ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr);
1684222ddf1SHong Zhang   ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr);
1697a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1704222ddf1SHong Zhang   ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr);
1714222ddf1SHong Zhang   ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr);
1724222ddf1SHong Zhang   ierr = MatProductSymbolic(BC);CHKERRQ(ierr);
1734222ddf1SHong Zhang 
1744222ddf1SHong Zhang   /* Symbolic mat = A*BC */
1754222ddf1SHong Zhang   ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr);
1767a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(mat,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
1774222ddf1SHong Zhang   product->B     = BC;
1784222ddf1SHong Zhang   product->Dwork = BC;
1794222ddf1SHong Zhang   ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr);
1804222ddf1SHong Zhang   ierr = MatProductSymbolic(mat);CHKERRQ(ierr);
1814222ddf1SHong Zhang 
1824222ddf1SHong Zhang   /* resume user's original input matrix setting for B */
1834222ddf1SHong Zhang   product->B = B;
1845415d71bSStefano Zampini   mat->ops->productnumeric = MatProductNumeric_ABC_Unsafe;
1854222ddf1SHong Zhang   PetscFunctionReturn(0);
1864222ddf1SHong Zhang }
1874222ddf1SHong Zhang 
1885415d71bSStefano Zampini static PetscErrorCode MatProductSymbolic_Unsafe(Mat mat)
1894222ddf1SHong Zhang {
1904222ddf1SHong Zhang   PetscErrorCode ierr;
1914222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1924222ddf1SHong Zhang 
1934222ddf1SHong Zhang   PetscFunctionBegin;
1944222ddf1SHong Zhang   switch (product->type) {
1954222ddf1SHong Zhang   case MATPRODUCT_PtAP:
1965415d71bSStefano Zampini     ierr = MatProductSymbolic_PtAP_Unsafe(mat);CHKERRQ(ierr);
1974222ddf1SHong Zhang     break;
1984222ddf1SHong Zhang   case MATPRODUCT_RARt:
1995415d71bSStefano Zampini     ierr = MatProductSymbolic_RARt_Unsafe(mat);CHKERRQ(ierr);
2004222ddf1SHong Zhang     break;
2014222ddf1SHong Zhang   case MATPRODUCT_ABC:
2025415d71bSStefano Zampini     ierr = MatProductSymbolic_ABC_Unsafe(mat);CHKERRQ(ierr);
2034222ddf1SHong Zhang     break;
2046718818eSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]);
2054222ddf1SHong Zhang   }
2064222ddf1SHong Zhang   PetscFunctionReturn(0);
2074222ddf1SHong Zhang }
2084222ddf1SHong Zhang 
2094222ddf1SHong Zhang /* ----------------------------------------------- */
2104222ddf1SHong Zhang /*@C
2114222ddf1SHong Zhang    MatProductReplaceMats - Replace input matrices for a matrix product.
2124222ddf1SHong Zhang 
2134222ddf1SHong Zhang    Collective on Mat
2144222ddf1SHong Zhang 
2154222ddf1SHong Zhang    Input Parameters:
2164222ddf1SHong Zhang +  A - the matrix or NULL if not being replaced
2174222ddf1SHong Zhang .  B - the matrix or NULL if not being replaced
2184222ddf1SHong Zhang .  C - the matrix or NULL if not being replaced
2194222ddf1SHong Zhang -  D - the matrix product
2204222ddf1SHong Zhang 
2214222ddf1SHong Zhang    Level: intermediate
2224222ddf1SHong Zhang 
2234222ddf1SHong Zhang    Notes:
2246718818eSStefano Zampini      To reuse the symbolic phase, input matrices must have exactly the same data structure as the replaced one.
225fa046f9fSJunchao Zhang      If the type of any of the input matrices is different than what was previously used, or their symmetry changed but
226fa046f9fSJunchao Zhang      the symbolic phase took advantage of their symmetry, the product is cleared and MatProductSetFromOptions()/MatProductSymbolic() are invoked again.
2274222ddf1SHong Zhang 
2286718818eSStefano Zampini .seealso: MatProductCreate(), MatProductSetFromOptions(), MatProductSymbolic(). MatProductClear()
2294222ddf1SHong Zhang @*/
2304222ddf1SHong Zhang PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D)
2314222ddf1SHong Zhang {
2324417c5e8SHong Zhang   PetscErrorCode ierr;
2336718818eSStefano Zampini   Mat_Product    *product;
2346718818eSStefano Zampini   PetscBool      flgA = PETSC_TRUE,flgB = PETSC_TRUE,flgC = PETSC_TRUE;
2354222ddf1SHong Zhang 
2364222ddf1SHong Zhang   PetscFunctionBegin;
2377a3c3d58SStefano Zampini   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
2386718818eSStefano Zampini   MatCheckProduct(D,4);
2396718818eSStefano Zampini   product = D->product;
2404222ddf1SHong Zhang   if (A) {
2417a3c3d58SStefano Zampini     PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2426718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
2436718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->A,((PetscObject)A)->type_name,&flgA);CHKERRQ(ierr);
244fa046f9fSJunchao Zhang     if (product->symbolic_used_the_fact_A_is_symmetric && !A->symmetric) { /* symbolic was built around a symmetric A, but the new A is not anymore */
245fa046f9fSJunchao Zhang       flgA = PETSC_FALSE;
246fa046f9fSJunchao Zhang       product->symbolic_used_the_fact_A_is_symmetric = PETSC_FALSE; /* reinit */
247fa046f9fSJunchao Zhang     }
2486718818eSStefano Zampini     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2494222ddf1SHong Zhang     product->A = A;
2504222ddf1SHong Zhang   }
2514222ddf1SHong Zhang   if (B) {
2527a3c3d58SStefano Zampini     PetscValidHeaderSpecific(B,MAT_CLASSID,2);
2536718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
2546718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->B,((PetscObject)B)->type_name,&flgB);CHKERRQ(ierr);
255fa046f9fSJunchao Zhang     if (product->symbolic_used_the_fact_B_is_symmetric && !B->symmetric) {
256fa046f9fSJunchao Zhang       flgB = PETSC_FALSE;
257fa046f9fSJunchao Zhang       product->symbolic_used_the_fact_B_is_symmetric = PETSC_FALSE; /* reinit */
258fa046f9fSJunchao Zhang     }
2596718818eSStefano Zampini     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
2604222ddf1SHong Zhang     product->B = B;
2614222ddf1SHong Zhang   }
2624417c5e8SHong Zhang   if (C) {
2637a3c3d58SStefano Zampini     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
2646718818eSStefano Zampini     ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
2656718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)product->C,((PetscObject)C)->type_name,&flgC);CHKERRQ(ierr);
266fa046f9fSJunchao Zhang     if (product->symbolic_used_the_fact_C_is_symmetric && !C->symmetric) {
267fa046f9fSJunchao Zhang       flgC = PETSC_FALSE;
268fa046f9fSJunchao Zhang       product->symbolic_used_the_fact_C_is_symmetric = PETSC_FALSE; /* reinit */
269fa046f9fSJunchao Zhang     }
2706718818eSStefano Zampini     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
2714417c5e8SHong Zhang     product->C = C;
2724417c5e8SHong Zhang   }
2736718818eSStefano Zampini   /* Any of the replaced mats is of a different type, reset */
2746718818eSStefano Zampini   if (!flgA || !flgB || !flgC) {
2756718818eSStefano Zampini     if (D->product->destroy) {
2766718818eSStefano Zampini       ierr = (*D->product->destroy)(D->product->data);CHKERRQ(ierr);
2776718818eSStefano Zampini     }
2786718818eSStefano Zampini     D->product->destroy = NULL;
2796718818eSStefano Zampini     D->product->data = NULL;
2806718818eSStefano Zampini     if (D->ops->productnumeric || D->ops->productsymbolic) {
2816718818eSStefano Zampini       ierr = MatProductSetFromOptions(D);CHKERRQ(ierr);
2826718818eSStefano Zampini       ierr = MatProductSymbolic(D);CHKERRQ(ierr);
2836718818eSStefano Zampini     }
2846718818eSStefano Zampini   }
2854222ddf1SHong Zhang   PetscFunctionReturn(0);
2864222ddf1SHong Zhang }
2874222ddf1SHong Zhang 
2887a3c3d58SStefano Zampini static PetscErrorCode MatProductNumeric_X_Dense(Mat C)
2897a3c3d58SStefano Zampini {
2907a3c3d58SStefano Zampini   PetscErrorCode ierr;
2917a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
2927a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
2937a3c3d58SStefano Zampini   PetscInt       k, K = B->cmap->N;
2947a3c3d58SStefano Zampini   PetscBool      t = PETSC_TRUE,iscuda = PETSC_FALSE;
2957a3c3d58SStefano Zampini   PetscBool      Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE;
2967a3c3d58SStefano Zampini   char           *Btype = NULL,*Ctype = NULL;
2977a3c3d58SStefano Zampini 
2987a3c3d58SStefano Zampini   PetscFunctionBegin;
2997a3c3d58SStefano Zampini   switch (product->type) {
3007a3c3d58SStefano Zampini   case MATPRODUCT_AB:
3017a3c3d58SStefano Zampini     t = PETSC_FALSE;
3027a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
3037a3c3d58SStefano Zampini     break;
3047a3c3d58SStefano 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);
3057a3c3d58SStefano Zampini   }
3067a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
3077a3c3d58SStefano Zampini     VecType vtype;
3087a3c3d58SStefano Zampini 
3097a3c3d58SStefano Zampini     ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr);
3107a3c3d58SStefano Zampini     ierr = PetscStrcmp(vtype,VECCUDA,&iscuda);CHKERRQ(ierr);
3117a3c3d58SStefano Zampini     if (!iscuda) {
3127a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
3137a3c3d58SStefano Zampini     }
3147a3c3d58SStefano Zampini     if (!iscuda) {
3157a3c3d58SStefano Zampini       ierr = PetscStrcmp(vtype,VECMPICUDA,&iscuda);CHKERRQ(ierr);
3167a3c3d58SStefano Zampini     }
3177a3c3d58SStefano Zampini     if (iscuda) { /* Make sure we have up-to-date data on the GPU */
3187a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)B)->type_name,&Btype);CHKERRQ(ierr);
3197a3c3d58SStefano Zampini       ierr = PetscStrallocpy(((PetscObject)C)->type_name,&Ctype);CHKERRQ(ierr);
3207a3c3d58SStefano Zampini       ierr = MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
3217a3c3d58SStefano Zampini       if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */
3227a3c3d58SStefano Zampini         ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3237a3c3d58SStefano Zampini         ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3247a3c3d58SStefano Zampini       }
3257a3c3d58SStefano Zampini       ierr = MatConvert(C,MATDENSECUDA,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
3267a3c3d58SStefano Zampini     } else { /* Make sure we have up-to-date data on the CPU */
3277a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
3287a3c3d58SStefano Zampini       Bcpu = B->boundtocpu;
3297a3c3d58SStefano Zampini       Ccpu = C->boundtocpu;
3307a3c3d58SStefano Zampini #endif
3317a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,PETSC_TRUE);CHKERRQ(ierr);
3327a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,PETSC_TRUE);CHKERRQ(ierr);
3337a3c3d58SStefano Zampini     }
3347a3c3d58SStefano Zampini   }
3357a3c3d58SStefano Zampini   for (k=0;k<K;k++) {
3367a3c3d58SStefano Zampini     Vec x,y;
3377a3c3d58SStefano Zampini 
3387a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecRead(B,k,&x);CHKERRQ(ierr);
3397a3c3d58SStefano Zampini     ierr = MatDenseGetColumnVecWrite(C,k,&y);CHKERRQ(ierr);
3407a3c3d58SStefano Zampini     if (t) {
3417a3c3d58SStefano Zampini       ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr);
3427a3c3d58SStefano Zampini     } else {
3437a3c3d58SStefano Zampini       ierr = MatMult(A,x,y);CHKERRQ(ierr);
3447a3c3d58SStefano Zampini     }
3457a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecRead(B,k,&x);CHKERRQ(ierr);
3467a3c3d58SStefano Zampini     ierr = MatDenseRestoreColumnVecWrite(C,k,&y);CHKERRQ(ierr);
3477a3c3d58SStefano Zampini   }
3487a3c3d58SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3497a3c3d58SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3507a3c3d58SStefano Zampini   if (PetscDefined(HAVE_CUDA)) {
3517a3c3d58SStefano Zampini     if (iscuda) {
3527a3c3d58SStefano Zampini       ierr = MatConvert(B,Btype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
3537a3c3d58SStefano Zampini       ierr = MatConvert(C,Ctype,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr);
3547a3c3d58SStefano Zampini     } else {
3557a3c3d58SStefano Zampini       ierr = MatBindToCPU(B,Bcpu);CHKERRQ(ierr);
3567a3c3d58SStefano Zampini       ierr = MatBindToCPU(C,Ccpu);CHKERRQ(ierr);
3577a3c3d58SStefano Zampini     }
3587a3c3d58SStefano Zampini   }
3597a3c3d58SStefano Zampini   ierr = PetscFree(Btype);CHKERRQ(ierr);
3607a3c3d58SStefano Zampini   ierr = PetscFree(Ctype);CHKERRQ(ierr);
3617a3c3d58SStefano Zampini   PetscFunctionReturn(0);
3627a3c3d58SStefano Zampini }
3637a3c3d58SStefano Zampini 
3647a3c3d58SStefano Zampini static PetscErrorCode MatProductSymbolic_X_Dense(Mat C)
3657a3c3d58SStefano Zampini {
3667a3c3d58SStefano Zampini   PetscErrorCode ierr;
3677a3c3d58SStefano Zampini   Mat_Product    *product = C->product;
3687a3c3d58SStefano Zampini   Mat            A = product->A, B = product->B;
3697a3c3d58SStefano Zampini   PetscBool      isdense;
3707a3c3d58SStefano Zampini 
3717a3c3d58SStefano Zampini   PetscFunctionBegin;
3727a3c3d58SStefano Zampini   switch (product->type) {
3737a3c3d58SStefano Zampini   case MATPRODUCT_AB:
3747a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,A->rmap->N,B->cmap->N);CHKERRQ(ierr);
3757a3c3d58SStefano Zampini     break;
3767a3c3d58SStefano Zampini   case MATPRODUCT_AtB:
3777a3c3d58SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,B->cmap->n,A->cmap->N,B->cmap->N);CHKERRQ(ierr);
3787a3c3d58SStefano Zampini     break;
3797a3c3d58SStefano 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);
3807a3c3d58SStefano Zampini   }
3817a3c3d58SStefano Zampini   ierr = PetscObjectBaseTypeCompareAny((PetscObject)C,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
3827a3c3d58SStefano Zampini   if (!isdense) {
3837a3c3d58SStefano Zampini     ierr = MatSetType(C,((PetscObject)B)->type_name);CHKERRQ(ierr);
3846718818eSStefano Zampini     /* If matrix type of C was not set or not dense, we need to reset the pointer */
3857a3c3d58SStefano Zampini     C->ops->productsymbolic = MatProductSymbolic_X_Dense;
3867a3c3d58SStefano Zampini   }
3876718818eSStefano Zampini   C->ops->productnumeric = MatProductNumeric_X_Dense;
3887a3c3d58SStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
3897a3c3d58SStefano Zampini   PetscFunctionReturn(0);
3907a3c3d58SStefano Zampini }
3917a3c3d58SStefano Zampini 
3926718818eSStefano Zampini /* a single driver to query the dispatching */
3936718818eSStefano Zampini static PetscErrorCode MatProductSetFromOptions_Private(Mat mat)
3944222ddf1SHong Zhang {
3954222ddf1SHong Zhang   PetscErrorCode    ierr;
3964222ddf1SHong Zhang   Mat_Product       *product = mat->product;
3976718818eSStefano Zampini   PetscInt          Am,An,Bm,Bn,Cm,Cn;
3984222ddf1SHong Zhang   Mat               A = product->A,B = product->B,C = product->C;
3996718818eSStefano Zampini   const char* const Bnames[] = { "B", "R", "P" };
4006718818eSStefano Zampini   const char*       bname;
4014222ddf1SHong Zhang   PetscErrorCode    (*fA)(Mat);
4024222ddf1SHong Zhang   PetscErrorCode    (*fB)(Mat);
4034222ddf1SHong Zhang   PetscErrorCode    (*fC)(Mat);
4044222ddf1SHong Zhang   PetscErrorCode    (*f)(Mat)=NULL;
4054222ddf1SHong Zhang 
4064222ddf1SHong Zhang   PetscFunctionBegin;
4076718818eSStefano Zampini   mat->ops->productsymbolic = NULL;
4086718818eSStefano Zampini   mat->ops->productnumeric = NULL;
4096718818eSStefano Zampini   if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(0);
410e01e2646SStefano Zampini   if (!A) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing A mat");
411e01e2646SStefano Zampini   if (!B) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing B mat");
412e01e2646SStefano Zampini   if (product->type == MATPRODUCT_ABC && !C) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing C mat");
4136718818eSStefano Zampini   if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */
4146718818eSStefano Zampini   if (product->type == MATPRODUCT_RARt) bname = Bnames[1];
4156718818eSStefano Zampini   else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2];
4166718818eSStefano Zampini   else bname = Bnames[0];
4176718818eSStefano Zampini 
4186718818eSStefano Zampini   /* Check matrices sizes */
4196718818eSStefano Zampini   Am = A->rmap->N;
4206718818eSStefano Zampini   An = A->cmap->N;
4216718818eSStefano Zampini   Bm = B->rmap->N;
4226718818eSStefano Zampini   Bn = B->cmap->N;
4236718818eSStefano Zampini   Cm = C ? C->rmap->N : 0;
4246718818eSStefano Zampini   Cn = C ? C->cmap->N : 0;
4256718818eSStefano Zampini   if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { PetscInt t = Bn; Bn = Bm; Bm = t; }
4266718818eSStefano Zampini   if (product->type == MATPRODUCT_AtB) { PetscInt t = An; An = Am; Am = t; }
4276718818eSStefano 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);
4286718818eSStefano 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);
4294222ddf1SHong Zhang 
4304222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4314222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
4326718818eSStefano Zampini   fC = C ? C->ops->productsetfromoptions : fA;
4336718818eSStefano Zampini   if (C) {
4346718818eSStefano 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);
4356718818eSStefano Zampini   } else {
4366718818eSStefano 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);
4376718818eSStefano Zampini   }
4384222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
4396896283bSStefano Zampini     ierr = PetscInfo(mat,"  matching op\n");CHKERRQ(ierr);
4406718818eSStefano Zampini     ierr = (*fA)(mat);CHKERRQ(ierr);
441*8d7b260cSStefano Zampini   }
442*8d7b260cSStefano Zampini   /* We may have found f but it did not succeed */
443*8d7b260cSStefano Zampini   if (!mat->ops->productsymbolic) { /* query MatProductSetFromOptions_Atype_Btype_Ctype */
4444222ddf1SHong Zhang     char  mtypes[256];
4454222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4464222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4474222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4484222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4496718818eSStefano Zampini     if (C) {
4504222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4514222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4526718818eSStefano Zampini     }
4534222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4544222ddf1SHong Zhang 
4554222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4566718818eSStefano Zampini     ierr = PetscInfo2(mat,"  querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr);
4574222ddf1SHong Zhang     if (!f) {
4584222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4596718818eSStefano Zampini       ierr = PetscInfo3(mat,"  querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr);
4604222ddf1SHong Zhang     }
4616718818eSStefano Zampini     if (!f && C) {
4624222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
4636718818eSStefano Zampini       ierr = PetscInfo2(mat,"  querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr);
4644222ddf1SHong Zhang     }
4656718818eSStefano Zampini     if (f) { ierr = (*f)(mat);CHKERRQ(ierr); }
4666718818eSStefano Zampini 
4676718818eSStefano Zampini     /* We may have found f but it did not succeed */
4686718818eSStefano Zampini     /* some matrices (i.e. MATTRANSPOSE, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */
4696718818eSStefano Zampini     if (!mat->ops->productsymbolic) {
4706718818eSStefano Zampini       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_anytype_C",sizeof(mtypes));CHKERRQ(ierr);
4716718818eSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4726718818eSStefano Zampini       ierr = PetscInfo2(mat,"  querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr);
4736718818eSStefano Zampini       if (!f) {
4746718818eSStefano Zampini         ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4756718818eSStefano Zampini         ierr = PetscInfo3(mat,"  querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr);
4766718818eSStefano Zampini       }
4776718818eSStefano Zampini       if (!f && C) {
4786718818eSStefano Zampini         ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
4796718818eSStefano Zampini         ierr = PetscInfo2(mat,"  querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr);
4806718818eSStefano Zampini       }
4816718818eSStefano Zampini     }
4826718818eSStefano Zampini     if (f) { ierr = (*f)(mat);CHKERRQ(ierr); }
4834222ddf1SHong Zhang   }
4844222ddf1SHong Zhang 
4856718818eSStefano Zampini   /* We may have found f but it did not succeed */
4866718818eSStefano Zampini   if (!mat->ops->productsymbolic) {
4876718818eSStefano Zampini     /* we can still compute the product if B is of type dense */
4886718818eSStefano Zampini     if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) {
4896718818eSStefano Zampini       PetscBool isdense;
4906718818eSStefano Zampini 
4916718818eSStefano Zampini       ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr);
4926718818eSStefano Zampini       if (isdense) {
4936718818eSStefano Zampini 
4946718818eSStefano Zampini         mat->ops->productsymbolic = MatProductSymbolic_X_Dense;
4956718818eSStefano Zampini         ierr = PetscInfo(mat,"  using basic looping over columns of a dense matrix\n");CHKERRQ(ierr);
4966718818eSStefano Zampini       }
4975415d71bSStefano Zampini     } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Unsafe() for triple products only */
4986718818eSStefano Zampini       /*
4996718818eSStefano Zampini          TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if
500*8d7b260cSStefano Zampini                the combination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result
5016718818eSStefano Zampini                before computing the symbolic phase
5026718818eSStefano Zampini       */
5035415d71bSStefano Zampini       ierr = PetscInfo(mat,"  symbolic product not supported, using MatProductSymbolic_Unsafe() implementation\n");CHKERRQ(ierr);
5045415d71bSStefano Zampini       mat->ops->productsymbolic = MatProductSymbolic_Unsafe;
5054222ddf1SHong Zhang     }
5066718818eSStefano Zampini   }
5076718818eSStefano Zampini   if (!mat->ops->productsymbolic) {
5086718818eSStefano Zampini     ierr = PetscInfo(mat,"  symbolic product is not supported\n");CHKERRQ(ierr);
5096718818eSStefano Zampini   }
5104222ddf1SHong Zhang   PetscFunctionReturn(0);
5114222ddf1SHong Zhang }
5124222ddf1SHong Zhang 
5134222ddf1SHong Zhang /*@C
5144222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
5154222ddf1SHong Zhang 
5164222ddf1SHong Zhang    Logically Collective on Mat
5174222ddf1SHong Zhang 
5184222ddf1SHong Zhang    Input Parameter:
5194222ddf1SHong Zhang .  mat - the matrix
5204222ddf1SHong Zhang 
5216718818eSStefano Zampini    Options Database Keys:
5226718818eSStefano Zampini .    -mat_product_clear - Clear intermediate data structures after MatProductNumeric() has been called
5234222ddf1SHong Zhang 
5246718818eSStefano Zampini    Level: intermediate
5256718818eSStefano Zampini 
5266718818eSStefano Zampini .seealso: MatSetFromOptions(), MatProductCreate(), MatProductCreateWithMat()
5274222ddf1SHong Zhang @*/
5284222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
5294222ddf1SHong Zhang {
5304222ddf1SHong Zhang   PetscErrorCode ierr;
5314222ddf1SHong Zhang 
5324222ddf1SHong Zhang   PetscFunctionBegin;
5334222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5346718818eSStefano Zampini   MatCheckProduct(mat,1);
5356718818eSStefano Zampini   if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot call MatProductSetFromOptions with already present data");
5366718818eSStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)mat);CHKERRQ(ierr);
5376718818eSStefano 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);
5386718818eSStefano Zampini   ierr = PetscOptionsDeprecated("-mat_freeintermediatedatastructures","-mat_product_clear","3.13","Or call MatProductClear() after MatProductNumeric()");CHKERRQ(ierr);
5396718818eSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
5406718818eSStefano Zampini   ierr = MatProductSetFromOptions_Private(mat);CHKERRQ(ierr);
5416718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after setup phase");
5426718818eSStefano Zampini   PetscFunctionReturn(0);
5436718818eSStefano Zampini }
5446718818eSStefano Zampini 
5456718818eSStefano Zampini /*@C
5466718818eSStefano Zampini    MatProductView - View a MatProduct
5476718818eSStefano Zampini 
5486718818eSStefano Zampini    Logically Collective on Mat
5496718818eSStefano Zampini 
5506718818eSStefano Zampini    Input Parameter:
5516718818eSStefano Zampini .  mat - the matrix obtained with MatProductCreate() or MatProductCreateWithMat()
5526718818eSStefano Zampini 
5536718818eSStefano Zampini    Level: intermediate
5546718818eSStefano Zampini 
5556718818eSStefano Zampini .seealso: MatView(), MatProductCreate(), MatProductCreateWithMat()
5566718818eSStefano Zampini @*/
5576718818eSStefano Zampini PetscErrorCode MatProductView(Mat mat, PetscViewer viewer)
5586718818eSStefano Zampini {
5596718818eSStefano Zampini   PetscErrorCode ierr;
5606718818eSStefano Zampini 
5616718818eSStefano Zampini   PetscFunctionBegin;
5626718818eSStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5636718818eSStefano Zampini   if (!mat->product) PetscFunctionReturn(0);
5646718818eSStefano Zampini   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer);CHKERRQ(ierr);}
5656718818eSStefano Zampini   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
5666718818eSStefano Zampini   PetscCheckSameComm(mat,1,viewer,2);
5676718818eSStefano Zampini   if (mat->product->view) {
5686718818eSStefano Zampini     ierr = (*mat->product->view)(mat,viewer);CHKERRQ(ierr);
5696718818eSStefano Zampini   }
5704222ddf1SHong Zhang   PetscFunctionReturn(0);
5714222ddf1SHong Zhang }
5724222ddf1SHong Zhang 
5734222ddf1SHong Zhang /* ----------------------------------------------- */
5746718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
5756718818eSStefano Zampini  * they are dangerous and should be removed in the future */
5764222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
5774222ddf1SHong Zhang {
5784222ddf1SHong Zhang   PetscErrorCode ierr;
5794222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5804222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5814222ddf1SHong Zhang 
5824222ddf1SHong Zhang   PetscFunctionBegin;
5837a3c3d58SStefano 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);
5847a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
5854222ddf1SHong Zhang   PetscFunctionReturn(0);
5864222ddf1SHong Zhang }
5874222ddf1SHong Zhang 
5884222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(Mat mat)
5894222ddf1SHong Zhang {
5904222ddf1SHong Zhang   PetscErrorCode ierr;
5914222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5924222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5934222ddf1SHong Zhang 
5944222ddf1SHong Zhang   PetscFunctionBegin;
5957a3c3d58SStefano 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);
5967a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
5974222ddf1SHong Zhang   PetscFunctionReturn(0);
5984222ddf1SHong Zhang }
5994222ddf1SHong Zhang 
6004222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
6014222ddf1SHong Zhang {
6024222ddf1SHong Zhang   PetscErrorCode ierr;
6034222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6044222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6054222ddf1SHong Zhang 
6064222ddf1SHong Zhang   PetscFunctionBegin;
6077a3c3d58SStefano 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);
6087a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
6094222ddf1SHong Zhang   PetscFunctionReturn(0);
6104222ddf1SHong Zhang }
6114222ddf1SHong Zhang 
6124222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
6134222ddf1SHong Zhang {
6144222ddf1SHong Zhang   PetscErrorCode ierr;
6154222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6164222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6174222ddf1SHong Zhang 
6184222ddf1SHong Zhang   PetscFunctionBegin;
6197a3c3d58SStefano 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);
6207a3c3d58SStefano Zampini   ierr = (*mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
6214222ddf1SHong Zhang   PetscFunctionReturn(0);
6224222ddf1SHong Zhang }
6234222ddf1SHong Zhang 
6244222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
6254222ddf1SHong Zhang {
6264222ddf1SHong Zhang   PetscErrorCode ierr;
6274222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6284222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6294222ddf1SHong Zhang 
6304222ddf1SHong Zhang   PetscFunctionBegin;
6317a3c3d58SStefano 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);
6327a3c3d58SStefano Zampini   ierr = (*mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
6334222ddf1SHong Zhang   PetscFunctionReturn(0);
6344222ddf1SHong Zhang }
6354222ddf1SHong Zhang 
6364222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
6374222ddf1SHong Zhang {
6384222ddf1SHong Zhang   PetscErrorCode ierr;
6394222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6404222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
6414222ddf1SHong Zhang 
6424222ddf1SHong Zhang   PetscFunctionBegin;
6437a3c3d58SStefano 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);
6447a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
6454222ddf1SHong Zhang   PetscFunctionReturn(0);
6464222ddf1SHong Zhang }
6474222ddf1SHong Zhang 
6486718818eSStefano Zampini /* ----------------------------------------------- */
6496718818eSStefano Zampini 
6504222ddf1SHong Zhang /*@
6514222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
6524222ddf1SHong Zhang 
6534222ddf1SHong Zhang    Collective on Mat
6544222ddf1SHong Zhang 
6556718818eSStefano Zampini    Input/Output Parameter:
6566718818eSStefano Zampini .  mat - the matrix holding the product
6574222ddf1SHong Zhang 
6584222ddf1SHong Zhang    Level: intermediate
6594222ddf1SHong Zhang 
6606718818eSStefano Zampini    Notes: MatProductSymbolic() must have been called on mat before calling this function
6616718818eSStefano Zampini 
6626718818eSStefano Zampini .seealso: MatProductCreate(), MatSetType(), MatProductSymbolic()
6634222ddf1SHong Zhang @*/
6644222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
6654222ddf1SHong Zhang {
6664222ddf1SHong Zhang   PetscErrorCode ierr;
667e017e560SStefano Zampini   PetscLogEvent  eventtype=-1;
6684222ddf1SHong Zhang 
6694222ddf1SHong Zhang   PetscFunctionBegin;
6704222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6716718818eSStefano Zampini   MatCheckProduct(mat,1);
672e017e560SStefano Zampini   /* log event */
673e017e560SStefano Zampini   switch (mat->product->type) {
674e017e560SStefano Zampini   case MATPRODUCT_AB:
675e017e560SStefano Zampini     eventtype = MAT_MatMultNumeric;
676e017e560SStefano Zampini     break;
677e017e560SStefano Zampini   case MATPRODUCT_AtB:
678e017e560SStefano Zampini     eventtype = MAT_TransposeMatMultNumeric;
679e017e560SStefano Zampini     break;
680e017e560SStefano Zampini   case MATPRODUCT_ABt:
681e017e560SStefano Zampini     eventtype = MAT_MatTransposeMultNumeric;
682e017e560SStefano Zampini     break;
683e017e560SStefano Zampini   case MATPRODUCT_PtAP:
684e017e560SStefano Zampini     eventtype = MAT_PtAPNumeric;
685e017e560SStefano Zampini     break;
686e017e560SStefano Zampini   case MATPRODUCT_RARt:
687e017e560SStefano Zampini     eventtype = MAT_RARtNumeric;
688e017e560SStefano Zampini     break;
689e017e560SStefano Zampini   case MATPRODUCT_ABC:
690e017e560SStefano Zampini     eventtype = MAT_MatMatMultNumeric;
691e017e560SStefano Zampini     break;
692e017e560SStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[mat->product->type]);
693e017e560SStefano Zampini   }
694*8d7b260cSStefano Zampini 
6954222ddf1SHong Zhang   if (mat->ops->productnumeric) {
696e017e560SStefano Zampini     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
6974222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
698e017e560SStefano Zampini     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
6997a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSymbolic() first");
7006718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after numeric phase");
7016718818eSStefano Zampini   if (mat->product->clear) {
7026718818eSStefano Zampini     ierr = MatProductClear(mat);CHKERRQ(ierr);
7036718818eSStefano Zampini   }
7045415d71bSStefano Zampini   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
7054222ddf1SHong Zhang   PetscFunctionReturn(0);
7064222ddf1SHong Zhang }
7074222ddf1SHong Zhang 
7084222ddf1SHong Zhang /* ----------------------------------------------- */
7096718818eSStefano Zampini /* these are basic implementations relying on the old function pointers
7106718818eSStefano Zampini  * they are dangerous and should be removed in the future */
7114222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
7124222ddf1SHong Zhang {
7134222ddf1SHong Zhang   PetscErrorCode ierr;
7144222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7154222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7164222ddf1SHong Zhang 
7174222ddf1SHong Zhang   PetscFunctionBegin;
7187a3c3d58SStefano Zampini   if (!mat->ops->matmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7197a3c3d58SStefano Zampini   ierr = (*mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7204222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
7214222ddf1SHong Zhang   PetscFunctionReturn(0);
7224222ddf1SHong Zhang }
7234222ddf1SHong Zhang 
7244222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
7254222ddf1SHong Zhang {
7264222ddf1SHong Zhang   PetscErrorCode ierr;
7274222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7284222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7294222ddf1SHong Zhang 
7304222ddf1SHong Zhang   PetscFunctionBegin;
7317a3c3d58SStefano Zampini   if (!mat->ops->transposematmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7327a3c3d58SStefano Zampini   ierr = (*mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7334222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
7344222ddf1SHong Zhang   PetscFunctionReturn(0);
7354222ddf1SHong Zhang }
7364222ddf1SHong Zhang 
7374222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
7384222ddf1SHong Zhang {
7394222ddf1SHong Zhang   PetscErrorCode ierr;
7404222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7414222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7424222ddf1SHong Zhang 
7434222ddf1SHong Zhang   PetscFunctionBegin;
7447a3c3d58SStefano Zampini   if (!mat->ops->mattransposemultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7457a3c3d58SStefano Zampini   ierr = (*mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7464222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
7474222ddf1SHong Zhang   PetscFunctionReturn(0);
7484222ddf1SHong Zhang }
7494222ddf1SHong Zhang 
7504222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
7514222ddf1SHong Zhang {
7524222ddf1SHong Zhang   PetscErrorCode ierr;
7534222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7544222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
7554222ddf1SHong Zhang 
7564222ddf1SHong Zhang   PetscFunctionBegin;
7577a3c3d58SStefano Zampini   if (!mat->ops->matmatmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]);
7587a3c3d58SStefano Zampini   ierr = (*mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
7594222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
7604222ddf1SHong Zhang   PetscFunctionReturn(0);
7614222ddf1SHong Zhang }
7624222ddf1SHong Zhang 
7636718818eSStefano Zampini /* ----------------------------------------------- */
7646718818eSStefano Zampini 
7654222ddf1SHong Zhang /*@
7664222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
7674222ddf1SHong Zhang 
7684222ddf1SHong Zhang    Collective on Mat
7694222ddf1SHong Zhang 
7706718818eSStefano Zampini    Input/Output Parameter:
7714222ddf1SHong Zhang .  mat - the matrix to hold a product
7724222ddf1SHong Zhang 
7734222ddf1SHong Zhang    Level: intermediate
7744222ddf1SHong Zhang 
7756718818eSStefano Zampini    Notes: MatProductSetFromOptions() must have been called on mat before calling this function
7766718818eSStefano Zampini 
7776718818eSStefano Zampini .seealso: MatProductCreate(), MatProductCreateWithMat(), MatProductSetFromOptions(), MatProductNumeric(), MatProductSetType(), MatProductSetAlgorithm()
7784222ddf1SHong Zhang @*/
7794222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
7804222ddf1SHong Zhang {
7814222ddf1SHong Zhang   PetscErrorCode ierr;
7824222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
7834222ddf1SHong Zhang 
7844222ddf1SHong Zhang   PetscFunctionBegin;
7854222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7866718818eSStefano Zampini   MatCheckProduct(mat,1);
7876718818eSStefano Zampini   if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot run symbolic phase. Product data not empty");
7884222ddf1SHong Zhang   /* log event */
7896718818eSStefano Zampini   switch (mat->product->type) {
7904222ddf1SHong Zhang   case MATPRODUCT_AB:
7914222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
7924222ddf1SHong Zhang     break;
7934222ddf1SHong Zhang   case MATPRODUCT_AtB:
7944222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
7954222ddf1SHong Zhang     break;
7964222ddf1SHong Zhang   case MATPRODUCT_ABt:
7974222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
7984222ddf1SHong Zhang     break;
7994222ddf1SHong Zhang   case MATPRODUCT_PtAP:
8004222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
8014222ddf1SHong Zhang     break;
8024222ddf1SHong Zhang   case MATPRODUCT_RARt:
8034222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
8044222ddf1SHong Zhang     break;
8054222ddf1SHong Zhang   case MATPRODUCT_ABC:
8064222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
8074222ddf1SHong Zhang     break;
8086718818eSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[mat->product->type]);
8094222ddf1SHong Zhang   }
8104222ddf1SHong Zhang 
8116718818eSStefano Zampini   mat->ops->productnumeric = NULL;
8124222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
8134222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
8144222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
8154222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
8167a3c3d58SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetFromOptions() first");
8176718818eSStefano Zampini   if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after symbolic phase");
8186718818eSStefano Zampini   if (!mat->ops->productnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Symbolic phase did not specify the numeric phase");
8194222ddf1SHong Zhang   PetscFunctionReturn(0);
8204222ddf1SHong Zhang }
8214222ddf1SHong Zhang 
8224222ddf1SHong Zhang /*@
8234222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
8244222ddf1SHong Zhang 
8254222ddf1SHong Zhang    Collective on Mat
8264222ddf1SHong Zhang 
8274222ddf1SHong Zhang    Input Parameters:
8284222ddf1SHong Zhang +  mat - the matrix product
829a5b23f4aSJose E. Roman -  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 irrelevant.
8304222ddf1SHong Zhang 
8314222ddf1SHong Zhang    Level: intermediate
8324222ddf1SHong Zhang 
8334222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
8344222ddf1SHong Zhang @*/
8354222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
8364222ddf1SHong Zhang {
8374222ddf1SHong Zhang   PetscFunctionBegin;
8384222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8396718818eSStefano Zampini   MatCheckProduct(mat,1);
8406718818eSStefano Zampini   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0;
8416718818eSStefano Zampini   else mat->product->fill = fill;
8424222ddf1SHong Zhang   PetscFunctionReturn(0);
8434222ddf1SHong Zhang }
8444222ddf1SHong Zhang 
8454222ddf1SHong Zhang /*@
8464222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
8474222ddf1SHong Zhang 
8484222ddf1SHong Zhang    Collective on Mat
8494222ddf1SHong Zhang 
8504222ddf1SHong Zhang    Input Parameters:
8514222ddf1SHong Zhang +  mat - the matrix product
8524222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
8534222ddf1SHong Zhang 
8544222ddf1SHong Zhang    Level: intermediate
8554222ddf1SHong Zhang 
8566718818eSStefano Zampini .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate(), MatProductAlgorithm
8574222ddf1SHong Zhang @*/
8584222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
8594222ddf1SHong Zhang {
8607a3c3d58SStefano Zampini   PetscErrorCode ierr;
8614222ddf1SHong Zhang 
8624222ddf1SHong Zhang   PetscFunctionBegin;
8634222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8646718818eSStefano Zampini   MatCheckProduct(mat,1);
8656718818eSStefano Zampini   ierr = PetscFree(mat->product->alg);CHKERRQ(ierr);
8666718818eSStefano Zampini   ierr = PetscStrallocpy(alg,&mat->product->alg);CHKERRQ(ierr);
8674222ddf1SHong Zhang   PetscFunctionReturn(0);
8684222ddf1SHong Zhang }
8694222ddf1SHong Zhang 
8704222ddf1SHong Zhang /*@
8716718818eSStefano Zampini    MatProductSetType - Sets a particular matrix product type
8724222ddf1SHong Zhang 
8734222ddf1SHong Zhang    Collective on Mat
8744222ddf1SHong Zhang 
8754222ddf1SHong Zhang    Input Parameters:
8764222ddf1SHong Zhang +  mat - the matrix
8774222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
8784222ddf1SHong Zhang 
8794222ddf1SHong Zhang    Level: intermediate
8804222ddf1SHong Zhang 
8816718818eSStefano Zampini .seealso: MatProductCreate(), MatProductType
8824222ddf1SHong Zhang @*/
8834222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
8844222ddf1SHong Zhang {
8856718818eSStefano Zampini   PetscErrorCode ierr;
8864222ddf1SHong Zhang 
8874222ddf1SHong Zhang   PetscFunctionBegin;
8884222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8896718818eSStefano Zampini   MatCheckProduct(mat,1);
8907a3c3d58SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,productype,2);
8916718818eSStefano Zampini   if (productype != mat->product->type) {
8926718818eSStefano Zampini     if (mat->product->destroy) {
8936718818eSStefano Zampini       ierr = (*mat->product->destroy)(mat->product->data);CHKERRQ(ierr);
8944222ddf1SHong Zhang     }
8956718818eSStefano Zampini     mat->product->destroy = NULL;
8966718818eSStefano Zampini     mat->product->data = NULL;
8976718818eSStefano Zampini     mat->ops->productsymbolic = NULL;
8986718818eSStefano Zampini     mat->ops->productnumeric  = NULL;
8996718818eSStefano Zampini   }
9006718818eSStefano Zampini   mat->product->type = productype;
9014222ddf1SHong Zhang   PetscFunctionReturn(0);
9024222ddf1SHong Zhang }
9034222ddf1SHong Zhang 
9044417c5e8SHong Zhang /*@
9054417c5e8SHong Zhang    MatProductClear - Clears matrix product internal structure.
9064417c5e8SHong Zhang 
9074417c5e8SHong Zhang    Collective on Mat
9084417c5e8SHong Zhang 
9094417c5e8SHong Zhang    Input Parameters:
9104417c5e8SHong Zhang .  mat - the product matrix
9114417c5e8SHong Zhang 
9124417c5e8SHong Zhang    Level: intermediate
9136718818eSStefano Zampini 
9146718818eSStefano Zampini    Notes: this function should be called to remove any intermediate data used by the product
9156718818eSStefano Zampini           After having called this function, MatProduct operations can no longer be used on mat
9164417c5e8SHong Zhang @*/
9174417c5e8SHong Zhang PetscErrorCode MatProductClear(Mat mat)
9184417c5e8SHong Zhang {
9194417c5e8SHong Zhang   PetscErrorCode ierr;
9204417c5e8SHong Zhang   Mat_Product    *product = mat->product;
9214417c5e8SHong Zhang 
9224417c5e8SHong Zhang   PetscFunctionBegin;
9237a3c3d58SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9244417c5e8SHong Zhang   if (product) {
9254417c5e8SHong Zhang     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
9264417c5e8SHong Zhang     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
9274417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
9287a3c3d58SStefano Zampini     ierr = PetscFree(product->alg);CHKERRQ(ierr);
9294417c5e8SHong Zhang     ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr);
9306718818eSStefano Zampini     if (product->destroy) {
9316718818eSStefano Zampini       ierr = (*product->destroy)(product->data);CHKERRQ(ierr);
9324417c5e8SHong Zhang     }
9336718818eSStefano Zampini   }
9346718818eSStefano Zampini   ierr = PetscFree(mat->product);CHKERRQ(ierr);
9356718818eSStefano Zampini   mat->ops->productsymbolic = NULL;
9366718818eSStefano Zampini   mat->ops->productnumeric = NULL;
9374417c5e8SHong Zhang   PetscFunctionReturn(0);
9384417c5e8SHong Zhang }
9394417c5e8SHong Zhang 
9404222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
9414417c5e8SHong Zhang PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
9424222ddf1SHong Zhang {
9434222ddf1SHong Zhang   PetscErrorCode ierr;
9444222ddf1SHong Zhang   Mat_Product    *product=NULL;
9454222ddf1SHong Zhang 
9464222ddf1SHong Zhang   PetscFunctionBegin;
9476718818eSStefano Zampini   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
9486718818eSStefano Zampini   if (D->product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"Product already present");
9494222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
9504222ddf1SHong Zhang   product->A        = A;
9514222ddf1SHong Zhang   product->B        = B;
9524222ddf1SHong Zhang   product->C        = C;
9536718818eSStefano Zampini   product->type     = MATPRODUCT_UNSPECIFIED;
9544222ddf1SHong Zhang   product->Dwork    = NULL;
9554222ddf1SHong Zhang   product->api_user = PETSC_FALSE;
9566718818eSStefano Zampini   product->clear    = PETSC_FALSE;
9574222ddf1SHong Zhang   D->product        = product;
9584417c5e8SHong Zhang 
9597a3c3d58SStefano Zampini   ierr = MatProductSetAlgorithm(D,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
9606718818eSStefano Zampini   ierr = MatProductSetFill(D,PETSC_DEFAULT);CHKERRQ(ierr);
9617a3c3d58SStefano Zampini 
9624417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
9634417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
9644417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
9654222ddf1SHong Zhang   PetscFunctionReturn(0);
9664222ddf1SHong Zhang }
9674222ddf1SHong Zhang 
9684222ddf1SHong Zhang /*@
9694222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
9704222ddf1SHong Zhang 
9714222ddf1SHong Zhang    Collective on Mat
9724222ddf1SHong Zhang 
9734222ddf1SHong Zhang    Input Parameters:
9744222ddf1SHong Zhang +  A - the first matrix
9754222ddf1SHong Zhang .  B - the second matrix
9764222ddf1SHong Zhang .  C - the third matrix (optional)
9774222ddf1SHong Zhang -  D - the matrix which will be used as a product
9784222ddf1SHong Zhang 
9794222ddf1SHong Zhang    Output Parameters:
9804222ddf1SHong Zhang .  D - the product matrix
9814222ddf1SHong Zhang 
9826718818eSStefano Zampini    Notes:
9836718818eSStefano Zampini      Any product data attached to D will be cleared
9846718818eSStefano Zampini 
9854222ddf1SHong Zhang    Level: intermediate
9864222ddf1SHong Zhang 
9876718818eSStefano Zampini .seealso: MatProductCreate(), MatProductClear()
9884222ddf1SHong Zhang @*/
9894222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
9904222ddf1SHong Zhang {
9914222ddf1SHong Zhang   PetscErrorCode ierr;
9924222ddf1SHong Zhang 
9934222ddf1SHong Zhang   PetscFunctionBegin;
9944222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
9954222ddf1SHong Zhang   PetscValidType(A,1);
9964222ddf1SHong Zhang   MatCheckPreallocated(A,1);
9974222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
9984222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
9994222ddf1SHong Zhang 
10004222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10014222ddf1SHong Zhang   PetscValidType(B,2);
10024222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10034222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10044222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10054222ddf1SHong Zhang 
10064222ddf1SHong Zhang   if (C) {
10074222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10084222ddf1SHong Zhang     PetscValidType(C,3);
10094222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10104222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10114222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10124222ddf1SHong Zhang   }
10134222ddf1SHong Zhang 
10144222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
10154222ddf1SHong Zhang   PetscValidType(D,4);
10164222ddf1SHong Zhang   MatCheckPreallocated(D,4);
10174222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10184222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10194222ddf1SHong Zhang 
10204222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
10216718818eSStefano Zampini   ierr = MatProductClear(D);CHKERRQ(ierr);
10224222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
10234222ddf1SHong Zhang   PetscFunctionReturn(0);
10244222ddf1SHong Zhang }
10254222ddf1SHong Zhang 
10264222ddf1SHong Zhang /*@
10274222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
10284222ddf1SHong Zhang 
10294222ddf1SHong Zhang    Collective on Mat
10304222ddf1SHong Zhang 
10314222ddf1SHong Zhang    Input Parameters:
10324222ddf1SHong Zhang +  A - the first matrix
10334222ddf1SHong Zhang .  B - the second matrix
10344222ddf1SHong Zhang -  C - the third matrix (optional)
10354222ddf1SHong Zhang 
10364222ddf1SHong Zhang    Output Parameters:
10374222ddf1SHong Zhang .  D - the product matrix
10384222ddf1SHong Zhang 
10394222ddf1SHong Zhang    Level: intermediate
10404222ddf1SHong Zhang 
10414222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
10424222ddf1SHong Zhang @*/
10434222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
10444222ddf1SHong Zhang {
10454222ddf1SHong Zhang   PetscErrorCode ierr;
10464222ddf1SHong Zhang 
10474222ddf1SHong Zhang   PetscFunctionBegin;
10484222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10494222ddf1SHong Zhang   PetscValidType(A,1);
10504222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10514222ddf1SHong Zhang   PetscValidType(B,2);
1052e01e2646SStefano Zampini   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix A");
1053e01e2646SStefano Zampini   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix B");
10544222ddf1SHong Zhang 
10554222ddf1SHong Zhang   if (C) {
10564222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10574222ddf1SHong Zhang     PetscValidType(C,3);
1058e01e2646SStefano Zampini     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix C");
10594222ddf1SHong Zhang   }
10604222ddf1SHong Zhang 
10614222ddf1SHong Zhang   PetscValidPointer(D,4);
10624222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
10634222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
10644222ddf1SHong Zhang   PetscFunctionReturn(0);
10654222ddf1SHong Zhang }
10665415d71bSStefano Zampini 
10675415d71bSStefano Zampini /*
10685415d71bSStefano Zampini    These are safe basic implementations of ABC, RARt and PtAP
10695415d71bSStefano Zampini    that do not rely on mat->ops->matmatop function pointers.
10705415d71bSStefano Zampini    They only use the MatProduct API and are currently used by
10715415d71bSStefano Zampini    cuSPARSE and KOKKOS-KERNELS backends
10725415d71bSStefano Zampini */
1073ec446438SStefano Zampini typedef struct {
10745415d71bSStefano Zampini   Mat BC;
10755415d71bSStefano Zampini   Mat ABC;
10765415d71bSStefano Zampini } MatMatMatPrivate;
10775415d71bSStefano Zampini 
10785415d71bSStefano Zampini static PetscErrorCode MatDestroy_MatMatMatPrivate(void *data)
10795415d71bSStefano Zampini {
10805415d71bSStefano Zampini   PetscErrorCode   ierr;
10815415d71bSStefano Zampini   MatMatMatPrivate *mmdata = (MatMatMatPrivate *)data;
10825415d71bSStefano Zampini 
10835415d71bSStefano Zampini   PetscFunctionBegin;
10845415d71bSStefano Zampini   ierr = MatDestroy(&mmdata->BC);CHKERRQ(ierr);
10855415d71bSStefano Zampini   ierr = MatDestroy(&mmdata->ABC);CHKERRQ(ierr);
10865415d71bSStefano Zampini   ierr = PetscFree(data);CHKERRQ(ierr);
10875415d71bSStefano Zampini   PetscFunctionReturn(0);
10885415d71bSStefano Zampini }
10895415d71bSStefano Zampini 
10905415d71bSStefano Zampini static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat)
10915415d71bSStefano Zampini {
10925415d71bSStefano Zampini   PetscErrorCode   ierr;
10935415d71bSStefano Zampini   Mat_Product      *product = mat->product;
10945415d71bSStefano Zampini   MatMatMatPrivate *mmabc;
10955415d71bSStefano Zampini 
10965415d71bSStefano Zampini   PetscFunctionBegin;
10975415d71bSStefano Zampini   MatCheckProduct(mat,1);
10985415d71bSStefano Zampini   if (!mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Product data empty");
10995415d71bSStefano Zampini   mmabc = (MatMatMatPrivate *)mat->product->data;
11005415d71bSStefano Zampini   if (!mmabc->BC->ops->productnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage");
1101ec446438SStefano Zampini   /* use function pointer directly to prevent logging */
11025415d71bSStefano Zampini   ierr = (*mmabc->BC->ops->productnumeric)(mmabc->BC);CHKERRQ(ierr);
11035415d71bSStefano Zampini   /* swap ABC product stuff with that of ABC for the numeric phase on mat */
11045415d71bSStefano Zampini   mat->product = mmabc->ABC->product;
11055415d71bSStefano Zampini   mat->ops->productnumeric = mmabc->ABC->ops->productnumeric;
11065415d71bSStefano Zampini   if (!mat->ops->productnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage");
1107ec446438SStefano Zampini   /* use function pointer directly to prevent logging */
11085415d71bSStefano Zampini   ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
11095415d71bSStefano Zampini   mat->ops->productnumeric = MatProductNumeric_ABC_Basic;
11105415d71bSStefano Zampini   mat->product = product;
11115415d71bSStefano Zampini   PetscFunctionReturn(0);
11125415d71bSStefano Zampini }
11135415d71bSStefano Zampini 
11145415d71bSStefano Zampini PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat)
11155415d71bSStefano Zampini {
11165415d71bSStefano Zampini   PetscErrorCode   ierr;
11175415d71bSStefano Zampini   Mat_Product      *product = mat->product;
11185415d71bSStefano Zampini   Mat              A, B ,C;
11195415d71bSStefano Zampini   MatProductType   p1,p2;
11205415d71bSStefano Zampini   MatMatMatPrivate *mmabc;
112165e4b4d4SStefano Zampini   const char       *prefix;
11225415d71bSStefano Zampini 
11235415d71bSStefano Zampini   PetscFunctionBegin;
11245415d71bSStefano Zampini   MatCheckProduct(mat,1);
11255415d71bSStefano Zampini   if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Product data not empty");
112665e4b4d4SStefano Zampini   ierr = MatGetOptionsPrefix(mat,&prefix);CHKERRQ(ierr);
11275415d71bSStefano Zampini   ierr = PetscNew(&mmabc);CHKERRQ(ierr);
11285415d71bSStefano Zampini   product->data    = mmabc;
11295415d71bSStefano Zampini   product->destroy = MatDestroy_MatMatMatPrivate;
11305415d71bSStefano Zampini   switch (product->type) {
11315415d71bSStefano Zampini   case MATPRODUCT_PtAP:
11325415d71bSStefano Zampini     p1 = MATPRODUCT_AB;
11335415d71bSStefano Zampini     p2 = MATPRODUCT_AtB;
11345415d71bSStefano Zampini     A = product->B;
11355415d71bSStefano Zampini     B = product->A;
11365415d71bSStefano Zampini     C = product->B;
11375415d71bSStefano Zampini     break;
11385415d71bSStefano Zampini   case MATPRODUCT_RARt:
11395415d71bSStefano Zampini     p1 = MATPRODUCT_ABt;
11405415d71bSStefano Zampini     p2 = MATPRODUCT_AB;
11415415d71bSStefano Zampini     A = product->B;
11425415d71bSStefano Zampini     B = product->A;
11435415d71bSStefano Zampini     C = product->B;
11445415d71bSStefano Zampini     break;
11455415d71bSStefano Zampini   case MATPRODUCT_ABC:
11465415d71bSStefano Zampini     p1 = MATPRODUCT_AB;
11475415d71bSStefano Zampini     p2 = MATPRODUCT_AB;
11485415d71bSStefano Zampini     A = product->A;
11495415d71bSStefano Zampini     B = product->B;
11505415d71bSStefano Zampini     C = product->C;
11515415d71bSStefano Zampini     break;
11525415d71bSStefano Zampini   default:
11535415d71bSStefano Zampini     SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Not for ProductType %s",MatProductTypes[product->type]);
11545415d71bSStefano Zampini   }
11555415d71bSStefano Zampini   ierr = MatProductCreate(B,C,NULL,&mmabc->BC);CHKERRQ(ierr);
115665e4b4d4SStefano Zampini   ierr = MatSetOptionsPrefix(mmabc->BC,prefix);CHKERRQ(ierr);
115765e4b4d4SStefano Zampini   ierr = MatAppendOptionsPrefix(mmabc->BC,"P1_");CHKERRQ(ierr);
11585415d71bSStefano Zampini   ierr = MatProductSetType(mmabc->BC,p1);CHKERRQ(ierr);
11595415d71bSStefano Zampini   ierr = MatProductSetAlgorithm(mmabc->BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
11605415d71bSStefano Zampini   ierr = MatProductSetFill(mmabc->BC,product->fill);CHKERRQ(ierr);
11615415d71bSStefano Zampini   mmabc->BC->product->api_user = product->api_user;
11625415d71bSStefano Zampini   ierr = MatProductSetFromOptions(mmabc->BC);CHKERRQ(ierr);
11635415d71bSStefano Zampini   if (!mmabc->BC->ops->productsymbolic) SETERRQ3(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Symbolic ProductType %s not supported with %s and %s",MatProductTypes[p1],((PetscObject)B)->type_name,((PetscObject)C)->type_name);
1164bfcc3627SStefano Zampini   /* use function pointer directly to prevent logging */
11655415d71bSStefano Zampini   ierr = (*mmabc->BC->ops->productsymbolic)(mmabc->BC);CHKERRQ(ierr);
11665415d71bSStefano Zampini 
11675415d71bSStefano Zampini   ierr = MatProductCreate(A,mmabc->BC,NULL,&mmabc->ABC);CHKERRQ(ierr);
116865e4b4d4SStefano Zampini   ierr = MatSetOptionsPrefix(mmabc->ABC,prefix);CHKERRQ(ierr);
116965e4b4d4SStefano Zampini   ierr = MatAppendOptionsPrefix(mmabc->ABC,"P2_");CHKERRQ(ierr);
11705415d71bSStefano Zampini   ierr = MatProductSetType(mmabc->ABC,p2);CHKERRQ(ierr);
11715415d71bSStefano Zampini   ierr = MatProductSetAlgorithm(mmabc->ABC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr);
11725415d71bSStefano Zampini   ierr = MatProductSetFill(mmabc->ABC,product->fill);CHKERRQ(ierr);
11735415d71bSStefano Zampini   mmabc->ABC->product->api_user = product->api_user;
11745415d71bSStefano Zampini   ierr = MatProductSetFromOptions(mmabc->ABC);CHKERRQ(ierr);
11755415d71bSStefano Zampini   if (!mmabc->ABC->ops->productsymbolic) SETERRQ3(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Symbolic ProductType %s not supported with %s and %s",MatProductTypes[p2],((PetscObject)A)->type_name,((PetscObject)mmabc->BC)->type_name);
11765415d71bSStefano Zampini   /* swap ABC product stuff with that of ABC for the symbolic phase on mat */
11775415d71bSStefano Zampini   mat->product = mmabc->ABC->product;
11785415d71bSStefano Zampini   mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic;
1179bfcc3627SStefano Zampini   /* use function pointer directly to prevent logging */
11805415d71bSStefano Zampini   ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
11815415d71bSStefano Zampini   mmabc->ABC->ops->productnumeric = mat->ops->productnumeric;
11825415d71bSStefano Zampini   mat->ops->productsymbolic       = MatProductSymbolic_ABC_Basic;
11835415d71bSStefano Zampini   mat->ops->productnumeric        = MatProductNumeric_ABC_Basic;
11845415d71bSStefano Zampini   mat->product                    = product;
11855415d71bSStefano Zampini   PetscFunctionReturn(0);
11865415d71bSStefano Zampini }
1187