xref: /petsc/src/mat/interface/matproduct.c (revision 544a5e07e08964aab8a0b04553d4936e9399006f)
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 
33*544a5e07SHong Zhang const char *const MatProductTypes[] = {"AB","AtB","ABt","PtAP","RARt","ABC","MatProductType","MAT_Product_",0};
34*544a5e07SHong 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);
2644222ddf1SHong Zhang 
2654222ddf1SHong Zhang   if (fB == fA && sametype && (!A_istrans || !B_istrans)) {
2664222ddf1SHong Zhang     f = fB;
2674222ddf1SHong Zhang   } else {
2684222ddf1SHong Zhang     char      mtypes[256];
2694222ddf1SHong Zhang     PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE;
2704222ddf1SHong Zhang     Mat       At = NULL,Bt = NULL;
2714222ddf1SHong Zhang 
2724222ddf1SHong Zhang     if (A_istrans && !B_istrans) {
2734222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
2744222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
2754222ddf1SHong Zhang       if (At_istrans) { /* mat = ATT * B */
2764222ddf1SHong Zhang         Mat Att = NULL;
2774222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
2784417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
2794417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2804222ddf1SHong Zhang         A                  = Att;
2814222ddf1SHong Zhang         product->A         = Att; /* use Att for matproduct */
2824222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */
2834222ddf1SHong Zhang       } else { /* !At_istrans: mat = At^T*B */
2844417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)At);CHKERRQ(ierr);
2854417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
2864222ddf1SHong Zhang         A                  = At;
2874222ddf1SHong Zhang         product->A         = At;
2884222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE;
2894222ddf1SHong Zhang         product->type      = MATPRODUCT_AtB;
2904222ddf1SHong Zhang       }
2914222ddf1SHong Zhang     } else if (!A_istrans && B_istrans) {
2924222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
2934222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
2944222ddf1SHong Zhang       if (Bt_istrans) { /* mat = A * BTT */
2954222ddf1SHong Zhang         Mat Btt = NULL;
2964222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
2974417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
2984417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
2994222ddf1SHong Zhang         B                  = Btt;
3004222ddf1SHong Zhang         product->B         = Btt; /* use Btt for matproduct */
3014222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
3024222ddf1SHong Zhang       } else { /* !Bt_istrans */
3034222ddf1SHong Zhang         /* mat = A*Bt^T */
3044417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Bt);CHKERRQ(ierr);
3054417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
3064222ddf1SHong Zhang         B                  = Bt;
3074222ddf1SHong Zhang         product->B         = Bt;
3084222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
3094222ddf1SHong Zhang         product->type = MATPRODUCT_ABt;
3104222ddf1SHong Zhang       }
3114222ddf1SHong Zhang     } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */
3124222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
3134222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
3144222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
3154222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
3164222ddf1SHong Zhang       if (At_istrans && Bt_istrans) {
3174222ddf1SHong Zhang         Mat Att= NULL,Btt = NULL;
3184222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
3194222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
3204417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr);
3214417c5e8SHong Zhang         ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr);
3224417c5e8SHong Zhang         ierr = MatDestroy(&product->A);CHKERRQ(ierr);
3234417c5e8SHong Zhang         ierr = MatDestroy(&product->B);CHKERRQ(ierr);
3244222ddf1SHong Zhang         A             = Att;
3254222ddf1SHong Zhang         product->A    = Att; product->Areplaced = PETSC_TRUE;
3264222ddf1SHong Zhang         B             = Btt;
3274222ddf1SHong Zhang         product->B    = Btt; product->Breplaced = PETSC_TRUE;
3284222ddf1SHong Zhang       } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet");
3294222ddf1SHong Zhang     }
3304222ddf1SHong Zhang 
3314222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
3324222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3334222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3344222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3354222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3364222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3374222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
3384222ddf1SHong Zhang     if (!f) {
3394222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3404222ddf1SHong Zhang     }
3414222ddf1SHong Zhang   }
3424222ddf1SHong Zhang 
3434222ddf1SHong 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);
3444222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
3454222ddf1SHong Zhang   PetscFunctionReturn(0);
3464222ddf1SHong Zhang }
3474222ddf1SHong Zhang 
3484222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat)
3494222ddf1SHong Zhang {
3504222ddf1SHong Zhang   PetscErrorCode ierr;
3514222ddf1SHong Zhang   Mat_Product    *product = mat->product;
3524222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
3534222ddf1SHong Zhang   PetscBool      sametype;
3544222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
3554222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
3564222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
3574222ddf1SHong Zhang 
3584222ddf1SHong Zhang   PetscFunctionBegin;
3594222ddf1SHong Zhang   /* Check matrix global sizes */
3604222ddf1SHong 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);
3614222ddf1SHong Zhang 
3624222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
3634222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
3644222ddf1SHong Zhang 
3654222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
3664222ddf1SHong Zhang 
3674222ddf1SHong Zhang   if (fB == fA && sametype) {
3684222ddf1SHong Zhang     f = fB;
3694222ddf1SHong Zhang   } else {
3704222ddf1SHong Zhang     char      mtypes[256];
3714222ddf1SHong Zhang     PetscBool istrans;
3724222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
3734222ddf1SHong Zhang     if (!istrans) {
3744222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
3754222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3764222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3774222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3784222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3794222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3804222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3814222ddf1SHong Zhang     } else {
3824222ddf1SHong Zhang       Mat T = NULL;
3834222ddf1SHong 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);
3844222ddf1SHong Zhang 
3854222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
3864222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
3874222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3884222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
3894222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
3904222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
3914222ddf1SHong Zhang 
3924222ddf1SHong Zhang       product->type = MATPRODUCT_AtB;
3934222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
3944222ddf1SHong Zhang     }
3954222ddf1SHong Zhang 
3964222ddf1SHong Zhang     if (!f) {
3974222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
3984222ddf1SHong Zhang     }
3994222ddf1SHong Zhang   }
4004222ddf1SHong 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);
4014222ddf1SHong Zhang 
4024222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
4034222ddf1SHong Zhang   PetscFunctionReturn(0);
4044222ddf1SHong Zhang }
4054222ddf1SHong Zhang 
4064222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat)
4074222ddf1SHong Zhang {
4084222ddf1SHong Zhang   PetscErrorCode ierr;
4094222ddf1SHong Zhang   Mat_Product    *product = mat->product;
4104222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
4114222ddf1SHong Zhang   PetscBool      sametype;
4124222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
4134222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
4144222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
4154222ddf1SHong Zhang 
4164222ddf1SHong Zhang   PetscFunctionBegin;
4174222ddf1SHong Zhang   /* Check matrix global sizes */
4184222ddf1SHong 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);
4194222ddf1SHong Zhang 
4204222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4214222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
4224222ddf1SHong Zhang 
4234222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
4244222ddf1SHong Zhang 
4254222ddf1SHong Zhang   if (fB == fA && sametype) {
4264222ddf1SHong Zhang     f = fB;
4274222ddf1SHong Zhang   } else {
4284222ddf1SHong Zhang     char      mtypes[256];
4294222ddf1SHong Zhang     PetscBool istrans;
4304222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
4314222ddf1SHong Zhang     if (!istrans) {
4324222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
4334222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4344222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4354222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4364222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4374222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4384222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4394222ddf1SHong Zhang     } else {
4404222ddf1SHong Zhang       Mat T = NULL;
4414222ddf1SHong 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);
4424222ddf1SHong Zhang 
4434222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
4444222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4454222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4464222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4474222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4484222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4494222ddf1SHong Zhang 
4504222ddf1SHong Zhang       product->type = MATPRODUCT_ABt;
4514222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4524222ddf1SHong Zhang     }
4534222ddf1SHong Zhang 
4544222ddf1SHong Zhang     if (!f) {
4554222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4564222ddf1SHong Zhang     }
4574222ddf1SHong Zhang   }
4584222ddf1SHong Zhang   if (!f) {
4594222ddf1SHong 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);
4604222ddf1SHong Zhang   }
4614222ddf1SHong Zhang 
4624222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
4634222ddf1SHong Zhang   PetscFunctionReturn(0);
4644222ddf1SHong Zhang }
4654222ddf1SHong Zhang 
4664222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat)
4674222ddf1SHong Zhang {
4684222ddf1SHong Zhang   PetscErrorCode ierr;
4694222ddf1SHong Zhang   Mat_Product    *product = mat->product;
4704222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
4714222ddf1SHong Zhang   PetscBool      sametype;
4724222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
4734222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
4744222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
4754222ddf1SHong Zhang 
4764222ddf1SHong Zhang   PetscFunctionBegin;
4774222ddf1SHong Zhang   /* Check matrix global sizes */
4784222ddf1SHong 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);
4794222ddf1SHong 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);
4804222ddf1SHong Zhang 
4814222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
4824222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
4834222ddf1SHong Zhang 
4844222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
4854222ddf1SHong Zhang   if (fB == fA && sametype) {
4864222ddf1SHong Zhang     f = fB;
4874222ddf1SHong Zhang   } else {
4884222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
4894222ddf1SHong Zhang     char  mtypes[256];
4904222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
4914222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4924222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
4934222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
4944222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
4954222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
4964222ddf1SHong Zhang 
4974222ddf1SHong Zhang     if (!f) {
4984222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
4994222ddf1SHong Zhang     }
5004222ddf1SHong Zhang   }
5014222ddf1SHong Zhang 
5024222ddf1SHong Zhang   if (f) {
5034222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5044222ddf1SHong Zhang   } else {
5054222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5064222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProductSetFromOptions_PtAP for A %s, P %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
5074222ddf1SHong Zhang   }
5084222ddf1SHong Zhang   PetscFunctionReturn(0);
5094222ddf1SHong Zhang }
5104222ddf1SHong Zhang 
5114222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat)
5124222ddf1SHong Zhang {
5134222ddf1SHong Zhang   PetscErrorCode ierr;
5144222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5154222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
5164222ddf1SHong Zhang   PetscBool      sametype;
5174222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5184222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5194222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5204222ddf1SHong Zhang 
5214222ddf1SHong Zhang   PetscFunctionBegin;
5224222ddf1SHong Zhang   /* Check matrix global sizes */
5234222ddf1SHong 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);
5244222ddf1SHong 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);
5254222ddf1SHong Zhang 
5264222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5274222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5284222ddf1SHong Zhang 
5294222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
5304222ddf1SHong Zhang   if (fB == fA && sametype) {
5314222ddf1SHong Zhang     f = fB;
5324222ddf1SHong Zhang   } else {
5334222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
5344222ddf1SHong Zhang     char  mtypes[256];
5354222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5364222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5374222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5384222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5394222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5404222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
5414222ddf1SHong Zhang 
5424222ddf1SHong Zhang     if (!f) {
5434222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
5444222ddf1SHong Zhang     }
5454222ddf1SHong Zhang   }
5464222ddf1SHong Zhang 
5474222ddf1SHong Zhang   if (f) {
5484222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5494222ddf1SHong Zhang   } else {
5504222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5514222ddf1SHong Zhang   }
5524222ddf1SHong Zhang   PetscFunctionReturn(0);
5534222ddf1SHong Zhang }
5544222ddf1SHong Zhang 
5554222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat)
5564222ddf1SHong Zhang {
5574222ddf1SHong Zhang   PetscErrorCode ierr;
5584222ddf1SHong Zhang   Mat_Product    *product = mat->product;
5594222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
5604222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
5614222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
5624222ddf1SHong Zhang   PetscErrorCode (*fC)(Mat);
5634222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
5644222ddf1SHong Zhang 
5654222ddf1SHong Zhang   PetscFunctionBegin;
5664222ddf1SHong Zhang   /* Check matrix global sizes */
5674222ddf1SHong 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);
5684222ddf1SHong 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);
5694222ddf1SHong Zhang 
5704222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
5714222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
5724222ddf1SHong Zhang   fC = C->ops->productsetfromoptions;
5734222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
5744222ddf1SHong Zhang     f = fA;
5754222ddf1SHong Zhang   } else {
5764222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype_Ctype */
5774222ddf1SHong Zhang     char  mtypes[256];
5784222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
5794222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5804222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5814222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5824222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
5834222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
5844222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
5854222ddf1SHong Zhang 
5864222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
5874222ddf1SHong Zhang     if (!f) {
5884222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
5894222ddf1SHong Zhang     }
5904222ddf1SHong Zhang     if (!f) {
5914222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
5924222ddf1SHong Zhang     }
5934222ddf1SHong Zhang   }
5944222ddf1SHong Zhang 
5954222ddf1SHong Zhang   if (f) {
5964222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
5974222ddf1SHong Zhang   } else { /* use MatProductSymbolic/Numeric_Basic() */
5984222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
5994222ddf1SHong Zhang   }
6004222ddf1SHong Zhang   PetscFunctionReturn(0);
6014222ddf1SHong Zhang }
6024222ddf1SHong Zhang 
6034222ddf1SHong Zhang /*@C
6044222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
6054222ddf1SHong Zhang 
6064222ddf1SHong Zhang    Logically Collective on Mat
6074222ddf1SHong Zhang 
6084222ddf1SHong Zhang    Input Parameter:
6094222ddf1SHong Zhang .  mat - the matrix
6104222ddf1SHong Zhang 
6114222ddf1SHong Zhang    Level: beginner
6124222ddf1SHong Zhang 
6134222ddf1SHong Zhang .seealso: MatSetFromOptions()
6144222ddf1SHong Zhang @*/
6154222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
6164222ddf1SHong Zhang {
6174222ddf1SHong Zhang   PetscErrorCode ierr;
6184222ddf1SHong Zhang 
6194222ddf1SHong Zhang   PetscFunctionBegin;
6204222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6214222ddf1SHong Zhang 
6224222ddf1SHong Zhang   if (mat->ops->productsetfromoptions) {
6234222ddf1SHong Zhang     ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr);
6244222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Call MatProductSetType() first");
6254222ddf1SHong Zhang   PetscFunctionReturn(0);
6264222ddf1SHong Zhang }
6274222ddf1SHong Zhang 
6284222ddf1SHong Zhang /* ----------------------------------------------- */
6294222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
6304222ddf1SHong Zhang {
6314222ddf1SHong Zhang   PetscErrorCode ierr;
6324222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6334222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6344222ddf1SHong Zhang 
6354222ddf1SHong Zhang   PetscFunctionBegin;
6364222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6374222ddf1SHong Zhang   ierr = (mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
6384222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6394222ddf1SHong Zhang   PetscFunctionReturn(0);
6404222ddf1SHong Zhang }
6414222ddf1SHong Zhang 
6424222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(Mat mat)
6434222ddf1SHong Zhang {
6444222ddf1SHong Zhang   PetscErrorCode ierr;
6454222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6464222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6474222ddf1SHong Zhang 
6484222ddf1SHong Zhang   PetscFunctionBegin;
6494222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6504222ddf1SHong Zhang   ierr = (mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
6514222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
6524222ddf1SHong Zhang   PetscFunctionReturn(0);
6534222ddf1SHong Zhang }
6544222ddf1SHong Zhang 
6554222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
6564222ddf1SHong Zhang {
6574222ddf1SHong Zhang   PetscErrorCode ierr;
6584222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6594222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6604222ddf1SHong Zhang 
6614222ddf1SHong Zhang   PetscFunctionBegin;
6624222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6634222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
6644222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
6654222ddf1SHong Zhang   PetscFunctionReturn(0);
6664222ddf1SHong Zhang }
6674222ddf1SHong Zhang 
6684222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
6694222ddf1SHong Zhang {
6704222ddf1SHong Zhang   PetscErrorCode ierr;
6714222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6724222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6734222ddf1SHong Zhang 
6744222ddf1SHong Zhang   PetscFunctionBegin;
6754222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6764222ddf1SHong Zhang   ierr = (mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
6774222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
6784222ddf1SHong Zhang   PetscFunctionReturn(0);
6794222ddf1SHong Zhang }
6804222ddf1SHong Zhang 
6814222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
6824222ddf1SHong Zhang {
6834222ddf1SHong Zhang   PetscErrorCode ierr;
6844222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6854222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
6864222ddf1SHong Zhang 
6874222ddf1SHong Zhang   PetscFunctionBegin;
6884222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6894222ddf1SHong Zhang   ierr = (mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
6904222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
6914222ddf1SHong Zhang   PetscFunctionReturn(0);
6924222ddf1SHong Zhang }
6934222ddf1SHong Zhang 
6944222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
6954222ddf1SHong Zhang {
6964222ddf1SHong Zhang   PetscErrorCode ierr;
6974222ddf1SHong Zhang   Mat_Product    *product = mat->product;
6984222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
6994222ddf1SHong Zhang 
7004222ddf1SHong Zhang   PetscFunctionBegin;
7014222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
7024222ddf1SHong Zhang   ierr = (mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
7034222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
7044222ddf1SHong Zhang   PetscFunctionReturn(0);
7054222ddf1SHong Zhang }
7064222ddf1SHong Zhang 
7074222ddf1SHong Zhang /*@
7084222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
7094222ddf1SHong Zhang 
7104222ddf1SHong Zhang    Collective on Mat
7114222ddf1SHong Zhang 
7124222ddf1SHong Zhang    Input Parameters:
7134222ddf1SHong Zhang .  mat - the matrix to hold a product
7144222ddf1SHong Zhang 
7154222ddf1SHong Zhang    Output Parameters:
7164222ddf1SHong Zhang .  mat - the matrix product
7174222ddf1SHong Zhang 
7184222ddf1SHong Zhang    Level: intermediate
7194222ddf1SHong Zhang 
7204222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType()
7214222ddf1SHong Zhang @*/
7224222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
7234222ddf1SHong Zhang {
7244222ddf1SHong Zhang   PetscErrorCode ierr;
7254222ddf1SHong Zhang 
7264222ddf1SHong Zhang   PetscFunctionBegin;
7274222ddf1SHong Zhang   PetscValidPointer(mat,1);
7284222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7294222ddf1SHong Zhang 
7304222ddf1SHong Zhang   if (mat->ops->productnumeric) {
7314222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
7324222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSymbolic() first");
7334222ddf1SHong Zhang   PetscFunctionReturn(0);
7344222ddf1SHong Zhang }
7354222ddf1SHong Zhang 
7364222ddf1SHong Zhang /* ----------------------------------------------- */
7374222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
7384222ddf1SHong Zhang {
7394222ddf1SHong Zhang   PetscErrorCode ierr;
7404222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7414222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7424222ddf1SHong Zhang 
7434222ddf1SHong Zhang   PetscFunctionBegin;
7444222ddf1SHong Zhang   ierr = (mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7454222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
7464222ddf1SHong Zhang   PetscFunctionReturn(0);
7474222ddf1SHong Zhang }
7484222ddf1SHong Zhang 
7494222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
7504222ddf1SHong Zhang {
7514222ddf1SHong Zhang   PetscErrorCode ierr;
7524222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7534222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7544222ddf1SHong Zhang 
7554222ddf1SHong Zhang   PetscFunctionBegin;
7564222ddf1SHong Zhang   ierr = (mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7574222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
7584222ddf1SHong Zhang   PetscFunctionReturn(0);
7594222ddf1SHong Zhang }
7604222ddf1SHong Zhang 
7614222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
7624222ddf1SHong Zhang {
7634222ddf1SHong Zhang   PetscErrorCode ierr;
7644222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7654222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
7664222ddf1SHong Zhang 
7674222ddf1SHong Zhang   PetscFunctionBegin;
7684222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
7694222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
7704222ddf1SHong Zhang   PetscFunctionReturn(0);
7714222ddf1SHong Zhang }
7724222ddf1SHong Zhang 
7734222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
7744222ddf1SHong Zhang {
7754222ddf1SHong Zhang   PetscErrorCode ierr;
7764222ddf1SHong Zhang   Mat_Product    *product = mat->product;
7774222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
7784222ddf1SHong Zhang 
7794222ddf1SHong Zhang   PetscFunctionBegin;
7804222ddf1SHong Zhang   ierr = (mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
7814222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
7824222ddf1SHong Zhang   PetscFunctionReturn(0);
7834222ddf1SHong Zhang }
7844222ddf1SHong Zhang 
7854222ddf1SHong Zhang /*@
7864222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
7874222ddf1SHong Zhang 
7884222ddf1SHong Zhang    Collective on Mat
7894222ddf1SHong Zhang 
7904222ddf1SHong Zhang    Input Parameters:
7914222ddf1SHong Zhang .  mat - the matrix to hold a product
7924222ddf1SHong Zhang 
7934222ddf1SHong Zhang    Output Parameters:
7944222ddf1SHong Zhang .  mat - the matrix product data structure
7954222ddf1SHong Zhang 
7964222ddf1SHong Zhang    Level: intermediate
7974222ddf1SHong Zhang 
7984222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm
7994222ddf1SHong Zhang @*/
8004222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
8014222ddf1SHong Zhang {
8024222ddf1SHong Zhang   PetscErrorCode ierr;
8034222ddf1SHong Zhang   Mat_Product    *product = mat->product;
8044222ddf1SHong Zhang   MatProductType productype = product->type;
8054222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
8064222ddf1SHong Zhang 
8074222ddf1SHong Zhang   PetscFunctionBegin;
8084222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8094222ddf1SHong Zhang 
8104222ddf1SHong Zhang   /* log event */
8114222ddf1SHong Zhang   switch (productype) {
8124222ddf1SHong Zhang   case MATPRODUCT_AB:
8134222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
8144222ddf1SHong Zhang     break;
8154222ddf1SHong Zhang   case MATPRODUCT_AtB:
8164222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
8174222ddf1SHong Zhang     break;
8184222ddf1SHong Zhang   case MATPRODUCT_ABt:
8194222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
8204222ddf1SHong Zhang     break;
8214222ddf1SHong Zhang   case MATPRODUCT_PtAP:
8224222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
8234222ddf1SHong Zhang     break;
8244222ddf1SHong Zhang   case MATPRODUCT_RARt:
8254222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
8264222ddf1SHong Zhang     break;
8274222ddf1SHong Zhang   case MATPRODUCT_ABC:
8284222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
8294222ddf1SHong Zhang     break;
8304222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported");
8314222ddf1SHong Zhang   }
8324222ddf1SHong Zhang 
8334222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
8344222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
8354222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
8364222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
8374222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSetFromOptions() first");
8384222ddf1SHong Zhang   PetscFunctionReturn(0);
8394222ddf1SHong Zhang }
8404222ddf1SHong Zhang 
8414222ddf1SHong Zhang /*@
8424222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
8434222ddf1SHong Zhang 
8444222ddf1SHong Zhang    Collective on Mat
8454222ddf1SHong Zhang 
8464222ddf1SHong Zhang    Input Parameters:
8474222ddf1SHong Zhang +  mat - the matrix product
8484222ddf1SHong 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.
8494222ddf1SHong Zhang 
8504222ddf1SHong Zhang    Level: intermediate
8514222ddf1SHong Zhang 
8524222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
8534222ddf1SHong Zhang @*/
8544222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
8554222ddf1SHong Zhang {
8564222ddf1SHong Zhang   Mat_Product *product = mat->product;
8574222ddf1SHong Zhang 
8584222ddf1SHong Zhang   PetscFunctionBegin;
8594222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8604222ddf1SHong Zhang 
8614222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
8624222ddf1SHong Zhang   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) {
8634222ddf1SHong Zhang     product->fill = 2.0;
8644222ddf1SHong Zhang   } else product->fill = fill;
8654222ddf1SHong Zhang   PetscFunctionReturn(0);
8664222ddf1SHong Zhang }
8674222ddf1SHong Zhang 
8684222ddf1SHong Zhang /*@
8694222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
8704222ddf1SHong Zhang 
8714222ddf1SHong Zhang    Collective on Mat
8724222ddf1SHong Zhang 
8734222ddf1SHong Zhang    Input Parameters:
8744222ddf1SHong Zhang +  mat - the matrix product
8754222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
8764222ddf1SHong Zhang 
8774222ddf1SHong Zhang    Level: intermediate
8784222ddf1SHong Zhang 
8794222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate()
8804222ddf1SHong Zhang @*/
8814222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
8824222ddf1SHong Zhang {
8834222ddf1SHong Zhang   Mat_Product *product = mat->product;
8844222ddf1SHong Zhang 
8854222ddf1SHong Zhang   PetscFunctionBegin;
8864222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
8874222ddf1SHong Zhang 
8884222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
8894222ddf1SHong Zhang   product->alg = alg;
8904222ddf1SHong Zhang   PetscFunctionReturn(0);
8914222ddf1SHong Zhang }
8924222ddf1SHong Zhang 
8934222ddf1SHong Zhang /*@
8944222ddf1SHong Zhang    MatProductSetType - Sets a particular matrix product type, for example Mat*Mat.
8954222ddf1SHong Zhang 
8964222ddf1SHong Zhang    Collective on Mat
8974222ddf1SHong Zhang 
8984222ddf1SHong Zhang    Input Parameters:
8994222ddf1SHong Zhang +  mat - the matrix
9004222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
9014222ddf1SHong Zhang 
9024222ddf1SHong Zhang    Level: intermediate
9034222ddf1SHong Zhang 
9044222ddf1SHong Zhang .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm
9054222ddf1SHong Zhang @*/
9064222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
9074222ddf1SHong Zhang {
9084222ddf1SHong Zhang   PetscErrorCode ierr;
9094222ddf1SHong Zhang   Mat_Product    *product = mat->product;
9104222ddf1SHong Zhang   MPI_Comm       comm;
9114222ddf1SHong Zhang 
9124222ddf1SHong Zhang   PetscFunctionBegin;
9134222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
9144222ddf1SHong Zhang 
9154222ddf1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
9164222ddf1SHong Zhang   if (!product) SETERRQ(comm,PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
9174222ddf1SHong Zhang   product->type = productype;
9184222ddf1SHong Zhang 
9194222ddf1SHong Zhang   switch (productype) {
9204222ddf1SHong Zhang   case MATPRODUCT_AB:
9214222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AB;
9224222ddf1SHong Zhang     break;
9234222ddf1SHong Zhang   case MATPRODUCT_AtB:
9244222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB;
9254222ddf1SHong Zhang     break;
9264222ddf1SHong Zhang   case MATPRODUCT_ABt:
9274222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt;
9284222ddf1SHong Zhang     break;
9294222ddf1SHong Zhang   case MATPRODUCT_PtAP:
9304222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP;
9314222ddf1SHong Zhang     break;
9324222ddf1SHong Zhang   case MATPRODUCT_RARt:
9334222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt;
9344222ddf1SHong Zhang     break;
9354222ddf1SHong Zhang   case MATPRODUCT_ABC:
9364222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC;
9374222ddf1SHong Zhang     break;
938*544a5e07SHong Zhang   default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]);
9394222ddf1SHong Zhang   }
9404222ddf1SHong Zhang   PetscFunctionReturn(0);
9414222ddf1SHong Zhang }
9424222ddf1SHong Zhang 
9434417c5e8SHong Zhang /*@
9444417c5e8SHong Zhang    MatProductClear - Clears matrix product internal structure.
9454417c5e8SHong Zhang 
9464417c5e8SHong Zhang    Collective on Mat
9474417c5e8SHong Zhang 
9484417c5e8SHong Zhang    Input Parameters:
9494417c5e8SHong Zhang .  mat - the product matrix
9504417c5e8SHong Zhang 
9514417c5e8SHong Zhang    Level: intermediate
9524417c5e8SHong Zhang @*/
9534417c5e8SHong Zhang PetscErrorCode MatProductClear(Mat mat)
9544417c5e8SHong Zhang {
9554417c5e8SHong Zhang   PetscErrorCode ierr;
9564417c5e8SHong Zhang   Mat_Product    *product = mat->product;
9574417c5e8SHong Zhang 
9584417c5e8SHong Zhang   PetscFunctionBegin;
9594417c5e8SHong Zhang   if (product) {
9604417c5e8SHong Zhang     /* release reference */
9614417c5e8SHong Zhang     ierr = MatDestroy(&product->A);CHKERRQ(ierr);
9624417c5e8SHong Zhang     ierr = MatDestroy(&product->B);CHKERRQ(ierr);
9634417c5e8SHong Zhang     ierr = MatDestroy(&product->C);CHKERRQ(ierr);
9644417c5e8SHong Zhang     ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr);
9654417c5e8SHong Zhang     ierr = PetscFree(mat->product);CHKERRQ(ierr);
9664417c5e8SHong Zhang   }
9674417c5e8SHong Zhang   PetscFunctionReturn(0);
9684417c5e8SHong Zhang }
9694417c5e8SHong Zhang 
9704222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
9714417c5e8SHong Zhang PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
9724222ddf1SHong Zhang {
9734222ddf1SHong Zhang   PetscErrorCode ierr;
9744222ddf1SHong Zhang   Mat_Product    *product=NULL;
9754222ddf1SHong Zhang 
9764222ddf1SHong Zhang   PetscFunctionBegin;
9774222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
9784222ddf1SHong Zhang   product->A        = A;
9794222ddf1SHong Zhang   product->B        = B;
9804222ddf1SHong Zhang   product->C        = C;
9814222ddf1SHong Zhang   product->Dwork    = NULL;
9824222ddf1SHong Zhang   product->alg      = MATPRODUCTALGORITHM_DEFAULT;
9834222ddf1SHong Zhang   product->fill     = 2.0; /* PETSC_DEFAULT */
9844222ddf1SHong Zhang   product->Areplaced = PETSC_FALSE;
9854222ddf1SHong Zhang   product->Breplaced = PETSC_FALSE;
9864222ddf1SHong Zhang   product->api_user  = PETSC_FALSE;
9874222ddf1SHong Zhang   D->product         = product;
9884417c5e8SHong Zhang 
9894417c5e8SHong Zhang   /* take ownership */
9904417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
9914417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
9924417c5e8SHong Zhang   ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
9934222ddf1SHong Zhang   PetscFunctionReturn(0);
9944222ddf1SHong Zhang }
9954222ddf1SHong Zhang 
9964222ddf1SHong Zhang /*@
9974222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
9984222ddf1SHong Zhang 
9994222ddf1SHong Zhang    Collective on Mat
10004222ddf1SHong Zhang 
10014222ddf1SHong Zhang    Input Parameters:
10024222ddf1SHong Zhang +  A - the first matrix
10034222ddf1SHong Zhang .  B - the second matrix
10044222ddf1SHong Zhang .  C - the third matrix (optional)
10054222ddf1SHong Zhang -  D - the matrix which will be used as a product
10064222ddf1SHong Zhang 
10074222ddf1SHong Zhang    Output Parameters:
10084222ddf1SHong Zhang .  D - the product matrix
10094222ddf1SHong Zhang 
10104222ddf1SHong Zhang    Level: intermediate
10114222ddf1SHong Zhang 
10124222ddf1SHong Zhang .seealso: MatProductCreate()
10134222ddf1SHong Zhang @*/
10144222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
10154222ddf1SHong Zhang {
10164222ddf1SHong Zhang   PetscErrorCode ierr;
10174222ddf1SHong Zhang 
10184222ddf1SHong Zhang   PetscFunctionBegin;
10194222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10204222ddf1SHong Zhang   PetscValidType(A,1);
10214222ddf1SHong Zhang   MatCheckPreallocated(A,1);
10224222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10234222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10244222ddf1SHong Zhang 
10254222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10264222ddf1SHong Zhang   PetscValidType(B,2);
10274222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10284222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10294222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10304222ddf1SHong Zhang 
10314222ddf1SHong Zhang   if (C) {
10324222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10334222ddf1SHong Zhang     PetscValidType(C,3);
10344222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10354222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10364222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10374222ddf1SHong Zhang   }
10384222ddf1SHong Zhang 
10394222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
10404222ddf1SHong Zhang   PetscValidType(D,4);
10414222ddf1SHong Zhang   MatCheckPreallocated(D,4);
10424222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10434222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10444222ddf1SHong Zhang 
10454222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
10464222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
10474222ddf1SHong Zhang   PetscFunctionReturn(0);
10484222ddf1SHong Zhang }
10494222ddf1SHong Zhang 
10504222ddf1SHong Zhang /*@
10514222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
10524222ddf1SHong Zhang 
10534222ddf1SHong Zhang    Collective on Mat
10544222ddf1SHong Zhang 
10554222ddf1SHong Zhang    Input Parameters:
10564222ddf1SHong Zhang +  A - the first matrix
10574222ddf1SHong Zhang .  B - the second matrix
10584222ddf1SHong Zhang -  C - the third matrix (optional)
10594222ddf1SHong Zhang 
10604222ddf1SHong Zhang    Output Parameters:
10614222ddf1SHong Zhang .  D - the product matrix
10624222ddf1SHong Zhang 
10634222ddf1SHong Zhang    Level: intermediate
10644222ddf1SHong Zhang 
10654222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
10664222ddf1SHong Zhang @*/
10674222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
10684222ddf1SHong Zhang {
10694222ddf1SHong Zhang   PetscErrorCode ierr;
10704222ddf1SHong Zhang 
10714222ddf1SHong Zhang   PetscFunctionBegin;
10724222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
10734222ddf1SHong Zhang   PetscValidType(A,1);
10744222ddf1SHong Zhang   MatCheckPreallocated(A,1);
10754222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10764222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10774222ddf1SHong Zhang 
10784222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
10794222ddf1SHong Zhang   PetscValidType(B,2);
10804222ddf1SHong Zhang   MatCheckPreallocated(B,2);
10814222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10824222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10834222ddf1SHong Zhang 
10844222ddf1SHong Zhang   if (C) {
10854222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
10864222ddf1SHong Zhang     PetscValidType(C,3);
10874222ddf1SHong Zhang     MatCheckPreallocated(C,3);
10884222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
10894222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
10904222ddf1SHong Zhang   }
10914222ddf1SHong Zhang 
10924222ddf1SHong Zhang   PetscValidPointer(D,4);
10934222ddf1SHong Zhang 
10944222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
10954222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
10964222ddf1SHong Zhang   PetscFunctionReturn(0);
10974222ddf1SHong Zhang }
1098