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
MatProductNumeric_ABC_Transpose_AIJ_AIJ(Mat RAP)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));
193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
204222ddf1SHong Zhang }
214222ddf1SHong Zhang
MatProductSymbolic_ABC_Transpose_AIJ_AIJ(Mat RAP)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;
353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
363dad0653Sstefano_zampini }
374222ddf1SHong Zhang
MatProductSetFromOptions_Transpose_AIJ_AIJ(Mat C)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;
43966bd95aSPierre Jolivet PetscCheck(product->type == MATPRODUCT_ABC, PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatProduct type %s is not supported for Transpose, AIJ and AIJ matrices", MatProductTypes[product->type]);
444222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_ABC_Transpose_AIJ_AIJ;
453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
463dad0653Sstefano_zampini }
473dad0653Sstefano_zampini #endif
483dad0653Sstefano_zampini
MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(Mat A,Mat B,Mat C,PetscReal fill,Mat D)49d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
50d71ae5a4SJacob Faibussowitsch {
51f996eeb8SHong Zhang Mat BC;
524222ddf1SHong Zhang PetscBool scalable;
536718818eSStefano Zampini Mat_Product *product;
54f996eeb8SHong Zhang
55f996eeb8SHong Zhang PetscFunctionBegin;
568f83a4d9SJacob Faibussowitsch MatCheckProduct(D, 5);
5728b400f6SJacob Faibussowitsch PetscCheck(!D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data not empty");
586718818eSStefano Zampini product = D->product;
599566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &BC));
609566063dSJacob Faibussowitsch PetscCall(MatProductSetType(BC, MATPRODUCT_AB));
619566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(product->alg, "scalable", &scalable));
624222ddf1SHong Zhang if (scalable) {
639566063dSJacob Faibussowitsch PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(B, C, fill, BC));
649566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
659566063dSJacob Faibussowitsch PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(A, BC, fill, D));
664222ddf1SHong Zhang } else {
679566063dSJacob Faibussowitsch PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(B, C, fill, BC));
689566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
699566063dSJacob Faibussowitsch PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(A, BC, fill, D));
70f996eeb8SHong Zhang }
719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork));
724222ddf1SHong Zhang product->Dwork = BC;
73f996eeb8SHong Zhang
744222ddf1SHong Zhang D->ops->matmatmultnumeric = MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ;
753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
76f996eeb8SHong Zhang }
77f996eeb8SHong Zhang
MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ(Mat A,Mat B,Mat C,Mat D)78d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, Mat D)
79d71ae5a4SJacob Faibussowitsch {
806718818eSStefano Zampini Mat_Product *product;
816718818eSStefano Zampini Mat BC;
82f996eeb8SHong Zhang
83f996eeb8SHong Zhang PetscFunctionBegin;
846718818eSStefano Zampini MatCheckProduct(D, 4);
8528b400f6SJacob Faibussowitsch PetscCheck(D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data empty");
866718818eSStefano Zampini product = D->product;
876718818eSStefano Zampini BC = product->Dwork;
889566063dSJacob Faibussowitsch PetscCall((*BC->ops->matmultnumeric)(B, C, BC));
899566063dSJacob Faibussowitsch PetscCall((*D->ops->matmultnumeric)(A, BC, D));
903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
91f996eeb8SHong Zhang }
928d45306eSHong Zhang
MatProductCtxDestroy_MPIAIJ_RARt(PetscCtxRt data)93*2a8381b2SBarry Smith static PetscErrorCode MatProductCtxDestroy_MPIAIJ_RARt(PetscCtxRt data)
94d71ae5a4SJacob Faibussowitsch {
95cc1eb50dSBarry Smith MatProductCtx_RARt *rart = *(MatProductCtx_RARt **)data;
964222ddf1SHong Zhang
974222ddf1SHong Zhang PetscFunctionBegin;
989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&rart->Rt));
99cc1eb50dSBarry Smith if (rart->destroy) PetscCall((*rart->destroy)(&rart->data));
1009566063dSJacob Faibussowitsch PetscCall(PetscFree(rart));
1013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1024222ddf1SHong Zhang }
1034222ddf1SHong Zhang
MatProductNumeric_RARt_MPIAIJ_MPIAIJ(Mat C)104d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_RARt_MPIAIJ_MPIAIJ(Mat C)
105d71ae5a4SJacob Faibussowitsch {
106cc1eb50dSBarry Smith MatProductCtx_RARt *rart;
1076718818eSStefano Zampini Mat A, R, Rt;
1084222ddf1SHong Zhang
1094222ddf1SHong Zhang PetscFunctionBegin;
1106718818eSStefano Zampini MatCheckProduct(C, 1);
11128b400f6SJacob Faibussowitsch PetscCheck(C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data empty");
112cc1eb50dSBarry Smith rart = (MatProductCtx_RARt *)C->product->data;
1136718818eSStefano Zampini A = C->product->A;
1146718818eSStefano Zampini R = C->product->B;
1156718818eSStefano Zampini Rt = rart->Rt;
1169566063dSJacob Faibussowitsch PetscCall(MatTranspose(R, MAT_REUSE_MATRIX, &Rt));
1176718818eSStefano Zampini if (rart->data) C->product->data = rart->data;
1189566063dSJacob Faibussowitsch PetscCall((*C->ops->matmatmultnumeric)(R, A, Rt, C));
1196718818eSStefano Zampini C->product->data = rart;
1203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1214222ddf1SHong Zhang }
1224222ddf1SHong Zhang
MatProductSymbolic_RARt_MPIAIJ_MPIAIJ(Mat C)123d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_RARt_MPIAIJ_MPIAIJ(Mat C)
124d71ae5a4SJacob Faibussowitsch {
1256718818eSStefano Zampini Mat A, R, Rt;
126cc1eb50dSBarry Smith MatProductCtx_RARt *rart;
1278d45306eSHong Zhang
1288d45306eSHong Zhang PetscFunctionBegin;
1296718818eSStefano Zampini MatCheckProduct(C, 1);
13028b400f6SJacob Faibussowitsch PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty");
1316718818eSStefano Zampini A = C->product->A;
1326718818eSStefano Zampini R = C->product->B;
1339566063dSJacob Faibussowitsch PetscCall(MatTranspose(R, MAT_INITIAL_MATRIX, &Rt));
1344222ddf1SHong Zhang /* product->Dwork is used to store A*Rt in MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ() */
1359566063dSJacob Faibussowitsch PetscCall(MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(R, A, Rt, C->product->fill, C));
1364222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_RARt_MPIAIJ_MPIAIJ;
1374222ddf1SHong Zhang
1384222ddf1SHong Zhang /* create a supporting struct */
1399566063dSJacob Faibussowitsch PetscCall(PetscNew(&rart));
1404222ddf1SHong Zhang rart->Rt = Rt;
1416718818eSStefano Zampini rart->data = C->product->data;
1426718818eSStefano Zampini rart->destroy = C->product->destroy;
1436718818eSStefano Zampini C->product->data = rart;
144cc1eb50dSBarry Smith C->product->destroy = MatProductCtxDestroy_MPIAIJ_RARt;
1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1468d45306eSHong Zhang }
147