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:   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]);
 44:   C->ops->productsymbolic = MatProductSymbolic_ABC_Transpose_AIJ_AIJ;
 45:   PetscFunctionReturn(PETSC_SUCCESS);
 46: }
 47: #endif

 49: PetscErrorCode MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
 50: {
 51:   Mat          BC;
 52:   PetscBool    scalable;
 53:   Mat_Product *product;

 55:   PetscFunctionBegin;
 56:   MatCheckProduct(D, 5);
 57:   PetscCheck(!D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data not empty");
 58:   product = D->product;
 59:   PetscCall(MatProductCreate(B, C, NULL, &BC));
 60:   PetscCall(MatProductSetType(BC, MATPRODUCT_AB));
 61:   PetscCall(PetscStrcmp(product->alg, "scalable", &scalable));
 62:   if (scalable) {
 63:     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(B, C, fill, BC));
 64:     PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
 65:     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ(A, BC, fill, D));
 66:   } else {
 67:     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(B, C, fill, BC));
 68:     PetscCall(MatZeroEntries(BC)); /* initialize value entries of BC */
 69:     PetscCall(MatMatMultSymbolic_MPIAIJ_MPIAIJ_nonscalable(A, BC, fill, D));
 70:   }
 71:   PetscCall(MatDestroy(&product->Dwork));
 72:   product->Dwork = BC;

 74:   D->ops->matmatmultnumeric = MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ;
 75:   PetscFunctionReturn(PETSC_SUCCESS);
 76: }

 78: PetscErrorCode MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ(Mat A, Mat B, Mat C, Mat D)
 79: {
 80:   Mat_Product *product;
 81:   Mat          BC;

 83:   PetscFunctionBegin;
 84:   MatCheckProduct(D, 4);
 85:   PetscCheck(D->product->data, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product data empty");
 86:   product = D->product;
 87:   BC      = product->Dwork;
 88:   PetscCall((*BC->ops->matmultnumeric)(B, C, BC));
 89:   PetscCall((*D->ops->matmultnumeric)(A, BC, D));
 90:   PetscFunctionReturn(PETSC_SUCCESS);
 91: }

 93: static PetscErrorCode MatDestroy_MPIAIJ_RARt(void *data)
 94: {
 95:   Mat_RARt *rart = (Mat_RARt *)data;

 97:   PetscFunctionBegin;
 98:   PetscCall(MatDestroy(&rart->Rt));
 99:   if (rart->destroy) PetscCall((*rart->destroy)(rart->data));
100:   PetscCall(PetscFree(rart));
101:   PetscFunctionReturn(PETSC_SUCCESS);
102: }

104: PetscErrorCode MatProductNumeric_RARt_MPIAIJ_MPIAIJ(Mat C)
105: {
106:   Mat_RARt *rart;
107:   Mat       A, R, Rt;

109:   PetscFunctionBegin;
110:   MatCheckProduct(C, 1);
111:   PetscCheck(C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data empty");
112:   rart = (Mat_RARt *)C->product->data;
113:   A    = C->product->A;
114:   R    = C->product->B;
115:   Rt   = rart->Rt;
116:   PetscCall(MatTranspose(R, MAT_REUSE_MATRIX, &Rt));
117:   if (rart->data) C->product->data = rart->data;
118:   PetscCall((*C->ops->matmatmultnumeric)(R, A, Rt, C));
119:   C->product->data = rart;
120:   PetscFunctionReturn(PETSC_SUCCESS);
121: }

123: PetscErrorCode MatProductSymbolic_RARt_MPIAIJ_MPIAIJ(Mat C)
124: {
125:   Mat       A, R, Rt;
126:   Mat_RARt *rart;

128:   PetscFunctionBegin;
129:   MatCheckProduct(C, 1);
130:   PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty");
131:   A = C->product->A;
132:   R = C->product->B;
133:   PetscCall(MatTranspose(R, MAT_INITIAL_MATRIX, &Rt));
134:   /* product->Dwork is used to store A*Rt in MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ() */
135:   PetscCall(MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ(R, A, Rt, C->product->fill, C));
136:   C->ops->productnumeric = MatProductNumeric_RARt_MPIAIJ_MPIAIJ;

138:   /* create a supporting struct */
139:   PetscCall(PetscNew(&rart));
140:   rart->Rt            = Rt;
141:   rart->data          = C->product->data;
142:   rart->destroy       = C->product->destroy;
143:   C->product->data    = rart;
144:   C->product->destroy = MatDestroy_MPIAIJ_RARt;
145:   PetscFunctionReturn(PETSC_SUCCESS);
146: }