xref: /petsc/src/mat/interface/matproduct.c (revision 4417c5e865a316438e66fe0a5f5b6f7342d46b87)
14222ddf1SHong Zhang 
24222ddf1SHong Zhang /*
34222ddf1SHong Zhang     Routines for matrix products. Calling procedure:
44222ddf1SHong Zhang 
54222ddf1SHong Zhang     MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D);
64222ddf1SHong Zhang     MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC);
74222ddf1SHong Zhang     MatProductSetAlgorithm(D, alg);
84222ddf1SHong Zhang     MatProductSetFill(D,fill);
94222ddf1SHong Zhang     MatProductSetFromOptions(D);
104222ddf1SHong Zhang       -> MatProductSetFromOptions_producttype(D):
114222ddf1SHong Zhang            # Check matrix global sizes
124222ddf1SHong Zhang            -> MatProductSetFromOptions_Atype_Btype_Ctype(D);
134222ddf1SHong Zhang                 ->MatProductSetFromOptions_Atype_Btype_Ctype_productype(D):
144222ddf1SHong Zhang                     # Check matrix local sizes for mpi matrices
154222ddf1SHong Zhang                     # Set default algorithm
164222ddf1SHong Zhang                     # Get runtime option
174222ddf1SHong Zhang                     # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype;
184222ddf1SHong Zhang 
194222ddf1SHong Zhang     PetscLogEventBegin()
204222ddf1SHong Zhang     MatProductSymbolic(D):
214222ddf1SHong Zhang       # Call MatxxxSymbolic_Atype_Btype_Ctype();
224222ddf1SHong Zhang       # Set D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype;
234222ddf1SHong Zhang     PetscLogEventEnd()
244222ddf1SHong Zhang 
254222ddf1SHong Zhang     PetscLogEventBegin()
264222ddf1SHong Zhang     MatProductNumeric(D);
274222ddf1SHong Zhang       # Call (D->ops->matxxxnumeric)();
284222ddf1SHong Zhang     PetscLogEventEnd()
294222ddf1SHong Zhang */
304222ddf1SHong Zhang 
314222ddf1SHong Zhang #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
324222ddf1SHong Zhang 
334222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C)
344222ddf1SHong Zhang {
354222ddf1SHong Zhang   PetscErrorCode ierr;
364222ddf1SHong Zhang   Mat_Product    *product = C->product;
374222ddf1SHong Zhang   Mat            P = product->B,AP = product->Dwork;
384222ddf1SHong Zhang 
394222ddf1SHong Zhang   PetscFunctionBegin;
404222ddf1SHong Zhang   /* AP = A*P */
414222ddf1SHong Zhang   ierr = MatProductNumeric(AP);CHKERRQ(ierr);
424222ddf1SHong Zhang   /* C = P^T*AP */
434222ddf1SHong Zhang   ierr = (C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr);
444222ddf1SHong Zhang   PetscFunctionReturn(0);
454222ddf1SHong Zhang }
464222ddf1SHong Zhang 
474222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C)
484222ddf1SHong Zhang {
494222ddf1SHong Zhang   PetscErrorCode ierr;
504222ddf1SHong Zhang   Mat_Product    *product = C->product;
514222ddf1SHong Zhang   Mat            A=product->A,P=product->B,AP;
524222ddf1SHong Zhang   PetscReal      fill=product->fill;
534222ddf1SHong Zhang 
544222ddf1SHong Zhang   PetscFunctionBegin;
554222ddf1SHong Zhang   /* AP = A*P */
564222ddf1SHong Zhang   ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr);
574222ddf1SHong Zhang   ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr);
584222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(AP,"default");CHKERRQ(ierr);
594222ddf1SHong Zhang   ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr);
604222ddf1SHong Zhang   ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr);
614222ddf1SHong Zhang   ierr = MatProductSymbolic(AP);CHKERRQ(ierr);
624222ddf1SHong Zhang 
634222ddf1SHong Zhang   /* C = P^T*AP */
644222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr);
654222ddf1SHong Zhang   product->alg = "default";
664222ddf1SHong Zhang   product->A   = P;
674222ddf1SHong Zhang   product->B   = AP;
684222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
694222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
704222ddf1SHong Zhang 
714222ddf1SHong Zhang   /* resume user's original input matrix setting for A and B */
724222ddf1SHong Zhang   product->A     = A;
734222ddf1SHong Zhang   product->B     = P;
744222ddf1SHong Zhang   product->Dwork = AP;
754222ddf1SHong Zhang 
764222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP_Basic;
774222ddf1SHong Zhang   PetscFunctionReturn(0);
784222ddf1SHong Zhang }
794222ddf1SHong Zhang 
804222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C)
814222ddf1SHong Zhang {
824222ddf1SHong Zhang   PetscErrorCode ierr;
834222ddf1SHong Zhang   Mat_Product    *product = C->product;
844222ddf1SHong Zhang   Mat            R=product->B,RA=product->Dwork;
854222ddf1SHong Zhang 
864222ddf1SHong Zhang   PetscFunctionBegin;
874222ddf1SHong Zhang   /* RA = R*A */
884222ddf1SHong Zhang   ierr = MatProductNumeric(RA);CHKERRQ(ierr);
894222ddf1SHong Zhang   /* C = RA*R^T */
904222ddf1SHong Zhang   ierr = (C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr);
914222ddf1SHong Zhang   PetscFunctionReturn(0);
924222ddf1SHong Zhang }
934222ddf1SHong Zhang 
944222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C)
954222ddf1SHong Zhang {
964222ddf1SHong Zhang   PetscErrorCode ierr;
974222ddf1SHong Zhang   Mat_Product    *product = C->product;
984222ddf1SHong Zhang   Mat            A=product->A,R=product->B,RA;
994222ddf1SHong Zhang   PetscReal      fill=product->fill;
1004222ddf1SHong Zhang 
1014222ddf1SHong Zhang   PetscFunctionBegin;
1024222ddf1SHong Zhang   /* RA = R*A */
1034222ddf1SHong Zhang   ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr);
1044222ddf1SHong Zhang   ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr);
1054222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(RA,"default");CHKERRQ(ierr);
1064222ddf1SHong Zhang   ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr);
1074222ddf1SHong Zhang   ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr);
1084222ddf1SHong Zhang   ierr = MatProductSymbolic(RA);CHKERRQ(ierr);
1094222ddf1SHong Zhang 
1104222ddf1SHong Zhang   /* C = RA*R^T */
1114222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr);
1124222ddf1SHong Zhang   product->alg  = "default";
1134222ddf1SHong Zhang   product->A    = RA;
1144222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
1154222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
1164222ddf1SHong Zhang 
1174222ddf1SHong Zhang   /* resume user's original input matrix setting for A */
1184222ddf1SHong Zhang   product->A     = A;
1194222ddf1SHong Zhang   product->Dwork = RA; /* save here so it will be destroyed with product C */
1204222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_RARt_Basic;
1214222ddf1SHong Zhang   PetscFunctionReturn(0);
1224222ddf1SHong Zhang }
1234222ddf1SHong Zhang 
1244222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat)
1254222ddf1SHong Zhang {
1264222ddf1SHong Zhang   PetscErrorCode ierr;
1274222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1284222ddf1SHong Zhang   Mat            A=product->A,BC=product->Dwork;
1294222ddf1SHong Zhang 
1304222ddf1SHong Zhang   PetscFunctionBegin;
1314222ddf1SHong Zhang   /* Numeric BC = B*C */
1324222ddf1SHong Zhang   ierr = MatProductNumeric(BC);CHKERRQ(ierr);
1334222ddf1SHong Zhang   /* Numeric mat = A*BC */
1344222ddf1SHong Zhang   ierr = (mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr);
1354222ddf1SHong Zhang   PetscFunctionReturn(0);
1364222ddf1SHong Zhang }
1374222ddf1SHong Zhang 
1384222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat)
1394222ddf1SHong Zhang {
1404222ddf1SHong Zhang   PetscErrorCode ierr;
1414222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1424222ddf1SHong Zhang   Mat            B=product->B,C=product->C,BC;
1434222ddf1SHong Zhang   PetscReal      fill=product->fill;
1444222ddf1SHong Zhang 
1454222ddf1SHong Zhang   PetscFunctionBegin;
1464222ddf1SHong Zhang   /* Symbolic BC = B*C */
1474222ddf1SHong Zhang   ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr);
1484222ddf1SHong Zhang   ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr);
1494222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(BC,"default");CHKERRQ(ierr);
1504222ddf1SHong Zhang   ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr);
1514222ddf1SHong Zhang   ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr);
1524222ddf1SHong Zhang   ierr = MatProductSymbolic(BC);CHKERRQ(ierr);
1534222ddf1SHong Zhang 
1544222ddf1SHong Zhang   /* Symbolic mat = A*BC */
1554222ddf1SHong Zhang   ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr);
1564222ddf1SHong Zhang   product->alg   = "default";
1574222ddf1SHong Zhang   product->B     = BC;
1584222ddf1SHong Zhang   product->Dwork = BC;
1594222ddf1SHong Zhang   ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr);
1604222ddf1SHong Zhang   ierr = MatProductSymbolic(mat);CHKERRQ(ierr);
1614222ddf1SHong Zhang 
1624222ddf1SHong Zhang   /* resume user's original input matrix setting for B */
1634222ddf1SHong Zhang   product->B = B;
1644222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC_Basic;
1654222ddf1SHong Zhang   PetscFunctionReturn(0);
1664222ddf1SHong Zhang }
1674222ddf1SHong Zhang 
1684222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_Basic(Mat mat)
1694222ddf1SHong Zhang {
1704222ddf1SHong Zhang   PetscErrorCode ierr;
1714222ddf1SHong Zhang   Mat_Product    *product = mat->product;
1724222ddf1SHong Zhang 
1734222ddf1SHong Zhang   PetscFunctionBegin;
1744222ddf1SHong Zhang   switch (product->type) {
1754222ddf1SHong Zhang   case MATPRODUCT_PtAP:
1764222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProduct_Basic_PtAP() for A %s, P %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);
1774222ddf1SHong Zhang     ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr);
1784222ddf1SHong Zhang     break;
1794222ddf1SHong Zhang   case MATPRODUCT_RARt:
1804222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProduct_Basic_RARt() for A %s, R %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);
1814222ddf1SHong Zhang     ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr);
1824222ddf1SHong Zhang     break;
1834222ddf1SHong Zhang   case MATPRODUCT_ABC:
1844222ddf1SHong Zhang     PetscInfo3((PetscObject)mat, "MatProduct_Basic_ABC() for A %s, B %s, C %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name,((PetscObject)product->C)->type_name);
1854222ddf1SHong Zhang     ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr);
1864222ddf1SHong Zhang     break;
1874222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported");
1884222ddf1SHong Zhang   }
1894222ddf1SHong Zhang   PetscFunctionReturn(0);
1904222ddf1SHong Zhang }
1914222ddf1SHong Zhang 
1924222ddf1SHong Zhang /* ----------------------------------------------- */
1934222ddf1SHong Zhang /*@C
1944222ddf1SHong Zhang    MatProductReplaceMats - Replace input matrices for a matrix product.
1954222ddf1SHong Zhang 
1964222ddf1SHong Zhang    Collective on Mat
1974222ddf1SHong Zhang 
1984222ddf1SHong Zhang    Input Parameters:
1994222ddf1SHong Zhang +  A - the matrix or NULL if not being replaced
2004222ddf1SHong Zhang .  B - the matrix or NULL if not being replaced
2014222ddf1SHong Zhang .  C - the matrix or NULL if not being replaced
2024222ddf1SHong Zhang -  D - the matrix product
2034222ddf1SHong Zhang 
2044222ddf1SHong Zhang    Level: intermediate
2054222ddf1SHong Zhang 
2064222ddf1SHong Zhang    Notes:
2074222ddf1SHong Zhang      Input matrix must have exactly same data structure as replaced one.
2084222ddf1SHong Zhang 
2094222ddf1SHong Zhang .seealso: MatProductCreate()
2104222ddf1SHong Zhang @*/
2114222ddf1SHong Zhang PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D)
2124222ddf1SHong Zhang {
213*4417c5e8SHong Zhang   PetscErrorCode ierr;
2144222ddf1SHong Zhang   Mat_Product    *product=D->product;
2154222ddf1SHong Zhang 
2164222ddf1SHong Zhang   PetscFunctionBegin;
2174222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_NULL,"Mat D does not have struct 'product'. Call MatProductReplaceProduct(). \n");
2184222ddf1SHong Zhang   if (A) {
2194222ddf1SHong Zhang     if (!product->Areplaced) {
220*4417c5e8SHong Zhang       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); /* take ownership of input */
221*4417c5e8SHong Zhang       ierr = MatDestroy(&product->A);CHKERRQ(ierr); /* release old reference */
2224222ddf1SHong Zhang       product->A = A;
2234222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix A was changed by a PETSc internal routine, cannot be replaced");
2244222ddf1SHong Zhang   }
2254222ddf1SHong Zhang   if (B) {
2264222ddf1SHong Zhang     if (!product->Breplaced) {
227*4417c5e8SHong Zhang       ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); /* take ownership of input */
228*4417c5e8SHong Zhang       ierr = MatDestroy(&product->B);CHKERRQ(ierr); /* release old reference */
2294222ddf1SHong Zhang       product->B = B;
2304222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix B was changed by a PETSc internal routine, cannot be replaced");
2314222ddf1SHong Zhang   }
232*4417c5e8SHong Zhang   if (C) {
233*4417c5e8SHong Zhang     ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); /* take ownership of input */
234*4417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr); /* release old reference */
235*4417c5e8SHong Zhang     product->C = C;
236*4417c5e8SHong Zhang   }
2374222ddf1SHong Zhang   PetscFunctionReturn(0);
2384222ddf1SHong Zhang }
2394222ddf1SHong Zhang 
2404222ddf1SHong Zhang /* ----------------------------------------------- */
2414222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AB(Mat mat)
2424222ddf1SHong Zhang {
2434222ddf1SHong Zhang   PetscErrorCode ierr;
2444222ddf1SHong Zhang   Mat_Product    *product = mat->product;
2454222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
2464222ddf1SHong Zhang   PetscBool      sametype;
2474222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
2484222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
2494222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
2504222ddf1SHong Zhang   PetscBool      A_istrans,B_istrans;
2514222ddf1SHong Zhang 
2524222ddf1SHong Zhang   PetscFunctionBegin;
2534222ddf1SHong Zhang   /* Check matrix global sizes */
2544222ddf1SHong Zhang   if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
2554222ddf1SHong Zhang 
2564222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
2574222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
2584222ddf1SHong Zhang 
2594222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
2604222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&A_istrans);CHKERRQ(ierr);
2614222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&B_istrans);CHKERRQ(ierr);
2624222ddf1SHong Zhang 
2634222ddf1SHong Zhang   if (fB == fA && sametype && (!A_istrans || !B_istrans)) {
2644222ddf1SHong Zhang     f = fB;
2654222ddf1SHong Zhang   } else {
2664222ddf1SHong Zhang     char      mtypes[256];
2674222ddf1SHong Zhang     PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE;
2684222ddf1SHong Zhang     Mat       At = NULL,Bt = NULL;
2694222ddf1SHong Zhang 
2704222ddf1SHong Zhang     if (A_istrans && !B_istrans) {
2714222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
2724222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
2734222ddf1SHong Zhang       if (At_istrans) { /* mat = ATT * B */
2744222ddf1SHong Zhang         Mat Att = NULL;
2754222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
276*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
277*4417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2784222ddf1SHong Zhang         A                  = Att;
2794222ddf1SHong Zhang         product->A         = Att; /* use Att for matproduct */
2804222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */
2814222ddf1SHong Zhang       } else { /* !At_istrans: mat = At^T*B */
282*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)At);CHKERRQ(ierr);
283*4417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2844222ddf1SHong Zhang         A                  = At;
2854222ddf1SHong Zhang         product->A         = At;
2864222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE;
2874222ddf1SHong Zhang         product->type      = MATPRODUCT_AtB;
2884222ddf1SHong Zhang       }
2894222ddf1SHong Zhang     } else if (!A_istrans && B_istrans) {
2904222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
2914222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
2924222ddf1SHong Zhang       if (Bt_istrans) { /* mat = A * BTT */
2934222ddf1SHong Zhang         Mat Btt = NULL;
2944222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
295*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
296*4417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
2974222ddf1SHong Zhang         B                  = Btt;
2984222ddf1SHong Zhang         product->B         = Btt; /* use Btt for matproduct */
2994222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
3004222ddf1SHong Zhang       } else { /* !Bt_istrans */
3014222ddf1SHong Zhang         /* mat = A*Bt^T */
302*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Bt);CHKERRQ(ierr);
303*4417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
3044222ddf1SHong Zhang         B                  = Bt;
3054222ddf1SHong Zhang         product->B         = Bt;
3064222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
3074222ddf1SHong Zhang         product->type = MATPRODUCT_ABt;
3084222ddf1SHong Zhang       }
3094222ddf1SHong Zhang     } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */
3104222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
3114222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
3124222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
3134222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
3144222ddf1SHong Zhang       if (At_istrans && Bt_istrans) {
3154222ddf1SHong Zhang         Mat Att= NULL,Btt = NULL;
3164222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
3174222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
318*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
319*4417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
320*4417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
321*4417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
3224222ddf1SHong Zhang         A             = Att;
3234222ddf1SHong Zhang         product->A    = Att; product->Areplaced = PETSC_TRUE;
3244222ddf1SHong Zhang         B             = Btt;
3254222ddf1SHong Zhang         product->B    = Btt; product->Breplaced = PETSC_TRUE;
3264222ddf1SHong Zhang       } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet");
3274222ddf1SHong Zhang     }
3284222ddf1SHong Zhang 
3294222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
3304222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3314222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3324222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3334222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3344222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3354222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
3364222ddf1SHong Zhang     if (!f) {
3374222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3384222ddf1SHong Zhang     }
3394222ddf1SHong Zhang   }
3404222ddf1SHong Zhang 
3414222ddf1SHong Zhang   if (!f) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
3424222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
3434222ddf1SHong Zhang   PetscFunctionReturn(0);
3444222ddf1SHong Zhang }
3454222ddf1SHong Zhang 
3464222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat)
3474222ddf1SHong Zhang {
3484222ddf1SHong Zhang   PetscErrorCode ierr;
3494222ddf1SHong Zhang   Mat_Product    *product = mat->product;
3504222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
3514222ddf1SHong Zhang   PetscBool      sametype;
3524222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
3534222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
3544222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
3554222ddf1SHong Zhang 
3564222ddf1SHong Zhang   PetscFunctionBegin;
3574222ddf1SHong Zhang   /* Check matrix global sizes */
3584222ddf1SHong Zhang   if (B->rmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->rmap->N);
3594222ddf1SHong Zhang 
3604222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
3614222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
3624222ddf1SHong Zhang 
3634222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
3644222ddf1SHong Zhang 
3654222ddf1SHong Zhang   if (fB == fA && sametype) {
3664222ddf1SHong Zhang     f = fB;
3674222ddf1SHong Zhang   } else {
3684222ddf1SHong Zhang     char      mtypes[256];
3694222ddf1SHong Zhang     PetscBool istrans;
3704222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
3714222ddf1SHong Zhang     if (!istrans) {
3724222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
3734222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3744222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3754222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3764222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3774222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3784222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3794222ddf1SHong Zhang     } else {
3804222ddf1SHong Zhang       Mat T = NULL;
3814222ddf1SHong Zhang       SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AtB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
3824222ddf1SHong Zhang 
3834222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
3844222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3854222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3864222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3874222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3884222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3894222ddf1SHong Zhang 
3904222ddf1SHong Zhang       product->type = MATPRODUCT_AtB;
3914222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3924222ddf1SHong Zhang     }
3934222ddf1SHong Zhang 
3944222ddf1SHong Zhang     if (!f) {
3954222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
3964222ddf1SHong Zhang     }
3974222ddf1SHong Zhang   }
3984222ddf1SHong Zhang   if (!f) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
3994222ddf1SHong Zhang 
4004222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
4014222ddf1SHong Zhang   PetscFunctionReturn(0);
4024222ddf1SHong Zhang }
4034222ddf1SHong Zhang 
4044222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat)
4054222ddf1SHong Zhang {
4064222ddf1SHong Zhang   PetscErrorCode ierr;
4074222ddf1SHong Zhang   Mat_Product    *product = mat->product;
4084222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
4094222ddf1SHong Zhang   PetscBool      sametype;
4104222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
4114222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
4124222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
4134222ddf1SHong Zhang 
4144222ddf1SHong Zhang   PetscFunctionBegin;
4154222ddf1SHong Zhang   /* Check matrix global sizes */
4164222ddf1SHong Zhang   if (B->cmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, AN %D != BN %D",A->cmap->N,B->cmap->N);
4174222ddf1SHong Zhang 
4184222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4194222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
4204222ddf1SHong Zhang 
4214222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
4224222ddf1SHong Zhang 
4234222ddf1SHong Zhang   if (fB == fA && sametype) {
4244222ddf1SHong Zhang     f = fB;
4254222ddf1SHong Zhang   } else {
4264222ddf1SHong Zhang     char      mtypes[256];
4274222ddf1SHong Zhang     PetscBool istrans;
4284222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
4294222ddf1SHong Zhang     if (!istrans) {
4304222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
4314222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4324222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4334222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4344222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4354222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4364222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4374222ddf1SHong Zhang     } else {
4384222ddf1SHong Zhang       Mat T = NULL;
4394222ddf1SHong Zhang       SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_ABt for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
4404222ddf1SHong Zhang 
4414222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
4424222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4434222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4444222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4454222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4464222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4474222ddf1SHong Zhang 
4484222ddf1SHong Zhang       product->type = MATPRODUCT_ABt;
4494222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4504222ddf1SHong Zhang     }
4514222ddf1SHong Zhang 
4524222ddf1SHong Zhang     if (!f) {
4534222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4544222ddf1SHong Zhang     }
4554222ddf1SHong Zhang   }
4564222ddf1SHong Zhang   if (!f) {
4574222ddf1SHong Zhang     SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
4584222ddf1SHong Zhang   }
4594222ddf1SHong Zhang 
4604222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
4614222ddf1SHong Zhang   PetscFunctionReturn(0);
4624222ddf1SHong Zhang }
4634222ddf1SHong Zhang 
4644222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat)
4654222ddf1SHong Zhang {
4664222ddf1SHong Zhang   PetscErrorCode ierr;
4674222ddf1SHong Zhang   Mat_Product    *product = mat->product;
4684222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
4694222ddf1SHong Zhang   PetscBool      sametype;
4704222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
4714222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
4724222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
4734222ddf1SHong Zhang 
4744222ddf1SHong Zhang   PetscFunctionBegin;
4754222ddf1SHong Zhang   /* Check matrix global sizes */
4764222ddf1SHong Zhang   if (A->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N);
4774222ddf1SHong Zhang   if (B->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
4784222ddf1SHong Zhang 
4794222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4804222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
4814222ddf1SHong Zhang 
4824222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
4834222ddf1SHong Zhang   if (fB == fA && sametype) {
4844222ddf1SHong Zhang     f = fB;
4854222ddf1SHong Zhang   } else {
4864222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
4874222ddf1SHong Zhang     char  mtypes[256];
4884222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4894222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4904222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4914222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4924222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4934222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4944222ddf1SHong Zhang 
4954222ddf1SHong Zhang     if (!f) {
4964222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4974222ddf1SHong Zhang     }
4984222ddf1SHong Zhang   }
4994222ddf1SHong Zhang 
5004222ddf1SHong Zhang   if (f) {
5014222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5024222ddf1SHong Zhang   } else {
5034222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5044222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProductSetFromOptions_PtAP for A %s, P %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
5054222ddf1SHong Zhang   }
5064222ddf1SHong Zhang   PetscFunctionReturn(0);
5074222ddf1SHong Zhang }
5084222ddf1SHong Zhang 
5094222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat)
5104222ddf1SHong Zhang {
5114222ddf1SHong Zhang   PetscErrorCode ierr;
5124222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5134222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5144222ddf1SHong Zhang   PetscBool      sametype;
5154222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5164222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5174222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5184222ddf1SHong Zhang 
5194222ddf1SHong Zhang   PetscFunctionBegin;
5204222ddf1SHong Zhang   /* Check matrix global sizes */
5214222ddf1SHong Zhang   if (A->rmap->N != B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N);
5224222ddf1SHong Zhang   if (B->cmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->cmap->N,A->cmap->N);
5234222ddf1SHong Zhang 
5244222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5254222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5264222ddf1SHong Zhang 
5274222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
5284222ddf1SHong Zhang   if (fB == fA && sametype) {
5294222ddf1SHong Zhang     f = fB;
5304222ddf1SHong Zhang   } else {
5314222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
5324222ddf1SHong Zhang     char  mtypes[256];
5334222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5344222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5354222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5364222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5374222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5384222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
5394222ddf1SHong Zhang 
5404222ddf1SHong Zhang     if (!f) {
5414222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
5424222ddf1SHong Zhang     }
5434222ddf1SHong Zhang   }
5444222ddf1SHong Zhang 
5454222ddf1SHong Zhang   if (f) {
5464222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5474222ddf1SHong Zhang   } else {
5484222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5494222ddf1SHong Zhang   }
5504222ddf1SHong Zhang   PetscFunctionReturn(0);
5514222ddf1SHong Zhang }
5524222ddf1SHong Zhang 
5534222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat)
5544222ddf1SHong Zhang {
5554222ddf1SHong Zhang   PetscErrorCode ierr;
5564222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5574222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
5584222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5594222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5604222ddf1SHong Zhang   PetscErrorCode (*fC)(Mat);
5614222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5624222ddf1SHong Zhang 
5634222ddf1SHong Zhang   PetscFunctionBegin;
5644222ddf1SHong Zhang   /* Check matrix global sizes */
5654222ddf1SHong Zhang   if (B->rmap->N!= A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N);
5664222ddf1SHong Zhang   if (C->rmap->N!= B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",C->rmap->N,B->cmap->N);
5674222ddf1SHong Zhang 
5684222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5694222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5704222ddf1SHong Zhang   fC = C->ops->productsetfromoptions;
5714222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
5724222ddf1SHong Zhang     f = fA;
5734222ddf1SHong Zhang   } else {
5744222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype_Ctype */
5754222ddf1SHong Zhang     char  mtypes[256];
5764222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5774222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5784222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5794222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5804222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5814222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5824222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5834222ddf1SHong Zhang 
5844222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
5854222ddf1SHong Zhang     if (!f) {
5864222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
5874222ddf1SHong Zhang     }
5884222ddf1SHong Zhang     if (!f) {
5894222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
5904222ddf1SHong Zhang     }
5914222ddf1SHong Zhang   }
5924222ddf1SHong Zhang 
5934222ddf1SHong Zhang   if (f) {
5944222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5954222ddf1SHong Zhang   } else { /* use MatProductSymbolic/Numeric_Basic() */
5964222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5974222ddf1SHong Zhang   }
5984222ddf1SHong Zhang   PetscFunctionReturn(0);
5994222ddf1SHong Zhang }
6004222ddf1SHong Zhang 
6014222ddf1SHong Zhang /*@C
6024222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
6034222ddf1SHong Zhang 
6044222ddf1SHong Zhang    Logically Collective on Mat
6054222ddf1SHong Zhang 
6064222ddf1SHong Zhang    Input Parameter:
6074222ddf1SHong Zhang .  mat - the matrix
6084222ddf1SHong Zhang 
6094222ddf1SHong Zhang    Level: beginner
6104222ddf1SHong Zhang 
6114222ddf1SHong Zhang .seealso: MatSetFromOptions()
6124222ddf1SHong Zhang @*/
6134222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
6144222ddf1SHong Zhang {
6154222ddf1SHong Zhang   PetscErrorCode ierr;
6164222ddf1SHong Zhang 
6174222ddf1SHong Zhang   PetscFunctionBegin;
6184222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6194222ddf1SHong Zhang 
6204222ddf1SHong Zhang   if (mat->ops->productsetfromoptions) {
6214222ddf1SHong Zhang     ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr);
6224222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Call MatProductSetType() first");
6234222ddf1SHong Zhang   PetscFunctionReturn(0);
6244222ddf1SHong Zhang }
6254222ddf1SHong Zhang 
6264222ddf1SHong Zhang /* ----------------------------------------------- */
6274222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
6284222ddf1SHong Zhang {
6294222ddf1SHong Zhang   PetscErrorCode ierr;
6304222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6314222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6324222ddf1SHong Zhang 
6334222ddf1SHong Zhang   PetscFunctionBegin;
6344222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6354222ddf1SHong Zhang   ierr = (mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
6364222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6374222ddf1SHong Zhang   PetscFunctionReturn(0);
6384222ddf1SHong Zhang }
6394222ddf1SHong Zhang 
6404222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(Mat mat)
6414222ddf1SHong Zhang {
6424222ddf1SHong Zhang   PetscErrorCode ierr;
6434222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6444222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6454222ddf1SHong Zhang 
6464222ddf1SHong Zhang   PetscFunctionBegin;
6474222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6484222ddf1SHong Zhang   ierr = (mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
6494222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6504222ddf1SHong Zhang   PetscFunctionReturn(0);
6514222ddf1SHong Zhang }
6524222ddf1SHong Zhang 
6534222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
6544222ddf1SHong Zhang {
6554222ddf1SHong Zhang   PetscErrorCode ierr;
6564222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6574222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6584222ddf1SHong Zhang 
6594222ddf1SHong Zhang   PetscFunctionBegin;
6604222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6614222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
6624222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6634222ddf1SHong Zhang   PetscFunctionReturn(0);
6644222ddf1SHong Zhang }
6654222ddf1SHong Zhang 
6664222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
6674222ddf1SHong Zhang {
6684222ddf1SHong Zhang   PetscErrorCode ierr;
6694222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6704222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6714222ddf1SHong Zhang 
6724222ddf1SHong Zhang   PetscFunctionBegin;
6734222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6744222ddf1SHong Zhang   ierr = (mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
6754222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6764222ddf1SHong Zhang   PetscFunctionReturn(0);
6774222ddf1SHong Zhang }
6784222ddf1SHong Zhang 
6794222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
6804222ddf1SHong Zhang {
6814222ddf1SHong Zhang   PetscErrorCode ierr;
6824222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6834222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6844222ddf1SHong Zhang 
6854222ddf1SHong Zhang   PetscFunctionBegin;
6864222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6874222ddf1SHong Zhang   ierr = (mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
6884222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6894222ddf1SHong Zhang   PetscFunctionReturn(0);
6904222ddf1SHong Zhang }
6914222ddf1SHong Zhang 
6924222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
6934222ddf1SHong Zhang {
6944222ddf1SHong Zhang   PetscErrorCode ierr;
6954222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6964222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
6974222ddf1SHong Zhang 
6984222ddf1SHong Zhang   PetscFunctionBegin;
6994222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
7004222ddf1SHong Zhang   ierr = (mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
7014222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
7024222ddf1SHong Zhang   PetscFunctionReturn(0);
7034222ddf1SHong Zhang }
7044222ddf1SHong Zhang 
7054222ddf1SHong Zhang /*@
7064222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
7074222ddf1SHong Zhang 
7084222ddf1SHong Zhang    Collective on Mat
7094222ddf1SHong Zhang 
7104222ddf1SHong Zhang    Input Parameters:
7114222ddf1SHong Zhang .  mat - the matrix to hold a product
7124222ddf1SHong Zhang 
7134222ddf1SHong Zhang    Output Parameters:
7144222ddf1SHong Zhang .  mat - the matrix product
7154222ddf1SHong Zhang 
7164222ddf1SHong Zhang    Level: intermediate
7174222ddf1SHong Zhang 
7184222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType()
7194222ddf1SHong Zhang @*/
7204222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
7214222ddf1SHong Zhang {
7224222ddf1SHong Zhang   PetscErrorCode ierr;
7234222ddf1SHong Zhang 
7244222ddf1SHong Zhang   PetscFunctionBegin;
7254222ddf1SHong Zhang   PetscValidPointer(mat,1);
7264222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7274222ddf1SHong Zhang 
7284222ddf1SHong Zhang   if (mat->ops->productnumeric) {
7294222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
7304222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSymbolic() first");
7314222ddf1SHong Zhang   PetscFunctionReturn(0);
7324222ddf1SHong Zhang }
7334222ddf1SHong Zhang 
7344222ddf1SHong Zhang /* ----------------------------------------------- */
7354222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
7364222ddf1SHong Zhang {
7374222ddf1SHong Zhang   PetscErrorCode ierr;
7384222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7394222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7404222ddf1SHong Zhang 
7414222ddf1SHong Zhang   PetscFunctionBegin;
7424222ddf1SHong Zhang   ierr = (mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7434222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
7444222ddf1SHong Zhang   PetscFunctionReturn(0);
7454222ddf1SHong Zhang }
7464222ddf1SHong Zhang 
7474222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
7484222ddf1SHong Zhang {
7494222ddf1SHong Zhang   PetscErrorCode ierr;
7504222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7514222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7524222ddf1SHong Zhang 
7534222ddf1SHong Zhang   PetscFunctionBegin;
7544222ddf1SHong Zhang   ierr = (mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7554222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
7564222ddf1SHong Zhang   PetscFunctionReturn(0);
7574222ddf1SHong Zhang }
7584222ddf1SHong Zhang 
7594222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
7604222ddf1SHong Zhang {
7614222ddf1SHong Zhang   PetscErrorCode ierr;
7624222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7634222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7644222ddf1SHong Zhang 
7654222ddf1SHong Zhang   PetscFunctionBegin;
7664222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7674222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
7684222ddf1SHong Zhang   PetscFunctionReturn(0);
7694222ddf1SHong Zhang }
7704222ddf1SHong Zhang 
7714222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
7724222ddf1SHong Zhang {
7734222ddf1SHong Zhang   PetscErrorCode ierr;
7744222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7754222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
7764222ddf1SHong Zhang 
7774222ddf1SHong Zhang   PetscFunctionBegin;
7784222ddf1SHong Zhang   ierr = (mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
7794222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
7804222ddf1SHong Zhang   PetscFunctionReturn(0);
7814222ddf1SHong Zhang }
7824222ddf1SHong Zhang 
7834222ddf1SHong Zhang /*@
7844222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
7854222ddf1SHong Zhang 
7864222ddf1SHong Zhang    Collective on Mat
7874222ddf1SHong Zhang 
7884222ddf1SHong Zhang    Input Parameters:
7894222ddf1SHong Zhang .  mat - the matrix to hold a product
7904222ddf1SHong Zhang 
7914222ddf1SHong Zhang    Output Parameters:
7924222ddf1SHong Zhang .  mat - the matrix product data structure
7934222ddf1SHong Zhang 
7944222ddf1SHong Zhang    Level: intermediate
7954222ddf1SHong Zhang 
7964222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm
7974222ddf1SHong Zhang @*/
7984222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
7994222ddf1SHong Zhang {
8004222ddf1SHong Zhang   PetscErrorCode ierr;
8014222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8024222ddf1SHong Zhang   MatProductType productype = product->type;
8034222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
8044222ddf1SHong Zhang 
8054222ddf1SHong Zhang   PetscFunctionBegin;
8064222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8074222ddf1SHong Zhang 
8084222ddf1SHong Zhang   /* log event */
8094222ddf1SHong Zhang   switch (productype) {
8104222ddf1SHong Zhang   case MATPRODUCT_AB:
8114222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
8124222ddf1SHong Zhang     break;
8134222ddf1SHong Zhang   case MATPRODUCT_AtB:
8144222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
8154222ddf1SHong Zhang     break;
8164222ddf1SHong Zhang   case MATPRODUCT_ABt:
8174222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
8184222ddf1SHong Zhang     break;
8194222ddf1SHong Zhang   case MATPRODUCT_PtAP:
8204222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
8214222ddf1SHong Zhang     break;
8224222ddf1SHong Zhang   case MATPRODUCT_RARt:
8234222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
8244222ddf1SHong Zhang     break;
8254222ddf1SHong Zhang   case MATPRODUCT_ABC:
8264222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
8274222ddf1SHong Zhang     break;
8284222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported");
8294222ddf1SHong Zhang   }
8304222ddf1SHong Zhang 
8314222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
8324222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
8334222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
8344222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
8354222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSetFromOptions() first");
8364222ddf1SHong Zhang   PetscFunctionReturn(0);
8374222ddf1SHong Zhang }
8384222ddf1SHong Zhang 
8394222ddf1SHong Zhang /*@
8404222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
8414222ddf1SHong Zhang 
8424222ddf1SHong Zhang    Collective on Mat
8434222ddf1SHong Zhang 
8444222ddf1SHong Zhang    Input Parameters:
8454222ddf1SHong Zhang +  mat - the matrix product
8464222ddf1SHong 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.
8474222ddf1SHong Zhang 
8484222ddf1SHong Zhang    Level: intermediate
8494222ddf1SHong Zhang 
8504222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
8514222ddf1SHong Zhang @*/
8524222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
8534222ddf1SHong Zhang {
8544222ddf1SHong Zhang   Mat_Product *product = mat->product;
8554222ddf1SHong Zhang 
8564222ddf1SHong Zhang   PetscFunctionBegin;
8574222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8584222ddf1SHong Zhang 
8594222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
8604222ddf1SHong Zhang   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) {
8614222ddf1SHong Zhang     product->fill = 2.0;
8624222ddf1SHong Zhang   } else product->fill = fill;
8634222ddf1SHong Zhang   PetscFunctionReturn(0);
8644222ddf1SHong Zhang }
8654222ddf1SHong Zhang 
8664222ddf1SHong Zhang /*@
8674222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
8684222ddf1SHong Zhang 
8694222ddf1SHong Zhang    Collective on Mat
8704222ddf1SHong Zhang 
8714222ddf1SHong Zhang    Input Parameters:
8724222ddf1SHong Zhang +  mat - the matrix product
8734222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
8744222ddf1SHong Zhang 
8754222ddf1SHong Zhang    Level: intermediate
8764222ddf1SHong Zhang 
8774222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate()
8784222ddf1SHong Zhang @*/
8794222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
8804222ddf1SHong Zhang {
8814222ddf1SHong Zhang   Mat_Product *product = mat->product;
8824222ddf1SHong Zhang 
8834222ddf1SHong Zhang   PetscFunctionBegin;
8844222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8854222ddf1SHong Zhang 
8864222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
8874222ddf1SHong Zhang   product->alg = alg;
8884222ddf1SHong Zhang   PetscFunctionReturn(0);
8894222ddf1SHong Zhang }
8904222ddf1SHong Zhang 
8914222ddf1SHong Zhang /*@
8924222ddf1SHong Zhang    MatProductSetType - Sets a particular matrix product type, for example Mat*Mat.
8934222ddf1SHong Zhang 
8944222ddf1SHong Zhang    Collective on Mat
8954222ddf1SHong Zhang 
8964222ddf1SHong Zhang    Input Parameters:
8974222ddf1SHong Zhang +  mat - the matrix
8984222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
8994222ddf1SHong Zhang 
9004222ddf1SHong Zhang    Level: intermediate
9014222ddf1SHong Zhang 
9024222ddf1SHong Zhang .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm
9034222ddf1SHong Zhang @*/
9044222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
9054222ddf1SHong Zhang {
9064222ddf1SHong Zhang   PetscErrorCode ierr;
9074222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9084222ddf1SHong Zhang   MPI_Comm       comm;
9094222ddf1SHong Zhang 
9104222ddf1SHong Zhang   PetscFunctionBegin;
9114222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9124222ddf1SHong Zhang 
9134222ddf1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
9144222ddf1SHong Zhang   if (!product) SETERRQ(comm,PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
9154222ddf1SHong Zhang   product->type = productype;
9164222ddf1SHong Zhang 
9174222ddf1SHong Zhang   switch (productype) {
9184222ddf1SHong Zhang   case MATPRODUCT_AB:
9194222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AB;
9204222ddf1SHong Zhang     break;
9214222ddf1SHong Zhang   case MATPRODUCT_AtB:
9224222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB;
9234222ddf1SHong Zhang     break;
9244222ddf1SHong Zhang   case MATPRODUCT_ABt:
9254222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt;
9264222ddf1SHong Zhang     break;
9274222ddf1SHong Zhang   case MATPRODUCT_PtAP:
9284222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP;
9294222ddf1SHong Zhang     break;
9304222ddf1SHong Zhang   case MATPRODUCT_RARt:
9314222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt;
9324222ddf1SHong Zhang     break;
9334222ddf1SHong Zhang   case MATPRODUCT_ABC:
9344222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC;
9354222ddf1SHong Zhang     break;
9364222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported\n");
9374222ddf1SHong Zhang   }
9384222ddf1SHong Zhang   PetscFunctionReturn(0);
9394222ddf1SHong Zhang }
9404222ddf1SHong Zhang 
941*4417c5e8SHong Zhang /*@
942*4417c5e8SHong Zhang    MatProductClear - Clears matrix product internal structure.
943*4417c5e8SHong Zhang 
944*4417c5e8SHong Zhang    Collective on Mat
945*4417c5e8SHong Zhang 
946*4417c5e8SHong Zhang    Input Parameters:
947*4417c5e8SHong Zhang .  mat - the product matrix
948*4417c5e8SHong Zhang 
949*4417c5e8SHong Zhang    Level: intermediate
950*4417c5e8SHong Zhang @*/
951*4417c5e8SHong Zhang PetscErrorCode MatProductClear(Mat mat)
952*4417c5e8SHong Zhang {
953*4417c5e8SHong Zhang   PetscErrorCode ierr;
954*4417c5e8SHong Zhang   Mat_Product    *product = mat->product;
955*4417c5e8SHong Zhang 
956*4417c5e8SHong Zhang   PetscFunctionBegin;
957*4417c5e8SHong Zhang   if (product) {
958*4417c5e8SHong Zhang     /* release reference */
959*4417c5e8SHong Zhang     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
960*4417c5e8SHong Zhang     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
961*4417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
962*4417c5e8SHong Zhang     ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr);
963*4417c5e8SHong Zhang     ierr = PetscFree(mat->product);CHKERRQ(ierr);
964*4417c5e8SHong Zhang   }
965*4417c5e8SHong Zhang   PetscFunctionReturn(0);
966*4417c5e8SHong Zhang }
967*4417c5e8SHong Zhang 
9684222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
969*4417c5e8SHong Zhang PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
9704222ddf1SHong Zhang {
9714222ddf1SHong Zhang   PetscErrorCode ierr;
9724222ddf1SHong Zhang   Mat_Product    *product=NULL;
9734222ddf1SHong Zhang 
9744222ddf1SHong Zhang   PetscFunctionBegin;
9754222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
9764222ddf1SHong Zhang   product->A        = A;
9774222ddf1SHong Zhang   product->B        = B;
9784222ddf1SHong Zhang   product->C        = C;
9794222ddf1SHong Zhang   product->Dwork    = NULL;
9804222ddf1SHong Zhang   product->alg      = MATPRODUCTALGORITHM_DEFAULT;
9814222ddf1SHong Zhang   product->fill     = 2.0; /* PETSC_DEFAULT */
9824222ddf1SHong Zhang   product->Areplaced = PETSC_FALSE;
9834222ddf1SHong Zhang   product->Breplaced = PETSC_FALSE;
9844222ddf1SHong Zhang   product->api_user  = PETSC_FALSE;
9854222ddf1SHong Zhang   D->product         = product;
986*4417c5e8SHong Zhang 
987*4417c5e8SHong Zhang   /* take ownership */
988*4417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
989*4417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
990*4417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
9914222ddf1SHong Zhang   PetscFunctionReturn(0);
9924222ddf1SHong Zhang }
9934222ddf1SHong Zhang 
9944222ddf1SHong Zhang /*@
9954222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
9964222ddf1SHong Zhang 
9974222ddf1SHong Zhang    Collective on Mat
9984222ddf1SHong Zhang 
9994222ddf1SHong Zhang    Input Parameters:
10004222ddf1SHong Zhang +  A - the first matrix
10014222ddf1SHong Zhang .  B - the second matrix
10024222ddf1SHong Zhang .  C - the third matrix (optional)
10034222ddf1SHong Zhang -  D - the matrix which will be used as a product
10044222ddf1SHong Zhang 
10054222ddf1SHong Zhang    Output Parameters:
10064222ddf1SHong Zhang .  D - the product matrix
10074222ddf1SHong Zhang 
10084222ddf1SHong Zhang    Level: intermediate
10094222ddf1SHong Zhang 
10104222ddf1SHong Zhang .seealso: MatProductCreate()
10114222ddf1SHong Zhang @*/
10124222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
10134222ddf1SHong Zhang {
10144222ddf1SHong Zhang   PetscErrorCode ierr;
10154222ddf1SHong Zhang 
10164222ddf1SHong Zhang   PetscFunctionBegin;
10174222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10184222ddf1SHong Zhang   PetscValidType(A,1);
10194222ddf1SHong Zhang   MatCheckPreallocated(A,1);
10204222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10214222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10224222ddf1SHong Zhang 
10234222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10244222ddf1SHong Zhang   PetscValidType(B,2);
10254222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10264222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10274222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10284222ddf1SHong Zhang 
10294222ddf1SHong Zhang   if (C) {
10304222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10314222ddf1SHong Zhang     PetscValidType(C,3);
10324222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10334222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10344222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10354222ddf1SHong Zhang   }
10364222ddf1SHong Zhang 
10374222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
10384222ddf1SHong Zhang   PetscValidType(D,4);
10394222ddf1SHong Zhang   MatCheckPreallocated(D,4);
10404222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10414222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10424222ddf1SHong Zhang 
10434222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
10444222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
10454222ddf1SHong Zhang   PetscFunctionReturn(0);
10464222ddf1SHong Zhang }
10474222ddf1SHong Zhang 
10484222ddf1SHong Zhang /*@
10494222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
10504222ddf1SHong Zhang 
10514222ddf1SHong Zhang    Collective on Mat
10524222ddf1SHong Zhang 
10534222ddf1SHong Zhang    Input Parameters:
10544222ddf1SHong Zhang +  A - the first matrix
10554222ddf1SHong Zhang .  B - the second matrix
10564222ddf1SHong Zhang -  C - the third matrix (optional)
10574222ddf1SHong Zhang 
10584222ddf1SHong Zhang    Output Parameters:
10594222ddf1SHong Zhang .  D - the product matrix
10604222ddf1SHong Zhang 
10614222ddf1SHong Zhang    Level: intermediate
10624222ddf1SHong Zhang 
10634222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
10644222ddf1SHong Zhang @*/
10654222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
10664222ddf1SHong Zhang {
10674222ddf1SHong Zhang   PetscErrorCode ierr;
10684222ddf1SHong Zhang 
10694222ddf1SHong Zhang   PetscFunctionBegin;
10704222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10714222ddf1SHong Zhang   PetscValidType(A,1);
10724222ddf1SHong Zhang   MatCheckPreallocated(A,1);
10734222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10744222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10754222ddf1SHong Zhang 
10764222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10774222ddf1SHong Zhang   PetscValidType(B,2);
10784222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10794222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10804222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10814222ddf1SHong Zhang 
10824222ddf1SHong Zhang   if (C) {
10834222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10844222ddf1SHong Zhang     PetscValidType(C,3);
10854222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10864222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10874222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10884222ddf1SHong Zhang   }
10894222ddf1SHong Zhang 
10904222ddf1SHong Zhang   PetscValidPointer(D,4);
10914222ddf1SHong Zhang 
10924222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
10934222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
10944222ddf1SHong Zhang   PetscFunctionReturn(0);
10954222ddf1SHong Zhang }
1096