xref: /petsc/src/mat/interface/matproduct.c (revision 4222ddf1d74c63827c599361b3bb0b06ad3944a0)
1*4222ddf1SHong Zhang 
2*4222ddf1SHong Zhang /*
3*4222ddf1SHong Zhang     Routines for matrix products. Calling procedure:
4*4222ddf1SHong Zhang 
5*4222ddf1SHong Zhang     MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D);
6*4222ddf1SHong Zhang     MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC);
7*4222ddf1SHong Zhang     MatProductSetAlgorithm(D, alg);
8*4222ddf1SHong Zhang     MatProductSetFill(D,fill);
9*4222ddf1SHong Zhang     MatProductSetFromOptions(D);
10*4222ddf1SHong Zhang       -> MatProductSetFromOptions_producttype(D):
11*4222ddf1SHong Zhang            # Check matrix global sizes
12*4222ddf1SHong Zhang            -> MatProductSetFromOptions_Atype_Btype_Ctype(D);
13*4222ddf1SHong Zhang                 ->MatProductSetFromOptions_Atype_Btype_Ctype_productype(D):
14*4222ddf1SHong Zhang                     # Check matrix local sizes for mpi matrices
15*4222ddf1SHong Zhang                     # Set default algorithm
16*4222ddf1SHong Zhang                     # Get runtime option
17*4222ddf1SHong Zhang                     # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype;
18*4222ddf1SHong Zhang 
19*4222ddf1SHong Zhang     PetscLogEventBegin()
20*4222ddf1SHong Zhang     MatProductSymbolic(D):
21*4222ddf1SHong Zhang       # Call MatxxxSymbolic_Atype_Btype_Ctype();
22*4222ddf1SHong Zhang       # Set D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype;
23*4222ddf1SHong Zhang     PetscLogEventEnd()
24*4222ddf1SHong Zhang 
25*4222ddf1SHong Zhang     PetscLogEventBegin()
26*4222ddf1SHong Zhang     MatProductNumeric(D);
27*4222ddf1SHong Zhang       # Call (D->ops->matxxxnumeric)();
28*4222ddf1SHong Zhang     PetscLogEventEnd()
29*4222ddf1SHong Zhang */
30*4222ddf1SHong Zhang 
31*4222ddf1SHong Zhang #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
32*4222ddf1SHong Zhang 
33*4222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C)
34*4222ddf1SHong Zhang {
35*4222ddf1SHong Zhang   PetscErrorCode ierr;
36*4222ddf1SHong Zhang   Mat_Product    *product = C->product;
37*4222ddf1SHong Zhang   Mat            P = product->B,AP = product->Dwork;
38*4222ddf1SHong Zhang 
39*4222ddf1SHong Zhang   PetscFunctionBegin;
40*4222ddf1SHong Zhang   /* AP = A*P */
41*4222ddf1SHong Zhang   ierr = MatProductNumeric(AP);CHKERRQ(ierr);
42*4222ddf1SHong Zhang   /* C = P^T*AP */
43*4222ddf1SHong Zhang   ierr = (C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr);
44*4222ddf1SHong Zhang   PetscFunctionReturn(0);
45*4222ddf1SHong Zhang }
46*4222ddf1SHong Zhang 
47*4222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C)
48*4222ddf1SHong Zhang {
49*4222ddf1SHong Zhang   PetscErrorCode ierr;
50*4222ddf1SHong Zhang   Mat_Product    *product = C->product;
51*4222ddf1SHong Zhang   Mat            A=product->A,P=product->B,AP;
52*4222ddf1SHong Zhang   PetscReal      fill=product->fill;
53*4222ddf1SHong Zhang 
54*4222ddf1SHong Zhang   PetscFunctionBegin;
55*4222ddf1SHong Zhang   /* AP = A*P */
56*4222ddf1SHong Zhang   ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr);
57*4222ddf1SHong Zhang   ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr);
58*4222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(AP,"default");CHKERRQ(ierr);
59*4222ddf1SHong Zhang   ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr);
60*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr);
61*4222ddf1SHong Zhang   ierr = MatProductSymbolic(AP);CHKERRQ(ierr);
62*4222ddf1SHong Zhang 
63*4222ddf1SHong Zhang   /* C = P^T*AP */
64*4222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr);
65*4222ddf1SHong Zhang   product->alg = "default";
66*4222ddf1SHong Zhang   product->A   = P;
67*4222ddf1SHong Zhang   product->B   = AP;
68*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
69*4222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
70*4222ddf1SHong Zhang 
71*4222ddf1SHong Zhang   /* resume user's original input matrix setting for A and B */
72*4222ddf1SHong Zhang   product->A     = A;
73*4222ddf1SHong Zhang   product->B     = P;
74*4222ddf1SHong Zhang   product->Dwork = AP;
75*4222ddf1SHong Zhang 
76*4222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP_Basic;
77*4222ddf1SHong Zhang   PetscFunctionReturn(0);
78*4222ddf1SHong Zhang }
79*4222ddf1SHong Zhang 
80*4222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C)
81*4222ddf1SHong Zhang {
82*4222ddf1SHong Zhang   PetscErrorCode ierr;
83*4222ddf1SHong Zhang   Mat_Product    *product = C->product;
84*4222ddf1SHong Zhang   Mat            R=product->B,RA=product->Dwork;
85*4222ddf1SHong Zhang 
86*4222ddf1SHong Zhang   PetscFunctionBegin;
87*4222ddf1SHong Zhang   /* RA = R*A */
88*4222ddf1SHong Zhang   ierr = MatProductNumeric(RA);CHKERRQ(ierr);
89*4222ddf1SHong Zhang   /* C = RA*R^T */
90*4222ddf1SHong Zhang   ierr = (C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr);
91*4222ddf1SHong Zhang   PetscFunctionReturn(0);
92*4222ddf1SHong Zhang }
93*4222ddf1SHong Zhang 
94*4222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C)
95*4222ddf1SHong Zhang {
96*4222ddf1SHong Zhang   PetscErrorCode ierr;
97*4222ddf1SHong Zhang   Mat_Product    *product = C->product;
98*4222ddf1SHong Zhang   Mat            A=product->A,R=product->B,RA;
99*4222ddf1SHong Zhang   PetscReal      fill=product->fill;
100*4222ddf1SHong Zhang 
101*4222ddf1SHong Zhang   PetscFunctionBegin;
102*4222ddf1SHong Zhang   /* RA = R*A */
103*4222ddf1SHong Zhang   ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr);
104*4222ddf1SHong Zhang   ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr);
105*4222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(RA,"default");CHKERRQ(ierr);
106*4222ddf1SHong Zhang   ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr);
107*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr);
108*4222ddf1SHong Zhang   ierr = MatProductSymbolic(RA);CHKERRQ(ierr);
109*4222ddf1SHong Zhang 
110*4222ddf1SHong Zhang   /* C = RA*R^T */
111*4222ddf1SHong Zhang   ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr);
112*4222ddf1SHong Zhang   product->alg  = "default";
113*4222ddf1SHong Zhang   product->A    = RA;
114*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(C);CHKERRQ(ierr);
115*4222ddf1SHong Zhang   ierr = MatProductSymbolic(C);CHKERRQ(ierr);
116*4222ddf1SHong Zhang 
117*4222ddf1SHong Zhang   /* resume user's original input matrix setting for A */
118*4222ddf1SHong Zhang   product->A     = A;
119*4222ddf1SHong Zhang   product->Dwork = RA; /* save here so it will be destroyed with product C */
120*4222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_RARt_Basic;
121*4222ddf1SHong Zhang   PetscFunctionReturn(0);
122*4222ddf1SHong Zhang }
123*4222ddf1SHong Zhang 
124*4222ddf1SHong Zhang static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat)
125*4222ddf1SHong Zhang {
126*4222ddf1SHong Zhang   PetscErrorCode ierr;
127*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
128*4222ddf1SHong Zhang   Mat            A=product->A,BC=product->Dwork;
129*4222ddf1SHong Zhang 
130*4222ddf1SHong Zhang   PetscFunctionBegin;
131*4222ddf1SHong Zhang   /* Numeric BC = B*C */
132*4222ddf1SHong Zhang   ierr = MatProductNumeric(BC);CHKERRQ(ierr);
133*4222ddf1SHong Zhang   /* Numeric mat = A*BC */
134*4222ddf1SHong Zhang   ierr = (mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr);
135*4222ddf1SHong Zhang   PetscFunctionReturn(0);
136*4222ddf1SHong Zhang }
137*4222ddf1SHong Zhang 
138*4222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat)
139*4222ddf1SHong Zhang {
140*4222ddf1SHong Zhang   PetscErrorCode ierr;
141*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
142*4222ddf1SHong Zhang   Mat            B=product->B,C=product->C,BC;
143*4222ddf1SHong Zhang   PetscReal      fill=product->fill;
144*4222ddf1SHong Zhang 
145*4222ddf1SHong Zhang   PetscFunctionBegin;
146*4222ddf1SHong Zhang   /* Symbolic BC = B*C */
147*4222ddf1SHong Zhang   ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr);
148*4222ddf1SHong Zhang   ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr);
149*4222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(BC,"default");CHKERRQ(ierr);
150*4222ddf1SHong Zhang   ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr);
151*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr);
152*4222ddf1SHong Zhang   ierr = MatProductSymbolic(BC);CHKERRQ(ierr);
153*4222ddf1SHong Zhang 
154*4222ddf1SHong Zhang   /* Symbolic mat = A*BC */
155*4222ddf1SHong Zhang   ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr);
156*4222ddf1SHong Zhang   product->alg   = "default";
157*4222ddf1SHong Zhang   product->B     = BC;
158*4222ddf1SHong Zhang   product->Dwork = BC;
159*4222ddf1SHong Zhang   ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr);
160*4222ddf1SHong Zhang   ierr = MatProductSymbolic(mat);CHKERRQ(ierr);
161*4222ddf1SHong Zhang 
162*4222ddf1SHong Zhang   /* resume user's original input matrix setting for B */
163*4222ddf1SHong Zhang   product->B = B;
164*4222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC_Basic;
165*4222ddf1SHong Zhang   PetscFunctionReturn(0);
166*4222ddf1SHong Zhang }
167*4222ddf1SHong Zhang 
168*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_Basic(Mat mat)
169*4222ddf1SHong Zhang {
170*4222ddf1SHong Zhang   PetscErrorCode ierr;
171*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
172*4222ddf1SHong Zhang 
173*4222ddf1SHong Zhang   PetscFunctionBegin;
174*4222ddf1SHong Zhang   switch (product->type) {
175*4222ddf1SHong Zhang   case MATPRODUCT_PtAP:
176*4222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProduct_Basic_PtAP() for A %s, P %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);
177*4222ddf1SHong Zhang     ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr);
178*4222ddf1SHong Zhang     break;
179*4222ddf1SHong Zhang   case MATPRODUCT_RARt:
180*4222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProduct_Basic_RARt() for A %s, R %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);
181*4222ddf1SHong Zhang     ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr);
182*4222ddf1SHong Zhang     break;
183*4222ddf1SHong Zhang   case MATPRODUCT_ABC:
184*4222ddf1SHong 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);
185*4222ddf1SHong Zhang     ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr);
186*4222ddf1SHong Zhang     break;
187*4222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported");
188*4222ddf1SHong Zhang   }
189*4222ddf1SHong Zhang   PetscFunctionReturn(0);
190*4222ddf1SHong Zhang }
191*4222ddf1SHong Zhang 
192*4222ddf1SHong Zhang /* ----------------------------------------------- */
193*4222ddf1SHong Zhang /*@C
194*4222ddf1SHong Zhang    MatProductReplaceMats - Replace input matrices for a matrix product.
195*4222ddf1SHong Zhang 
196*4222ddf1SHong Zhang    Collective on Mat
197*4222ddf1SHong Zhang 
198*4222ddf1SHong Zhang    Input Parameters:
199*4222ddf1SHong Zhang +  A - the matrix or NULL if not being replaced
200*4222ddf1SHong Zhang .  B - the matrix or NULL if not being replaced
201*4222ddf1SHong Zhang .  C - the matrix or NULL if not being replaced
202*4222ddf1SHong Zhang -  D - the matrix product
203*4222ddf1SHong Zhang 
204*4222ddf1SHong Zhang    Level: intermediate
205*4222ddf1SHong Zhang 
206*4222ddf1SHong Zhang    Notes:
207*4222ddf1SHong Zhang      Input matrix must have exactly same data structure as replaced one.
208*4222ddf1SHong Zhang 
209*4222ddf1SHong Zhang .seealso: MatProductCreate()
210*4222ddf1SHong Zhang @*/
211*4222ddf1SHong Zhang PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D)
212*4222ddf1SHong Zhang {
213*4222ddf1SHong Zhang   Mat_Product    *product=D->product;
214*4222ddf1SHong Zhang 
215*4222ddf1SHong Zhang   PetscFunctionBegin;
216*4222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_NULL,"Mat D does not have struct 'product'. Call MatProductReplaceProduct(). \n");
217*4222ddf1SHong Zhang   if (A) {
218*4222ddf1SHong Zhang     if (!product->Areplaced) {
219*4222ddf1SHong Zhang       product->A = A;
220*4222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix A was changed by a PETSc internal routine, cannot be replaced");
221*4222ddf1SHong Zhang   }
222*4222ddf1SHong Zhang   if (B) {
223*4222ddf1SHong Zhang     if (!product->Breplaced) {
224*4222ddf1SHong Zhang       product->B = B;
225*4222ddf1SHong Zhang     } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix B was changed by a PETSc internal routine, cannot be replaced");
226*4222ddf1SHong Zhang   }
227*4222ddf1SHong Zhang   if (C) product->C = C;
228*4222ddf1SHong Zhang   PetscFunctionReturn(0);
229*4222ddf1SHong Zhang }
230*4222ddf1SHong Zhang 
231*4222ddf1SHong Zhang /* ----------------------------------------------- */
232*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AB(Mat mat)
233*4222ddf1SHong Zhang {
234*4222ddf1SHong Zhang   PetscErrorCode ierr;
235*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
236*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
237*4222ddf1SHong Zhang   PetscBool      sametype;
238*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
239*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
240*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
241*4222ddf1SHong Zhang   PetscBool      A_istrans,B_istrans;
242*4222ddf1SHong Zhang 
243*4222ddf1SHong Zhang   PetscFunctionBegin;
244*4222ddf1SHong Zhang   /* Check matrix global sizes */
245*4222ddf1SHong 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);
246*4222ddf1SHong Zhang 
247*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
248*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
249*4222ddf1SHong Zhang 
250*4222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
251*4222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&A_istrans);CHKERRQ(ierr);
252*4222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&B_istrans);CHKERRQ(ierr);
253*4222ddf1SHong Zhang 
254*4222ddf1SHong Zhang   if (fB == fA && sametype && (!A_istrans || !B_istrans)) {
255*4222ddf1SHong Zhang     f = fB;
256*4222ddf1SHong Zhang   } else {
257*4222ddf1SHong Zhang     char      mtypes[256];
258*4222ddf1SHong Zhang     PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE;
259*4222ddf1SHong Zhang     Mat       At = NULL,Bt = NULL;
260*4222ddf1SHong Zhang 
261*4222ddf1SHong Zhang     if (A_istrans && !B_istrans) {
262*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
263*4222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
264*4222ddf1SHong Zhang       if (At_istrans) { /* mat = ATT * B */
265*4222ddf1SHong Zhang         Mat Att = NULL;
266*4222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
267*4222ddf1SHong Zhang         A                  = Att;
268*4222ddf1SHong Zhang         product->A         = Att; /* use Att for matproduct */
269*4222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */
270*4222ddf1SHong Zhang       } else { /* !At_istrans: mat = At^T*B */
271*4222ddf1SHong Zhang         A                  = At;
272*4222ddf1SHong Zhang         product->A         = At;
273*4222ddf1SHong Zhang         product->Areplaced = PETSC_TRUE;
274*4222ddf1SHong Zhang         product->type      = MATPRODUCT_AtB;
275*4222ddf1SHong Zhang       }
276*4222ddf1SHong Zhang     } else if (!A_istrans && B_istrans) {
277*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
278*4222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
279*4222ddf1SHong Zhang       if (Bt_istrans) { /* mat = A * BTT */
280*4222ddf1SHong Zhang         Mat Btt = NULL;
281*4222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
282*4222ddf1SHong Zhang         B                  = Btt;
283*4222ddf1SHong Zhang         product->B         = Btt; /* use Btt for matproduct */
284*4222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
285*4222ddf1SHong Zhang       } else { /* !Bt_istrans */
286*4222ddf1SHong Zhang         /* mat = A*Bt^T */
287*4222ddf1SHong Zhang         B                  = Bt;
288*4222ddf1SHong Zhang         product->B         = Bt;
289*4222ddf1SHong Zhang         product->Breplaced = PETSC_TRUE;
290*4222ddf1SHong Zhang         product->type = MATPRODUCT_ABt;
291*4222ddf1SHong Zhang       }
292*4222ddf1SHong Zhang     } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */
293*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr);
294*4222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr);
295*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr);
296*4222ddf1SHong Zhang       ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr);
297*4222ddf1SHong Zhang       if (At_istrans && Bt_istrans) {
298*4222ddf1SHong Zhang         Mat Att= NULL,Btt = NULL;
299*4222ddf1SHong Zhang         ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr);
300*4222ddf1SHong Zhang         ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr);
301*4222ddf1SHong Zhang         A             = Att;
302*4222ddf1SHong Zhang         product->A    = Att; product->Areplaced = PETSC_TRUE;
303*4222ddf1SHong Zhang         B             = Btt;
304*4222ddf1SHong Zhang         product->B    = Btt; product->Breplaced = PETSC_TRUE;
305*4222ddf1SHong Zhang       } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet");
306*4222ddf1SHong Zhang     }
307*4222ddf1SHong Zhang 
308*4222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
309*4222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
310*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
311*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
312*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
313*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
314*4222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
315*4222ddf1SHong Zhang     if (!f) {
316*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
317*4222ddf1SHong Zhang     }
318*4222ddf1SHong Zhang   }
319*4222ddf1SHong Zhang 
320*4222ddf1SHong 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);
321*4222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
322*4222ddf1SHong Zhang   PetscFunctionReturn(0);
323*4222ddf1SHong Zhang }
324*4222ddf1SHong Zhang 
325*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat)
326*4222ddf1SHong Zhang {
327*4222ddf1SHong Zhang   PetscErrorCode ierr;
328*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
329*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
330*4222ddf1SHong Zhang   PetscBool      sametype;
331*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
332*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
333*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
334*4222ddf1SHong Zhang 
335*4222ddf1SHong Zhang   PetscFunctionBegin;
336*4222ddf1SHong Zhang   /* Check matrix global sizes */
337*4222ddf1SHong 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);
338*4222ddf1SHong Zhang 
339*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
340*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
341*4222ddf1SHong Zhang 
342*4222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
343*4222ddf1SHong Zhang 
344*4222ddf1SHong Zhang   if (fB == fA && sametype) {
345*4222ddf1SHong Zhang     f = fB;
346*4222ddf1SHong Zhang   } else {
347*4222ddf1SHong Zhang     char      mtypes[256];
348*4222ddf1SHong Zhang     PetscBool istrans;
349*4222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
350*4222ddf1SHong Zhang     if (!istrans) {
351*4222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
352*4222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
353*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
354*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
355*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
356*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
357*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
358*4222ddf1SHong Zhang     } else {
359*4222ddf1SHong Zhang       Mat T = NULL;
360*4222ddf1SHong 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);
361*4222ddf1SHong Zhang 
362*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
363*4222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
364*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
365*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
366*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
367*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
368*4222ddf1SHong Zhang 
369*4222ddf1SHong Zhang       product->type = MATPRODUCT_AtB;
370*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
371*4222ddf1SHong Zhang     }
372*4222ddf1SHong Zhang 
373*4222ddf1SHong Zhang     if (!f) {
374*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
375*4222ddf1SHong Zhang     }
376*4222ddf1SHong Zhang   }
377*4222ddf1SHong 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);
378*4222ddf1SHong Zhang 
379*4222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
380*4222ddf1SHong Zhang   PetscFunctionReturn(0);
381*4222ddf1SHong Zhang }
382*4222ddf1SHong Zhang 
383*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat)
384*4222ddf1SHong Zhang {
385*4222ddf1SHong Zhang   PetscErrorCode ierr;
386*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
387*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
388*4222ddf1SHong Zhang   PetscBool      sametype;
389*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
390*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
391*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
392*4222ddf1SHong Zhang 
393*4222ddf1SHong Zhang   PetscFunctionBegin;
394*4222ddf1SHong Zhang   /* Check matrix global sizes */
395*4222ddf1SHong 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);
396*4222ddf1SHong Zhang 
397*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
398*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
399*4222ddf1SHong Zhang 
400*4222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
401*4222ddf1SHong Zhang 
402*4222ddf1SHong Zhang   if (fB == fA && sametype) {
403*4222ddf1SHong Zhang     f = fB;
404*4222ddf1SHong Zhang   } else {
405*4222ddf1SHong Zhang     char      mtypes[256];
406*4222ddf1SHong Zhang     PetscBool istrans;
407*4222ddf1SHong Zhang     ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr);
408*4222ddf1SHong Zhang     if (!istrans) {
409*4222ddf1SHong Zhang       /* query MatProductSetFromOptions_Atype_Btype */
410*4222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
411*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
412*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
413*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
414*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
415*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
416*4222ddf1SHong Zhang     } else {
417*4222ddf1SHong Zhang       Mat T = NULL;
418*4222ddf1SHong 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);
419*4222ddf1SHong Zhang 
420*4222ddf1SHong Zhang       ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr);
421*4222ddf1SHong Zhang       ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
422*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr);
423*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
424*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
425*4222ddf1SHong Zhang       ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
426*4222ddf1SHong Zhang 
427*4222ddf1SHong Zhang       product->type = MATPRODUCT_ABt;
428*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
429*4222ddf1SHong Zhang     }
430*4222ddf1SHong Zhang 
431*4222ddf1SHong Zhang     if (!f) {
432*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
433*4222ddf1SHong Zhang     }
434*4222ddf1SHong Zhang   }
435*4222ddf1SHong Zhang   if (!f) {
436*4222ddf1SHong 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);
437*4222ddf1SHong Zhang   }
438*4222ddf1SHong Zhang 
439*4222ddf1SHong Zhang   ierr = (*f)(mat);CHKERRQ(ierr);
440*4222ddf1SHong Zhang   PetscFunctionReturn(0);
441*4222ddf1SHong Zhang }
442*4222ddf1SHong Zhang 
443*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat)
444*4222ddf1SHong Zhang {
445*4222ddf1SHong Zhang   PetscErrorCode ierr;
446*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
447*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
448*4222ddf1SHong Zhang   PetscBool      sametype;
449*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
450*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
451*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
452*4222ddf1SHong Zhang 
453*4222ddf1SHong Zhang   PetscFunctionBegin;
454*4222ddf1SHong Zhang   /* Check matrix global sizes */
455*4222ddf1SHong 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);
456*4222ddf1SHong 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);
457*4222ddf1SHong Zhang 
458*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
459*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
460*4222ddf1SHong Zhang 
461*4222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
462*4222ddf1SHong Zhang   if (fB == fA && sametype) {
463*4222ddf1SHong Zhang     f = fB;
464*4222ddf1SHong Zhang   } else {
465*4222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
466*4222ddf1SHong Zhang     char  mtypes[256];
467*4222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
468*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
469*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
470*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
471*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
472*4222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
473*4222ddf1SHong Zhang 
474*4222ddf1SHong Zhang     if (!f) {
475*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
476*4222ddf1SHong Zhang     }
477*4222ddf1SHong Zhang   }
478*4222ddf1SHong Zhang 
479*4222ddf1SHong Zhang   if (f) {
480*4222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
481*4222ddf1SHong Zhang   } else {
482*4222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
483*4222ddf1SHong Zhang     PetscInfo2((PetscObject)mat, "MatProductSetFromOptions_PtAP for A %s, P %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name);
484*4222ddf1SHong Zhang   }
485*4222ddf1SHong Zhang   PetscFunctionReturn(0);
486*4222ddf1SHong Zhang }
487*4222ddf1SHong Zhang 
488*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat)
489*4222ddf1SHong Zhang {
490*4222ddf1SHong Zhang   PetscErrorCode ierr;
491*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
492*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
493*4222ddf1SHong Zhang   PetscBool      sametype;
494*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
495*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
496*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
497*4222ddf1SHong Zhang 
498*4222ddf1SHong Zhang   PetscFunctionBegin;
499*4222ddf1SHong Zhang   /* Check matrix global sizes */
500*4222ddf1SHong 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);
501*4222ddf1SHong 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);
502*4222ddf1SHong Zhang 
503*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
504*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
505*4222ddf1SHong Zhang 
506*4222ddf1SHong Zhang   ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr);
507*4222ddf1SHong Zhang   if (fB == fA && sametype) {
508*4222ddf1SHong Zhang     f = fB;
509*4222ddf1SHong Zhang   } else {
510*4222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype */
511*4222ddf1SHong Zhang     char  mtypes[256];
512*4222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
513*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
514*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
515*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
516*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
517*4222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
518*4222ddf1SHong Zhang 
519*4222ddf1SHong Zhang     if (!f) {
520*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
521*4222ddf1SHong Zhang     }
522*4222ddf1SHong Zhang   }
523*4222ddf1SHong Zhang 
524*4222ddf1SHong Zhang   if (f) {
525*4222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
526*4222ddf1SHong Zhang   } else {
527*4222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
528*4222ddf1SHong Zhang   }
529*4222ddf1SHong Zhang   PetscFunctionReturn(0);
530*4222ddf1SHong Zhang }
531*4222ddf1SHong Zhang 
532*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat)
533*4222ddf1SHong Zhang {
534*4222ddf1SHong Zhang   PetscErrorCode ierr;
535*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
536*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
537*4222ddf1SHong Zhang   PetscErrorCode (*fA)(Mat);
538*4222ddf1SHong Zhang   PetscErrorCode (*fB)(Mat);
539*4222ddf1SHong Zhang   PetscErrorCode (*fC)(Mat);
540*4222ddf1SHong Zhang   PetscErrorCode (*f)(Mat)=NULL;
541*4222ddf1SHong Zhang 
542*4222ddf1SHong Zhang   PetscFunctionBegin;
543*4222ddf1SHong Zhang   /* Check matrix global sizes */
544*4222ddf1SHong 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);
545*4222ddf1SHong 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);
546*4222ddf1SHong Zhang 
547*4222ddf1SHong Zhang   fA = A->ops->productsetfromoptions;
548*4222ddf1SHong Zhang   fB = B->ops->productsetfromoptions;
549*4222ddf1SHong Zhang   fC = C->ops->productsetfromoptions;
550*4222ddf1SHong Zhang   if (fA == fB && fA == fC && fA) {
551*4222ddf1SHong Zhang     f = fA;
552*4222ddf1SHong Zhang   } else {
553*4222ddf1SHong Zhang     /* query MatProductSetFromOptions_Atype_Btype_Ctype */
554*4222ddf1SHong Zhang     char  mtypes[256];
555*4222ddf1SHong Zhang     ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr);
556*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr);
557*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
558*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr);
559*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr);
560*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr);
561*4222ddf1SHong Zhang     ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr);
562*4222ddf1SHong Zhang 
563*4222ddf1SHong Zhang     ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr);
564*4222ddf1SHong Zhang     if (!f) {
565*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr);
566*4222ddf1SHong Zhang     }
567*4222ddf1SHong Zhang     if (!f) {
568*4222ddf1SHong Zhang       ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr);
569*4222ddf1SHong Zhang     }
570*4222ddf1SHong Zhang   }
571*4222ddf1SHong Zhang 
572*4222ddf1SHong Zhang   if (f) {
573*4222ddf1SHong Zhang     ierr = (*f)(mat);CHKERRQ(ierr);
574*4222ddf1SHong Zhang   } else { /* use MatProductSymbolic/Numeric_Basic() */
575*4222ddf1SHong Zhang     mat->ops->productsymbolic = MatProductSymbolic_Basic;
576*4222ddf1SHong Zhang   }
577*4222ddf1SHong Zhang   PetscFunctionReturn(0);
578*4222ddf1SHong Zhang }
579*4222ddf1SHong Zhang 
580*4222ddf1SHong Zhang /*@C
581*4222ddf1SHong Zhang    MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database.
582*4222ddf1SHong Zhang 
583*4222ddf1SHong Zhang    Logically Collective on Mat
584*4222ddf1SHong Zhang 
585*4222ddf1SHong Zhang    Input Parameter:
586*4222ddf1SHong Zhang .  mat - the matrix
587*4222ddf1SHong Zhang 
588*4222ddf1SHong Zhang    Level: beginner
589*4222ddf1SHong Zhang 
590*4222ddf1SHong Zhang .seealso: MatSetFromOptions()
591*4222ddf1SHong Zhang @*/
592*4222ddf1SHong Zhang PetscErrorCode MatProductSetFromOptions(Mat mat)
593*4222ddf1SHong Zhang {
594*4222ddf1SHong Zhang   PetscErrorCode ierr;
595*4222ddf1SHong Zhang 
596*4222ddf1SHong Zhang   PetscFunctionBegin;
597*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
598*4222ddf1SHong Zhang 
599*4222ddf1SHong Zhang   if (mat->ops->productsetfromoptions) {
600*4222ddf1SHong Zhang     ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr);
601*4222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Call MatProductSetType() first");
602*4222ddf1SHong Zhang   PetscFunctionReturn(0);
603*4222ddf1SHong Zhang }
604*4222ddf1SHong Zhang 
605*4222ddf1SHong Zhang /* ----------------------------------------------- */
606*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AB(Mat mat)
607*4222ddf1SHong Zhang {
608*4222ddf1SHong Zhang   PetscErrorCode ierr;
609*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
610*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
611*4222ddf1SHong Zhang 
612*4222ddf1SHong Zhang   PetscFunctionBegin;
613*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
614*4222ddf1SHong Zhang   ierr = (mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr);
615*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
616*4222ddf1SHong Zhang   PetscFunctionReturn(0);
617*4222ddf1SHong Zhang }
618*4222ddf1SHong Zhang 
619*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_AtB(Mat mat)
620*4222ddf1SHong Zhang {
621*4222ddf1SHong Zhang   PetscErrorCode ierr;
622*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
623*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
624*4222ddf1SHong Zhang 
625*4222ddf1SHong Zhang   PetscFunctionBegin;
626*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
627*4222ddf1SHong Zhang   ierr = (mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr);
628*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
629*4222ddf1SHong Zhang   PetscFunctionReturn(0);
630*4222ddf1SHong Zhang }
631*4222ddf1SHong Zhang 
632*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABt(Mat mat)
633*4222ddf1SHong Zhang {
634*4222ddf1SHong Zhang   PetscErrorCode ierr;
635*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
636*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
637*4222ddf1SHong Zhang 
638*4222ddf1SHong Zhang   PetscFunctionBegin;
639*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
640*4222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr);
641*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
642*4222ddf1SHong Zhang   PetscFunctionReturn(0);
643*4222ddf1SHong Zhang }
644*4222ddf1SHong Zhang 
645*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_PtAP(Mat mat)
646*4222ddf1SHong Zhang {
647*4222ddf1SHong Zhang   PetscErrorCode ierr;
648*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
649*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
650*4222ddf1SHong Zhang 
651*4222ddf1SHong Zhang   PetscFunctionBegin;
652*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
653*4222ddf1SHong Zhang   ierr = (mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr);
654*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr);
655*4222ddf1SHong Zhang   PetscFunctionReturn(0);
656*4222ddf1SHong Zhang }
657*4222ddf1SHong Zhang 
658*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_RARt(Mat mat)
659*4222ddf1SHong Zhang {
660*4222ddf1SHong Zhang   PetscErrorCode ierr;
661*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
662*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
663*4222ddf1SHong Zhang 
664*4222ddf1SHong Zhang   PetscFunctionBegin;
665*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
666*4222ddf1SHong Zhang   ierr = (mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr);
667*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr);
668*4222ddf1SHong Zhang   PetscFunctionReturn(0);
669*4222ddf1SHong Zhang }
670*4222ddf1SHong Zhang 
671*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric_ABC(Mat mat)
672*4222ddf1SHong Zhang {
673*4222ddf1SHong Zhang   PetscErrorCode ierr;
674*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
675*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
676*4222ddf1SHong Zhang 
677*4222ddf1SHong Zhang   PetscFunctionBegin;
678*4222ddf1SHong Zhang   ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
679*4222ddf1SHong Zhang   ierr = (mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr);
680*4222ddf1SHong Zhang   ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr);
681*4222ddf1SHong Zhang   PetscFunctionReturn(0);
682*4222ddf1SHong Zhang }
683*4222ddf1SHong Zhang 
684*4222ddf1SHong Zhang /*@
685*4222ddf1SHong Zhang    MatProductNumeric - Implement a matrix product with numerical values.
686*4222ddf1SHong Zhang 
687*4222ddf1SHong Zhang    Collective on Mat
688*4222ddf1SHong Zhang 
689*4222ddf1SHong Zhang    Input Parameters:
690*4222ddf1SHong Zhang .  mat - the matrix to hold a product
691*4222ddf1SHong Zhang 
692*4222ddf1SHong Zhang    Output Parameters:
693*4222ddf1SHong Zhang .  mat - the matrix product
694*4222ddf1SHong Zhang 
695*4222ddf1SHong Zhang    Level: intermediate
696*4222ddf1SHong Zhang 
697*4222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType()
698*4222ddf1SHong Zhang @*/
699*4222ddf1SHong Zhang PetscErrorCode MatProductNumeric(Mat mat)
700*4222ddf1SHong Zhang {
701*4222ddf1SHong Zhang   PetscErrorCode ierr;
702*4222ddf1SHong Zhang 
703*4222ddf1SHong Zhang   PetscFunctionBegin;
704*4222ddf1SHong Zhang   PetscValidPointer(mat,1);
705*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
706*4222ddf1SHong Zhang 
707*4222ddf1SHong Zhang   if (mat->ops->productnumeric) {
708*4222ddf1SHong Zhang     ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr);
709*4222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSymbolic() first");
710*4222ddf1SHong Zhang   PetscFunctionReturn(0);
711*4222ddf1SHong Zhang }
712*4222ddf1SHong Zhang 
713*4222ddf1SHong Zhang /* ----------------------------------------------- */
714*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AB(Mat mat)
715*4222ddf1SHong Zhang {
716*4222ddf1SHong Zhang   PetscErrorCode ierr;
717*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
718*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
719*4222ddf1SHong Zhang 
720*4222ddf1SHong Zhang   PetscFunctionBegin;
721*4222ddf1SHong Zhang   ierr = (mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
722*4222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AB;
723*4222ddf1SHong Zhang   PetscFunctionReturn(0);
724*4222ddf1SHong Zhang }
725*4222ddf1SHong Zhang 
726*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_AtB(Mat mat)
727*4222ddf1SHong Zhang {
728*4222ddf1SHong Zhang   PetscErrorCode ierr;
729*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
730*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
731*4222ddf1SHong Zhang 
732*4222ddf1SHong Zhang   PetscFunctionBegin;
733*4222ddf1SHong Zhang   ierr = (mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
734*4222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_AtB;
735*4222ddf1SHong Zhang   PetscFunctionReturn(0);
736*4222ddf1SHong Zhang }
737*4222ddf1SHong Zhang 
738*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABt(Mat mat)
739*4222ddf1SHong Zhang {
740*4222ddf1SHong Zhang   PetscErrorCode ierr;
741*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
742*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B;
743*4222ddf1SHong Zhang 
744*4222ddf1SHong Zhang   PetscFunctionBegin;
745*4222ddf1SHong Zhang   ierr = (mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr);
746*4222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABt;
747*4222ddf1SHong Zhang   PetscFunctionReturn(0);
748*4222ddf1SHong Zhang }
749*4222ddf1SHong Zhang 
750*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic_ABC(Mat mat)
751*4222ddf1SHong Zhang {
752*4222ddf1SHong Zhang   PetscErrorCode ierr;
753*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
754*4222ddf1SHong Zhang   Mat            A=product->A,B=product->B,C=product->C;
755*4222ddf1SHong Zhang 
756*4222ddf1SHong Zhang   PetscFunctionBegin;
757*4222ddf1SHong Zhang   ierr = (mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr);
758*4222ddf1SHong Zhang   mat->ops->productnumeric = MatProductNumeric_ABC;
759*4222ddf1SHong Zhang   PetscFunctionReturn(0);
760*4222ddf1SHong Zhang }
761*4222ddf1SHong Zhang 
762*4222ddf1SHong Zhang /*@
763*4222ddf1SHong Zhang    MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce.
764*4222ddf1SHong Zhang 
765*4222ddf1SHong Zhang    Collective on Mat
766*4222ddf1SHong Zhang 
767*4222ddf1SHong Zhang    Input Parameters:
768*4222ddf1SHong Zhang .  mat - the matrix to hold a product
769*4222ddf1SHong Zhang 
770*4222ddf1SHong Zhang    Output Parameters:
771*4222ddf1SHong Zhang .  mat - the matrix product data structure
772*4222ddf1SHong Zhang 
773*4222ddf1SHong Zhang    Level: intermediate
774*4222ddf1SHong Zhang 
775*4222ddf1SHong Zhang .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm
776*4222ddf1SHong Zhang @*/
777*4222ddf1SHong Zhang PetscErrorCode MatProductSymbolic(Mat mat)
778*4222ddf1SHong Zhang {
779*4222ddf1SHong Zhang   PetscErrorCode ierr;
780*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
781*4222ddf1SHong Zhang   MatProductType productype = product->type;
782*4222ddf1SHong Zhang   PetscLogEvent  eventtype=-1;
783*4222ddf1SHong Zhang 
784*4222ddf1SHong Zhang   PetscFunctionBegin;
785*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
786*4222ddf1SHong Zhang 
787*4222ddf1SHong Zhang   /* log event */
788*4222ddf1SHong Zhang   switch (productype) {
789*4222ddf1SHong Zhang   case MATPRODUCT_AB:
790*4222ddf1SHong Zhang     eventtype = MAT_MatMultSymbolic;
791*4222ddf1SHong Zhang     break;
792*4222ddf1SHong Zhang   case MATPRODUCT_AtB:
793*4222ddf1SHong Zhang     eventtype = MAT_TransposeMatMultSymbolic;
794*4222ddf1SHong Zhang     break;
795*4222ddf1SHong Zhang   case MATPRODUCT_ABt:
796*4222ddf1SHong Zhang     eventtype = MAT_MatTransposeMultSymbolic;
797*4222ddf1SHong Zhang     break;
798*4222ddf1SHong Zhang   case MATPRODUCT_PtAP:
799*4222ddf1SHong Zhang     eventtype = MAT_PtAPSymbolic;
800*4222ddf1SHong Zhang     break;
801*4222ddf1SHong Zhang   case MATPRODUCT_RARt:
802*4222ddf1SHong Zhang     eventtype = MAT_RARtSymbolic;
803*4222ddf1SHong Zhang     break;
804*4222ddf1SHong Zhang   case MATPRODUCT_ABC:
805*4222ddf1SHong Zhang     eventtype = MAT_MatMatMultSymbolic;
806*4222ddf1SHong Zhang     break;
807*4222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported");
808*4222ddf1SHong Zhang   }
809*4222ddf1SHong Zhang 
810*4222ddf1SHong Zhang   if (mat->ops->productsymbolic) {
811*4222ddf1SHong Zhang     ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr);
812*4222ddf1SHong Zhang     ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr);
813*4222ddf1SHong Zhang     ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr);
814*4222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSetFromOptions() first");
815*4222ddf1SHong Zhang   PetscFunctionReturn(0);
816*4222ddf1SHong Zhang }
817*4222ddf1SHong Zhang 
818*4222ddf1SHong Zhang /*@
819*4222ddf1SHong Zhang    MatProductSetFill - Set an expected fill of the matrix product.
820*4222ddf1SHong Zhang 
821*4222ddf1SHong Zhang    Collective on Mat
822*4222ddf1SHong Zhang 
823*4222ddf1SHong Zhang    Input Parameters:
824*4222ddf1SHong Zhang +  mat - the matrix product
825*4222ddf1SHong 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.
826*4222ddf1SHong Zhang 
827*4222ddf1SHong Zhang    Level: intermediate
828*4222ddf1SHong Zhang 
829*4222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate()
830*4222ddf1SHong Zhang @*/
831*4222ddf1SHong Zhang PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill)
832*4222ddf1SHong Zhang {
833*4222ddf1SHong Zhang   Mat_Product *product = mat->product;
834*4222ddf1SHong Zhang 
835*4222ddf1SHong Zhang   PetscFunctionBegin;
836*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
837*4222ddf1SHong Zhang 
838*4222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
839*4222ddf1SHong Zhang   if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) {
840*4222ddf1SHong Zhang     product->fill = 2.0;
841*4222ddf1SHong Zhang   } else product->fill = fill;
842*4222ddf1SHong Zhang   PetscFunctionReturn(0);
843*4222ddf1SHong Zhang }
844*4222ddf1SHong Zhang 
845*4222ddf1SHong Zhang /*@
846*4222ddf1SHong Zhang    MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation.
847*4222ddf1SHong Zhang 
848*4222ddf1SHong Zhang    Collective on Mat
849*4222ddf1SHong Zhang 
850*4222ddf1SHong Zhang    Input Parameters:
851*4222ddf1SHong Zhang +  mat - the matrix product
852*4222ddf1SHong Zhang -  alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT.
853*4222ddf1SHong Zhang 
854*4222ddf1SHong Zhang    Level: intermediate
855*4222ddf1SHong Zhang 
856*4222ddf1SHong Zhang .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate()
857*4222ddf1SHong Zhang @*/
858*4222ddf1SHong Zhang PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg)
859*4222ddf1SHong Zhang {
860*4222ddf1SHong Zhang   Mat_Product *product = mat->product;
861*4222ddf1SHong Zhang 
862*4222ddf1SHong Zhang   PetscFunctionBegin;
863*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
864*4222ddf1SHong Zhang 
865*4222ddf1SHong Zhang   if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
866*4222ddf1SHong Zhang   product->alg = alg;
867*4222ddf1SHong Zhang   PetscFunctionReturn(0);
868*4222ddf1SHong Zhang }
869*4222ddf1SHong Zhang 
870*4222ddf1SHong Zhang /*@
871*4222ddf1SHong Zhang    MatProductSetType - Sets a particular matrix product type, for example Mat*Mat.
872*4222ddf1SHong Zhang 
873*4222ddf1SHong Zhang    Collective on Mat
874*4222ddf1SHong Zhang 
875*4222ddf1SHong Zhang    Input Parameters:
876*4222ddf1SHong Zhang +  mat - the matrix
877*4222ddf1SHong Zhang -  productype   - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC.
878*4222ddf1SHong Zhang 
879*4222ddf1SHong Zhang    Level: intermediate
880*4222ddf1SHong Zhang 
881*4222ddf1SHong Zhang .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm
882*4222ddf1SHong Zhang @*/
883*4222ddf1SHong Zhang PetscErrorCode MatProductSetType(Mat mat,MatProductType productype)
884*4222ddf1SHong Zhang {
885*4222ddf1SHong Zhang   PetscErrorCode ierr;
886*4222ddf1SHong Zhang   Mat_Product    *product = mat->product;
887*4222ddf1SHong Zhang   MPI_Comm       comm;
888*4222ddf1SHong Zhang 
889*4222ddf1SHong Zhang   PetscFunctionBegin;
890*4222ddf1SHong Zhang   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
891*4222ddf1SHong Zhang 
892*4222ddf1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
893*4222ddf1SHong Zhang   if (!product) SETERRQ(comm,PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first");
894*4222ddf1SHong Zhang   product->type = productype;
895*4222ddf1SHong Zhang 
896*4222ddf1SHong Zhang   switch (productype) {
897*4222ddf1SHong Zhang   case MATPRODUCT_AB:
898*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AB;
899*4222ddf1SHong Zhang     break;
900*4222ddf1SHong Zhang   case MATPRODUCT_AtB:
901*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB;
902*4222ddf1SHong Zhang     break;
903*4222ddf1SHong Zhang   case MATPRODUCT_ABt:
904*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt;
905*4222ddf1SHong Zhang     break;
906*4222ddf1SHong Zhang   case MATPRODUCT_PtAP:
907*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP;
908*4222ddf1SHong Zhang     break;
909*4222ddf1SHong Zhang   case MATPRODUCT_RARt:
910*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt;
911*4222ddf1SHong Zhang     break;
912*4222ddf1SHong Zhang   case MATPRODUCT_ABC:
913*4222ddf1SHong Zhang     mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC;
914*4222ddf1SHong Zhang     break;
915*4222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported\n");
916*4222ddf1SHong Zhang   }
917*4222ddf1SHong Zhang   PetscFunctionReturn(0);
918*4222ddf1SHong Zhang }
919*4222ddf1SHong Zhang 
920*4222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */
921*4222ddf1SHong Zhang static PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D)
922*4222ddf1SHong Zhang {
923*4222ddf1SHong Zhang   PetscErrorCode ierr;
924*4222ddf1SHong Zhang   Mat_Product    *product=NULL;
925*4222ddf1SHong Zhang 
926*4222ddf1SHong Zhang   PetscFunctionBegin;
927*4222ddf1SHong Zhang   ierr = PetscNewLog(D,&product);CHKERRQ(ierr);
928*4222ddf1SHong Zhang   product->A        = A;
929*4222ddf1SHong Zhang   product->B        = B;
930*4222ddf1SHong Zhang   product->C        = C;
931*4222ddf1SHong Zhang   product->Dwork    = NULL;
932*4222ddf1SHong Zhang   product->alg      = MATPRODUCTALGORITHM_DEFAULT;
933*4222ddf1SHong Zhang   product->fill     = 2.0; /* PETSC_DEFAULT */
934*4222ddf1SHong Zhang   product->Areplaced = PETSC_FALSE;
935*4222ddf1SHong Zhang   product->Breplaced = PETSC_FALSE;
936*4222ddf1SHong Zhang   product->api_user  = PETSC_FALSE;
937*4222ddf1SHong Zhang   D->product         = product;
938*4222ddf1SHong Zhang   PetscFunctionReturn(0);
939*4222ddf1SHong Zhang }
940*4222ddf1SHong Zhang 
941*4222ddf1SHong Zhang /*@
942*4222ddf1SHong Zhang    MatProductCreateWithMat - Setup a given matrix as a matrix product.
943*4222ddf1SHong Zhang 
944*4222ddf1SHong Zhang    Collective on Mat
945*4222ddf1SHong Zhang 
946*4222ddf1SHong Zhang    Input Parameters:
947*4222ddf1SHong Zhang +  A - the first matrix
948*4222ddf1SHong Zhang .  B - the second matrix
949*4222ddf1SHong Zhang .  C - the third matrix (optional)
950*4222ddf1SHong Zhang -  D - the matrix which will be used as a product
951*4222ddf1SHong Zhang 
952*4222ddf1SHong Zhang    Output Parameters:
953*4222ddf1SHong Zhang .  D - the product matrix
954*4222ddf1SHong Zhang 
955*4222ddf1SHong Zhang    Level: intermediate
956*4222ddf1SHong Zhang 
957*4222ddf1SHong Zhang .seealso: MatProductCreate()
958*4222ddf1SHong Zhang @*/
959*4222ddf1SHong Zhang PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D)
960*4222ddf1SHong Zhang {
961*4222ddf1SHong Zhang   PetscErrorCode ierr;
962*4222ddf1SHong Zhang 
963*4222ddf1SHong Zhang   PetscFunctionBegin;
964*4222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
965*4222ddf1SHong Zhang   PetscValidType(A,1);
966*4222ddf1SHong Zhang   MatCheckPreallocated(A,1);
967*4222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
968*4222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
969*4222ddf1SHong Zhang 
970*4222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
971*4222ddf1SHong Zhang   PetscValidType(B,2);
972*4222ddf1SHong Zhang   MatCheckPreallocated(B,2);
973*4222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
974*4222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
975*4222ddf1SHong Zhang 
976*4222ddf1SHong Zhang   if (C) {
977*4222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
978*4222ddf1SHong Zhang     PetscValidType(C,3);
979*4222ddf1SHong Zhang     MatCheckPreallocated(C,3);
980*4222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
981*4222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
982*4222ddf1SHong Zhang   }
983*4222ddf1SHong Zhang 
984*4222ddf1SHong Zhang   PetscValidHeaderSpecific(D,MAT_CLASSID,4);
985*4222ddf1SHong Zhang   PetscValidType(D,4);
986*4222ddf1SHong Zhang   MatCheckPreallocated(D,4);
987*4222ddf1SHong Zhang   if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
988*4222ddf1SHong Zhang   if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
989*4222ddf1SHong Zhang 
990*4222ddf1SHong Zhang   /* Create a supporting struct and attach it to D */
991*4222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr);
992*4222ddf1SHong Zhang   PetscFunctionReturn(0);
993*4222ddf1SHong Zhang }
994*4222ddf1SHong Zhang 
995*4222ddf1SHong Zhang /*@
996*4222ddf1SHong Zhang    MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations.
997*4222ddf1SHong Zhang 
998*4222ddf1SHong Zhang    Collective on Mat
999*4222ddf1SHong Zhang 
1000*4222ddf1SHong Zhang    Input Parameters:
1001*4222ddf1SHong Zhang +  A - the first matrix
1002*4222ddf1SHong Zhang .  B - the second matrix
1003*4222ddf1SHong Zhang -  C - the third matrix (optional)
1004*4222ddf1SHong Zhang 
1005*4222ddf1SHong Zhang    Output Parameters:
1006*4222ddf1SHong Zhang .  D - the product matrix
1007*4222ddf1SHong Zhang 
1008*4222ddf1SHong Zhang    Level: intermediate
1009*4222ddf1SHong Zhang 
1010*4222ddf1SHong Zhang .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm()
1011*4222ddf1SHong Zhang @*/
1012*4222ddf1SHong Zhang PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D)
1013*4222ddf1SHong Zhang {
1014*4222ddf1SHong Zhang   PetscErrorCode ierr;
1015*4222ddf1SHong Zhang 
1016*4222ddf1SHong Zhang   PetscFunctionBegin;
1017*4222ddf1SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1018*4222ddf1SHong Zhang   PetscValidType(A,1);
1019*4222ddf1SHong Zhang   MatCheckPreallocated(A,1);
1020*4222ddf1SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1021*4222ddf1SHong Zhang   if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1022*4222ddf1SHong Zhang 
1023*4222ddf1SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
1024*4222ddf1SHong Zhang   PetscValidType(B,2);
1025*4222ddf1SHong Zhang   MatCheckPreallocated(B,2);
1026*4222ddf1SHong Zhang   if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1027*4222ddf1SHong Zhang   if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1028*4222ddf1SHong Zhang 
1029*4222ddf1SHong Zhang   if (C) {
1030*4222ddf1SHong Zhang     PetscValidHeaderSpecific(C,MAT_CLASSID,3);
1031*4222ddf1SHong Zhang     PetscValidType(C,3);
1032*4222ddf1SHong Zhang     MatCheckPreallocated(C,3);
1033*4222ddf1SHong Zhang     if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1034*4222ddf1SHong Zhang     if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1035*4222ddf1SHong Zhang   }
1036*4222ddf1SHong Zhang 
1037*4222ddf1SHong Zhang   PetscValidPointer(D,4);
1038*4222ddf1SHong Zhang 
1039*4222ddf1SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
1040*4222ddf1SHong Zhang   ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr);
1041*4222ddf1SHong Zhang   PetscFunctionReturn(0);
1042*4222ddf1SHong Zhang }
1043