Actual source code: mpimatmatmatmult.c
1: /*
2: Defines matrix-matrix-matrix product routines for MPIAIJ matrices
3: D = A * B * C
4: */
5: #include <../src/mat/impls/aij/mpi/mpiaij.h>
7: #if defined(PETSC_HAVE_HYPRE)
8: PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat, Mat, Mat, PetscReal, Mat);
9: PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat, Mat, Mat, Mat);
11: PETSC_INTERN PetscErrorCode MatProductNumeric_ABC_Transpose_AIJ_AIJ(Mat RAP)
12: {
13: Mat_Product *product = RAP->product;
14: Mat Rt, R = product->A, A = product->B, P = product->C;
16: PetscFunctionBegin;
17: PetscCall(MatTransposeGetMat(R, &Rt));
18: PetscCall(MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Rt, A, P, RAP));
19: PetscFunctionReturn(PETSC_SUCCESS);
20: }
22: PETSC_INTERN PetscErrorCode MatProductSymbolic_ABC_Transpose_AIJ_AIJ(Mat RAP)
23: {
24: Mat_Product *product = RAP->product;
25: Mat Rt, R = product->A, A = product->B, P = product->C;
26: PetscBool flg;
28: PetscFunctionBegin;
29: /* local sizes of matrices will be checked by the calling subroutines */
30: PetscCall(MatTransposeGetMat(R, &Rt));
31: PetscCall(PetscObjectTypeCompareAny((PetscObject)Rt, &flg, MATSEQAIJ, MATSEQAIJMKL, MATMPIAIJ, NULL));
32: PetscCheck(flg, PetscObjectComm((PetscObject)Rt), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)Rt)->type_name);
33: PetscCall(MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Rt, A, P, product->fill, RAP));
34: RAP->ops->productnumeric = MatProductNumeric_ABC_Transpose_AIJ_AIJ;
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose_AIJ_AIJ(Mat C)
39: {
40: Mat_Product *product = C->product;
42: PetscFunctionBegin;
43: if (product->type == MATPRODUCT_ABC) {
44: C->ops->productsymbolic = MatProductSymbolic_ABC_Transpose_AIJ_AIJ;
45: } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatProduct type %s is not supported for Transpose, AIJ and AIJ matrices", MatProductTypes[product->type]);
46: PetscFunctionReturn(PETSC_SUCCESS);
47: }
48: #endif
50: PetscErrorCode MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
51: {
52: Mat BC;
53: PetscBool scalable;
54: Mat_Product *product;
56: PetscFunctionBegin;
57: MatCheckProduct(D, 5);
58: PetscCheck(!D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data not empty");
59: product = D->product;
60: PetscCall(MatProductCreate(B, C, NULL, &BC));
61: PetscCall(MatProductSetType(BC, MATPRODUCT_AB));
62: PetscCall(PetscStrcmp(product->alg, "scalable", &scalable));
63: if (scalable) {
64: PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(B, C, fill, BC));
65: PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
66: PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(A, BC, fill, D));
67: } else {
68: PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(B, C, fill, BC));
69: PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
70: PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(A, BC, fill, D));
71: }
72: PetscCall(MatDestroy(&product->Dwork));
73: product->Dwork = BC;
75: D->ops->matmatmultnumeric = MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ;
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
79: PetscErrorCode MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, Mat D)
80: {
81: Mat_Product *product;
82: Mat BC;
84: PetscFunctionBegin;
85: MatCheckProduct(D, 4);
86: PetscCheck(D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data empty");
87: product = D->product;
88: BC = product->Dwork;
89: PetscCall((*BC->ops->matmultnumeric)(B, C, BC));
90: PetscCall((*D->ops->matmultnumeric)(A, BC, D));
91: PetscFunctionReturn(PETSC_SUCCESS);
92: }
94: static PetscErrorCode MatDestroy_MPIAIJ_RARt(void *data)
95: {
96: Mat_RARt *rart = (Mat_RARt *)data;
98: PetscFunctionBegin;
99: PetscCall(MatDestroy(&rart->Rt));
100: if (rart->destroy) PetscCall((*rart->destroy)(rart->data));
101: PetscCall(PetscFree(rart));
102: PetscFunctionReturn(PETSC_SUCCESS);
103: }
105: PetscErrorCode MatProductNumeric_RARt_MPIAIJ_MPIAIJ(Mat C)
106: {
107: Mat_RARt *rart;
108: Mat A, R, Rt;
110: PetscFunctionBegin;
111: MatCheckProduct(C, 1);
112: PetscCheck(C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data empty");
113: rart = (Mat_RARt *)C->product->data;
114: A = C->product->A;
115: R = C->product->B;
116: Rt = rart->Rt;
117: PetscCall(MatTranspose(R, MAT_REUSE_MATRIX, &Rt));
118: if (rart->data) C->product->data = rart->data;
119: PetscCall((*C->ops->matmatmultnumeric)(R, A, Rt, C));
120: C->product->data = rart;
121: PetscFunctionReturn(PETSC_SUCCESS);
122: }
124: PetscErrorCode MatProductSymbolic_RARt_MPIAIJ_MPIAIJ(Mat C)
125: {
126: Mat A, R, Rt;
127: Mat_RARt *rart;
129: PetscFunctionBegin;
130: MatCheckProduct(C, 1);
131: PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty");
132: A = C->product->A;
133: R = C->product->B;
134: PetscCall(MatTranspose(R, MAT_INITIAL_MATRIX, &Rt));
135: /* product->Dwork is used to store A*Rt in MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ() */
136: PetscCall(MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(R, A, Rt, C->product->fill, C));
137: C->ops->productnumeric = MatProductNumeric_RARt_MPIAIJ_MPIAIJ;
139: /* create a supporting struct */
140: PetscCall(PetscNew(&rart));
141: rart->Rt = Rt;
142: rart->data = C->product->data;
143: rart->destroy = C->product->destroy;
144: C->product->data = rart;
145: C->product->destroy = MatDestroy_MPIAIJ_RARt;
146: PetscFunctionReturn(PETSC_SUCCESS);
147: }