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