xref: /petsc/src/mat/impls/aij/mpi/mpimatmatmatmult.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1f996eeb8SHong Zhang /*
2f996eeb8SHong Zhang   Defines matrix-matrix-matrix product routines for MPIAIJ matrices
3f996eeb8SHong Zhang           D = A * B * C
4f996eeb8SHong Zhang */
5f996eeb8SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h> /*I "petscmat.h" I*/
6f996eeb8SHong Zhang 
73dad0653Sstefano_zampini #if defined(PETSC_HAVE_HYPRE)
84222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat, Mat, Mat, PetscReal, Mat);
93dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat, Mat, Mat, Mat);
103dad0653Sstefano_zampini 
11d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductNumeric_ABC_Transpose_AIJ_AIJ(Mat RAP)
12d71ae5a4SJacob Faibussowitsch {
134222ddf1SHong Zhang   Mat_Product *product = RAP->product;
144222ddf1SHong Zhang   Mat          Rt, R = product->A, A = product->B, P = product->C;
153dad0653Sstefano_zampini 
163dad0653Sstefano_zampini   PetscFunctionBegin;
179566063dSJacob Faibussowitsch   PetscCall(MatTransposeGetMat(R, &Rt));
189566063dSJacob Faibussowitsch   PetscCall(MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Rt, A, P, RAP));
19*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204222ddf1SHong Zhang }
214222ddf1SHong Zhang 
22d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSymbolic_ABC_Transpose_AIJ_AIJ(Mat RAP)
23d71ae5a4SJacob Faibussowitsch {
244222ddf1SHong Zhang   Mat_Product *product = RAP->product;
254222ddf1SHong Zhang   Mat          Rt, R = product->A, A = product->B, P = product->C;
264222ddf1SHong Zhang   PetscBool    flg;
274222ddf1SHong Zhang 
284222ddf1SHong Zhang   PetscFunctionBegin;
294222ddf1SHong Zhang   /* local sizes of matrices will be checked by the calling subroutines */
309566063dSJacob Faibussowitsch   PetscCall(MatTransposeGetMat(R, &Rt));
319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)Rt, &flg, MATSEQAIJ, MATSEQAIJMKL, MATMPIAIJ, NULL));
3228b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)Rt), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)Rt)->type_name);
339566063dSJacob Faibussowitsch   PetscCall(MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Rt, A, P, product->fill, RAP));
344222ddf1SHong Zhang   RAP->ops->productnumeric = MatProductNumeric_ABC_Transpose_AIJ_AIJ;
35*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
363dad0653Sstefano_zampini }
374222ddf1SHong Zhang 
38d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose_AIJ_AIJ(Mat C)
39d71ae5a4SJacob Faibussowitsch {
404222ddf1SHong Zhang   Mat_Product *product = C->product;
414222ddf1SHong Zhang 
424222ddf1SHong Zhang   PetscFunctionBegin;
434222ddf1SHong Zhang   if (product->type == MATPRODUCT_ABC) {
444222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_ABC_Transpose_AIJ_AIJ;
4598921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatProduct type %s is not supported for Transpose, AIJ and AIJ matrices", MatProductTypes[product->type]);
46*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
473dad0653Sstefano_zampini }
483dad0653Sstefano_zampini #endif
493dad0653Sstefano_zampini 
50d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
51d71ae5a4SJacob Faibussowitsch {
52f996eeb8SHong Zhang   Mat          BC;
534222ddf1SHong Zhang   PetscBool    scalable;
546718818eSStefano Zampini   Mat_Product *product;
55f996eeb8SHong Zhang 
56f996eeb8SHong Zhang   PetscFunctionBegin;
578f83a4d9SJacob Faibussowitsch   MatCheckProduct(D, 5);
5828b400f6SJacob Faibussowitsch   PetscCheck(!D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data not empty");
596718818eSStefano Zampini   product = D->product;
609566063dSJacob Faibussowitsch   PetscCall(MatProductCreate(B, C, NULL, &BC));
619566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(BC, MATPRODUCT_AB));
629566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(product->alg, "scalable", &scalable));
634222ddf1SHong Zhang   if (scalable) {
649566063dSJacob Faibussowitsch     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(B, C, fill, BC));
659566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
669566063dSJacob Faibussowitsch     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(A, BC, fill, D));
674222ddf1SHong Zhang   } else {
689566063dSJacob Faibussowitsch     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(B, C, fill, BC));
699566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
709566063dSJacob Faibussowitsch     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(A, BC, fill, D));
71f996eeb8SHong Zhang   }
729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&product->Dwork));
734222ddf1SHong Zhang   product->Dwork = BC;
74f996eeb8SHong Zhang 
754222ddf1SHong Zhang   D->ops->matmatmultnumeric = MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ;
76*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77f996eeb8SHong Zhang }
78f996eeb8SHong Zhang 
79d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, Mat D)
80d71ae5a4SJacob Faibussowitsch {
816718818eSStefano Zampini   Mat_Product *product;
826718818eSStefano Zampini   Mat          BC;
83f996eeb8SHong Zhang 
84f996eeb8SHong Zhang   PetscFunctionBegin;
856718818eSStefano Zampini   MatCheckProduct(D, 4);
8628b400f6SJacob Faibussowitsch   PetscCheck(D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data empty");
876718818eSStefano Zampini   product = D->product;
886718818eSStefano Zampini   BC      = product->Dwork;
899566063dSJacob Faibussowitsch   PetscCall((*BC->ops->matmultnumeric)(B, C, BC));
909566063dSJacob Faibussowitsch   PetscCall((*D->ops->matmultnumeric)(A, BC, D));
91*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92f996eeb8SHong Zhang }
938d45306eSHong Zhang 
944222ddf1SHong Zhang /* ----------------------------------------------------- */
95d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPIAIJ_RARt(void *data)
96d71ae5a4SJacob Faibussowitsch {
976718818eSStefano Zampini   Mat_RARt *rart = (Mat_RARt *)data;
984222ddf1SHong Zhang 
994222ddf1SHong Zhang   PetscFunctionBegin;
1009566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&rart->Rt));
1011baa6e33SBarry Smith   if (rart->destroy) PetscCall((*rart->destroy)(rart->data));
1029566063dSJacob Faibussowitsch   PetscCall(PetscFree(rart));
103*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1044222ddf1SHong Zhang }
1054222ddf1SHong Zhang 
106d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_RARt_MPIAIJ_MPIAIJ(Mat C)
107d71ae5a4SJacob Faibussowitsch {
1086718818eSStefano Zampini   Mat_RARt *rart;
1096718818eSStefano Zampini   Mat       A, R, Rt;
1104222ddf1SHong Zhang 
1114222ddf1SHong Zhang   PetscFunctionBegin;
1126718818eSStefano Zampini   MatCheckProduct(C, 1);
11328b400f6SJacob Faibussowitsch   PetscCheck(C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data empty");
1146718818eSStefano Zampini   rart = (Mat_RARt *)C->product->data;
1156718818eSStefano Zampini   A    = C->product->A;
1166718818eSStefano Zampini   R    = C->product->B;
1176718818eSStefano Zampini   Rt   = rart->Rt;
1189566063dSJacob Faibussowitsch   PetscCall(MatTranspose(R, MAT_REUSE_MATRIX, &Rt));
1196718818eSStefano Zampini   if (rart->data) C->product->data = rart->data;
1209566063dSJacob Faibussowitsch   PetscCall((*C->ops->matmatmultnumeric)(R, A, Rt, C));
1216718818eSStefano Zampini   C->product->data = rart;
122*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1234222ddf1SHong Zhang }
1244222ddf1SHong Zhang 
125d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_RARt_MPIAIJ_MPIAIJ(Mat C)
126d71ae5a4SJacob Faibussowitsch {
1276718818eSStefano Zampini   Mat       A, R, Rt;
1284222ddf1SHong Zhang   Mat_RARt *rart;
1298d45306eSHong Zhang 
1308d45306eSHong Zhang   PetscFunctionBegin;
1316718818eSStefano Zampini   MatCheckProduct(C, 1);
13228b400f6SJacob Faibussowitsch   PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty");
1336718818eSStefano Zampini   A = C->product->A;
1346718818eSStefano Zampini   R = C->product->B;
1359566063dSJacob Faibussowitsch   PetscCall(MatTranspose(R, MAT_INITIAL_MATRIX, &Rt));
1364222ddf1SHong Zhang   /* product->Dwork is used to store A*Rt in MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ() */
1379566063dSJacob Faibussowitsch   PetscCall(MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(R, A, Rt, C->product->fill, C));
1384222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_RARt_MPIAIJ_MPIAIJ;
1394222ddf1SHong Zhang 
1404222ddf1SHong Zhang   /* create a supporting struct */
1419566063dSJacob Faibussowitsch   PetscCall(PetscNew(&rart));
1424222ddf1SHong Zhang   rart->Rt            = Rt;
1436718818eSStefano Zampini   rart->data          = C->product->data;
1446718818eSStefano Zampini   rart->destroy       = C->product->destroy;
1456718818eSStefano Zampini   C->product->data    = rart;
1466718818eSStefano Zampini   C->product->destroy = MatDestroy_MPIAIJ_RARt;
147*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1488d45306eSHong Zhang }
149