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