14222ddf1SHong Zhang /* 24222ddf1SHong Zhang Routines for matrix products. Calling procedure: 34222ddf1SHong Zhang 46718818eSStefano Zampini MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 56718818eSStefano Zampini MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC) 66718818eSStefano Zampini MatProductSetAlgorithm(D, alg) 76718818eSStefano Zampini MatProductSetFill(D,fill) 86718818eSStefano Zampini MatProductSetFromOptions(D) 96718818eSStefano Zampini -> MatProductSetFromOptions_Private(D) 104222ddf1SHong Zhang # Check matrix global sizes 116718818eSStefano Zampini if the matrices have the same setfromoptions routine, use it 126718818eSStefano Zampini if not, try: 136718818eSStefano Zampini -> Query MatProductSetFromOptions_Atype_Btype_Ctype_C(D) from A, B and C (in order) 146718818eSStefano Zampini if found -> run the specific setup that must set the symbolic operation (these callbacks should never fail) 156718818eSStefano Zampini if callback not found or no symbolic operation set 16013e2dc7SBarry Smith -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANSPOSEVIRTUAL) 176718818eSStefano Zampini if dispatch found but combination still not present do 186718818eSStefano Zampini -> check if B is dense and product type AtB or AB -> if true, basic looping of dense columns 196718818eSStefano Zampini -> check if triple product (PtAP, RARt or ABC) -> if true, set the Basic routines 206718818eSStefano Zampini 216718818eSStefano Zampini # The setfromoptions calls MatProductSetFromOptions_Atype_Btype_Ctype should 224222ddf1SHong Zhang # Check matrix local sizes for mpi matrices 234222ddf1SHong Zhang # Set default algorithm 244222ddf1SHong Zhang # Get runtime option 256718818eSStefano Zampini # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype if found 264222ddf1SHong Zhang 276718818eSStefano Zampini MatProductSymbolic(D) 286718818eSStefano Zampini # Call MatProductSymbolic_productype_Atype_Btype_Ctype() 296718818eSStefano Zampini the callback must set the numeric phase D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype 304222ddf1SHong Zhang 316718818eSStefano Zampini MatProductNumeric(D) 326718818eSStefano Zampini # Call the numeric phase 336718818eSStefano Zampini 346718818eSStefano Zampini # The symbolic phases are allowed to set extra data structures and attach those to the product 356718818eSStefano Zampini # this additional data can be reused between multiple numeric phases with the same matrices 366718818eSStefano Zampini # if not needed, call 376718818eSStefano Zampini MatProductClear(D) 384222ddf1SHong Zhang */ 394222ddf1SHong Zhang 404222ddf1SHong Zhang #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 414222ddf1SHong Zhang 426718818eSStefano Zampini const char *const MatProductTypes[] = {"UNSPECIFIED", "AB", "AtB", "ABt", "PtAP", "RARt", "ABC"}; 43544a5e07SHong Zhang 446718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 456718818eSStefano Zampini * they are dangerous and should be removed in the future */ 46d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_PtAP_Unsafe(Mat C) 47d71ae5a4SJacob Faibussowitsch { 484222ddf1SHong Zhang Mat_Product *product = C->product; 494222ddf1SHong Zhang Mat P = product->B, AP = product->Dwork; 504222ddf1SHong Zhang 514222ddf1SHong Zhang PetscFunctionBegin; 524222ddf1SHong Zhang /* AP = A*P */ 539566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(AP)); 544222ddf1SHong Zhang /* C = P^T*AP */ 55fe47926eSStefano Zampini product->type = MATPRODUCT_AtB; 569566063dSJacob Faibussowitsch PetscCall((*C->ops->transposematmultnumeric)(P, AP, C)); 57fe47926eSStefano Zampini product->type = MATPRODUCT_PtAP; 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 594222ddf1SHong Zhang } 604222ddf1SHong Zhang 61d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_Unsafe(Mat C) 62d71ae5a4SJacob Faibussowitsch { 634222ddf1SHong Zhang Mat_Product *product = C->product; 644222ddf1SHong Zhang Mat A = product->A, P = product->B, AP; 654222ddf1SHong Zhang PetscReal fill = product->fill; 664222ddf1SHong Zhang 674222ddf1SHong Zhang PetscFunctionBegin; 68835f2295SStefano Zampini PetscCall(PetscInfo(C, "for A %s, P %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 694222ddf1SHong Zhang /* AP = A*P */ 709566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, P, NULL, &AP)); 719566063dSJacob Faibussowitsch PetscCall(MatProductSetType(AP, MATPRODUCT_AB)); 729566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(AP, MATPRODUCTALGORITHMDEFAULT)); 739566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(AP, fill)); 749566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(AP)); 759566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(AP)); 764222ddf1SHong Zhang 774222ddf1SHong Zhang /* C = P^T*AP */ 789566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_AtB)); 799566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 804222ddf1SHong Zhang product->A = P; 814222ddf1SHong Zhang product->B = AP; 829566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 839566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 844222ddf1SHong Zhang 854222ddf1SHong Zhang /* resume user's original input matrix setting for A and B */ 86fe47926eSStefano Zampini product->type = MATPRODUCT_PtAP; 874222ddf1SHong Zhang product->A = A; 884222ddf1SHong Zhang product->B = P; 894222ddf1SHong Zhang product->Dwork = AP; 904222ddf1SHong Zhang 915415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_PtAP_Unsafe; 923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 934222ddf1SHong Zhang } 944222ddf1SHong Zhang 95d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_RARt_Unsafe(Mat C) 96d71ae5a4SJacob Faibussowitsch { 974222ddf1SHong Zhang Mat_Product *product = C->product; 984222ddf1SHong Zhang Mat R = product->B, RA = product->Dwork; 994222ddf1SHong Zhang 1004222ddf1SHong Zhang PetscFunctionBegin; 1014222ddf1SHong Zhang /* RA = R*A */ 1029566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(RA)); 1034222ddf1SHong Zhang /* C = RA*R^T */ 104fe47926eSStefano Zampini product->type = MATPRODUCT_ABt; 1059566063dSJacob Faibussowitsch PetscCall((*C->ops->mattransposemultnumeric)(RA, R, C)); 106fe47926eSStefano Zampini product->type = MATPRODUCT_RARt; 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1084222ddf1SHong Zhang } 1094222ddf1SHong Zhang 110d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_RARt_Unsafe(Mat C) 111d71ae5a4SJacob Faibussowitsch { 1124222ddf1SHong Zhang Mat_Product *product = C->product; 1134222ddf1SHong Zhang Mat A = product->A, R = product->B, RA; 1144222ddf1SHong Zhang PetscReal fill = product->fill; 1154222ddf1SHong Zhang 1164222ddf1SHong Zhang PetscFunctionBegin; 117835f2295SStefano Zampini PetscCall(PetscInfo(C, "for A %s, R %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 1184222ddf1SHong Zhang /* RA = R*A */ 1199566063dSJacob Faibussowitsch PetscCall(MatProductCreate(R, A, NULL, &RA)); 1209566063dSJacob Faibussowitsch PetscCall(MatProductSetType(RA, MATPRODUCT_AB)); 1219566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(RA, MATPRODUCTALGORITHMDEFAULT)); 1229566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(RA, fill)); 1239566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(RA)); 1249566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(RA)); 1254222ddf1SHong Zhang 1264222ddf1SHong Zhang /* C = RA*R^T */ 1279566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_ABt)); 1289566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 1294222ddf1SHong Zhang product->A = RA; 1309566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 1319566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 1324222ddf1SHong Zhang 1334222ddf1SHong Zhang /* resume user's original input matrix setting for A */ 134fe47926eSStefano Zampini product->type = MATPRODUCT_RARt; 1354222ddf1SHong Zhang product->A = A; 1364222ddf1SHong Zhang product->Dwork = RA; /* save here so it will be destroyed with product C */ 1375415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_RARt_Unsafe; 1383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1394222ddf1SHong Zhang } 1404222ddf1SHong Zhang 141d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_ABC_Unsafe(Mat mat) 142d71ae5a4SJacob Faibussowitsch { 1434222ddf1SHong Zhang Mat_Product *product = mat->product; 1444222ddf1SHong Zhang Mat A = product->A, BC = product->Dwork; 1454222ddf1SHong Zhang 1464222ddf1SHong Zhang PetscFunctionBegin; 1474222ddf1SHong Zhang /* Numeric BC = B*C */ 1489566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(BC)); 1494222ddf1SHong Zhang /* Numeric mat = A*BC */ 150fe47926eSStefano Zampini product->type = MATPRODUCT_AB; 1519566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, BC, mat)); 152fe47926eSStefano Zampini product->type = MATPRODUCT_ABC; 1533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1544222ddf1SHong Zhang } 1554222ddf1SHong Zhang 156d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_ABC_Unsafe(Mat mat) 157d71ae5a4SJacob Faibussowitsch { 1584222ddf1SHong Zhang Mat_Product *product = mat->product; 1594222ddf1SHong Zhang Mat B = product->B, C = product->C, BC; 1604222ddf1SHong Zhang PetscReal fill = product->fill; 1614222ddf1SHong Zhang 1624222ddf1SHong Zhang PetscFunctionBegin; 163835f2295SStefano Zampini PetscCall(PetscInfo(mat, "for A %s, B %s, C %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name, ((PetscObject)product->C)->type_name)); 1644222ddf1SHong Zhang /* Symbolic BC = B*C */ 1659566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &BC)); 1669566063dSJacob Faibussowitsch PetscCall(MatProductSetType(BC, MATPRODUCT_AB)); 1679566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(BC, MATPRODUCTALGORITHMDEFAULT)); 1689566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(BC, fill)); 1699566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(BC)); 1709566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(BC)); 1714222ddf1SHong Zhang 1724222ddf1SHong Zhang /* Symbolic mat = A*BC */ 1739566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mat, MATPRODUCT_AB)); 1749566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mat, MATPRODUCTALGORITHMDEFAULT)); 1754222ddf1SHong Zhang product->B = BC; 1764222ddf1SHong Zhang product->Dwork = BC; 1779566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mat)); 1789566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(mat)); 1794222ddf1SHong Zhang 1804222ddf1SHong Zhang /* resume user's original input matrix setting for B */ 181fe47926eSStefano Zampini product->type = MATPRODUCT_ABC; 1824222ddf1SHong Zhang product->B = B; 1835415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Unsafe; 1843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1854222ddf1SHong Zhang } 1864222ddf1SHong Zhang 187d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_Unsafe(Mat mat) 188d71ae5a4SJacob Faibussowitsch { 1894222ddf1SHong Zhang Mat_Product *product = mat->product; 1904222ddf1SHong Zhang 1914222ddf1SHong Zhang PetscFunctionBegin; 1924222ddf1SHong Zhang switch (product->type) { 193d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 194d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_PtAP_Unsafe(mat)); 195d71ae5a4SJacob Faibussowitsch break; 196d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 197d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_RARt_Unsafe(mat)); 198d71ae5a4SJacob Faibussowitsch break; 199d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 200d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_ABC_Unsafe(mat)); 201d71ae5a4SJacob Faibussowitsch break; 202d71ae5a4SJacob Faibussowitsch default: 203d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[product->type]); 2044222ddf1SHong Zhang } 2053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2064222ddf1SHong Zhang } 2074222ddf1SHong Zhang 208cb3ff29fSJose E. Roman /*@ 20927430b45SBarry Smith MatProductReplaceMats - Replace the input matrices for the matrix-matrix product operation inside the computed matrix 2104222ddf1SHong Zhang 21127430b45SBarry Smith Collective 2124222ddf1SHong Zhang 2134222ddf1SHong Zhang Input Parameters: 21427430b45SBarry Smith + A - the matrix or `NULL` if not being replaced 21527430b45SBarry Smith . B - the matrix or `NULL` if not being replaced 21627430b45SBarry Smith . C - the matrix or `NULL` if not being replaced 21727430b45SBarry Smith - D - the matrix whose values are computed via a matrix-matrix product operation 2184222ddf1SHong Zhang 2194222ddf1SHong Zhang Level: intermediate 2204222ddf1SHong Zhang 22111a5261eSBarry Smith Note: 22211a5261eSBarry Smith To reuse the symbolic phase, the input matrices must have exactly the same data structure as the replaced one. 2231cdffd5eSHong Zhang If the type of any of the input matrices is different than what was previously used, or their symmetry flag changed but 22427430b45SBarry Smith the symbolic phase took advantage of their symmetry, the product is cleared and `MatProductSetFromOptions()` 22527430b45SBarry Smith and `MatProductSymbolic()` are invoked again. 2264222ddf1SHong Zhang 2270241b274SPierre Jolivet .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreate()`, `MatProductSetFromOptions()`, `MatProductSymbolic()`, `MatProductClear()` 2284222ddf1SHong Zhang @*/ 229d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductReplaceMats(Mat A, Mat B, Mat C, Mat D) 230d71ae5a4SJacob Faibussowitsch { 2316718818eSStefano Zampini Mat_Product *product; 232b94d7dedSBarry Smith PetscBool flgA = PETSC_TRUE, flgB = PETSC_TRUE, flgC = PETSC_TRUE, isset, issym; 2334222ddf1SHong Zhang 2344222ddf1SHong Zhang PetscFunctionBegin; 2357a3c3d58SStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 2366718818eSStefano Zampini MatCheckProduct(D, 4); 2376718818eSStefano Zampini product = D->product; 2384222ddf1SHong Zhang if (A) { 2397a3c3d58SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 2419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, ((PetscObject)A)->type_name, &flgA)); 242b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(A, &isset, &issym)); 243b94d7dedSBarry Smith if (product->symbolic_used_the_fact_A_is_symmetric && isset && !issym) { /* symbolic was built around a symmetric A, but the new A is not anymore */ 244fa046f9fSJunchao Zhang flgA = PETSC_FALSE; 245fa046f9fSJunchao Zhang product->symbolic_used_the_fact_A_is_symmetric = PETSC_FALSE; /* reinit */ 246fa046f9fSJunchao Zhang } 2479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 2484222ddf1SHong Zhang product->A = A; 2494222ddf1SHong Zhang } 2504222ddf1SHong Zhang if (B) { 2517a3c3d58SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 2529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 2539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->B, ((PetscObject)B)->type_name, &flgB)); 254b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(B, &isset, &issym)); 255b94d7dedSBarry Smith if (product->symbolic_used_the_fact_B_is_symmetric && isset && !issym) { 256fa046f9fSJunchao Zhang flgB = PETSC_FALSE; 257fa046f9fSJunchao Zhang product->symbolic_used_the_fact_B_is_symmetric = PETSC_FALSE; /* reinit */ 258fa046f9fSJunchao Zhang } 2599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 2604222ddf1SHong Zhang product->B = B; 2614222ddf1SHong Zhang } 2624417c5e8SHong Zhang if (C) { 2637a3c3d58SStefano Zampini PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 2659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->C, ((PetscObject)C)->type_name, &flgC)); 266b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(C, &isset, &issym)); 267b94d7dedSBarry Smith if (product->symbolic_used_the_fact_C_is_symmetric && isset && !issym) { 268fa046f9fSJunchao Zhang flgC = PETSC_FALSE; 269fa046f9fSJunchao Zhang product->symbolic_used_the_fact_C_is_symmetric = PETSC_FALSE; /* reinit */ 270fa046f9fSJunchao Zhang } 2719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 2724417c5e8SHong Zhang product->C = C; 2734417c5e8SHong Zhang } 2746718818eSStefano Zampini /* Any of the replaced mats is of a different type, reset */ 2756718818eSStefano Zampini if (!flgA || !flgB || !flgC) { 276*cc1eb50dSBarry Smith if (D->product->destroy) PetscCall((*D->product->destroy)(&D->product->data)); 2776718818eSStefano Zampini D->product->destroy = NULL; 2786718818eSStefano Zampini D->product->data = NULL; 2796718818eSStefano Zampini if (D->ops->productnumeric || D->ops->productsymbolic) { 2809566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(D)); 2819566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(D)); 2826718818eSStefano Zampini } 2836718818eSStefano Zampini } 2843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2854222ddf1SHong Zhang } 2864222ddf1SHong Zhang 287d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_X_Dense(Mat C) 288d71ae5a4SJacob Faibussowitsch { 2897a3c3d58SStefano Zampini Mat_Product *product = C->product; 2907a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 2917a3c3d58SStefano Zampini PetscInt k, K = B->cmap->N; 2927a3c3d58SStefano Zampini PetscBool t = PETSC_TRUE, iscuda = PETSC_FALSE; 2937a3c3d58SStefano Zampini PetscBool Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE; 2947a3c3d58SStefano Zampini char *Btype = NULL, *Ctype = NULL; 2957a3c3d58SStefano Zampini 2967a3c3d58SStefano Zampini PetscFunctionBegin; 2977a3c3d58SStefano Zampini switch (product->type) { 298d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 299d71ae5a4SJacob Faibussowitsch t = PETSC_FALSE; 300d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 301d71ae5a4SJacob Faibussowitsch break; 302d71ae5a4SJacob Faibussowitsch default: 303d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatProductNumeric type %s not supported for %s and %s matrices", MatProductTypes[product->type], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name); 3047a3c3d58SStefano Zampini } 3057a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 3067a3c3d58SStefano Zampini VecType vtype; 3077a3c3d58SStefano Zampini 3089566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A, &vtype)); 3099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype, VECCUDA, &iscuda)); 31048a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECSEQCUDA, &iscuda)); 31148a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECMPICUDA, &iscuda)); 3127a3c3d58SStefano Zampini if (iscuda) { /* Make sure we have up-to-date data on the GPU */ 3139566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)B)->type_name, &Btype)); 3149566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)C)->type_name, &Ctype)); 3159566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3167a3c3d58SStefano Zampini if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */ 3179566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 3189566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 3197a3c3d58SStefano Zampini } 3209566063dSJacob Faibussowitsch PetscCall(MatConvert(C, MATDENSECUDA, MAT_INPLACE_MATRIX, &C)); 3217a3c3d58SStefano Zampini } else { /* Make sure we have up-to-date data on the CPU */ 3227a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL) 3237a3c3d58SStefano Zampini Bcpu = B->boundtocpu; 3247a3c3d58SStefano Zampini Ccpu = C->boundtocpu; 3257a3c3d58SStefano Zampini #endif 3269566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, PETSC_TRUE)); 3279566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, PETSC_TRUE)); 3287a3c3d58SStefano Zampini } 3297a3c3d58SStefano Zampini } 3307a3c3d58SStefano Zampini for (k = 0; k < K; k++) { 3317a3c3d58SStefano Zampini Vec x, y; 3327a3c3d58SStefano Zampini 3339566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(B, k, &x)); 3349566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecWrite(C, k, &y)); 3357a3c3d58SStefano Zampini if (t) { 3369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, x, y)); 3377a3c3d58SStefano Zampini } else { 3389566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, y)); 3397a3c3d58SStefano Zampini } 3409566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(B, k, &x)); 3419566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecWrite(C, k, &y)); 3427a3c3d58SStefano Zampini } 34367af85e8SPierre Jolivet PetscCall(MatSetOption(C, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 3449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 3459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 3467a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 3477a3c3d58SStefano Zampini if (iscuda) { 3489566063dSJacob Faibussowitsch PetscCall(MatConvert(B, Btype, MAT_INPLACE_MATRIX, &B)); 3499566063dSJacob Faibussowitsch PetscCall(MatConvert(C, Ctype, MAT_INPLACE_MATRIX, &C)); 3507a3c3d58SStefano Zampini } else { 3519566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, Bcpu)); 3529566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, Ccpu)); 3537a3c3d58SStefano Zampini } 3547a3c3d58SStefano Zampini } 3559566063dSJacob Faibussowitsch PetscCall(PetscFree(Btype)); 3569566063dSJacob Faibussowitsch PetscCall(PetscFree(Ctype)); 3573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3587a3c3d58SStefano Zampini } 3597a3c3d58SStefano Zampini 360d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_X_Dense(Mat C) 361d71ae5a4SJacob Faibussowitsch { 3627a3c3d58SStefano Zampini Mat_Product *product = C->product; 3637a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 3647a3c3d58SStefano Zampini PetscBool isdense; 3657a3c3d58SStefano Zampini 3667a3c3d58SStefano Zampini PetscFunctionBegin; 3677a3c3d58SStefano Zampini switch (product->type) { 368d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 369d71ae5a4SJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->n, B->cmap->n, A->rmap->N, B->cmap->N)); 370d71ae5a4SJacob Faibussowitsch break; 371d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 372d71ae5a4SJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, B->cmap->n, A->cmap->N, B->cmap->N)); 373d71ae5a4SJacob Faibussowitsch break; 374d71ae5a4SJacob Faibussowitsch default: 375d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatProductSymbolic type %s not supported for %s and %s matrices", MatProductTypes[product->type], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name); 3767a3c3d58SStefano Zampini } 3779566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)C, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 3787a3c3d58SStefano Zampini if (!isdense) { 3799566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)B)->type_name)); 3806718818eSStefano Zampini /* If matrix type of C was not set or not dense, we need to reset the pointer */ 3817a3c3d58SStefano Zampini C->ops->productsymbolic = MatProductSymbolic_X_Dense; 3827a3c3d58SStefano Zampini } 3836718818eSStefano Zampini C->ops->productnumeric = MatProductNumeric_X_Dense; 3849566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 3853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3867a3c3d58SStefano Zampini } 3877a3c3d58SStefano Zampini 3886718818eSStefano Zampini /* a single driver to query the dispatching */ 389d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Private(Mat mat) 390d71ae5a4SJacob Faibussowitsch { 3914222ddf1SHong Zhang Mat_Product *product = mat->product; 3926718818eSStefano Zampini PetscInt Am, An, Bm, Bn, Cm, Cn; 3934222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 3946718818eSStefano Zampini const char *const Bnames[] = {"B", "R", "P"}; 3956718818eSStefano Zampini const char *bname; 3964222ddf1SHong Zhang PetscErrorCode (*fA)(Mat); 3974222ddf1SHong Zhang PetscErrorCode (*fB)(Mat); 3984222ddf1SHong Zhang PetscErrorCode (*fC)(Mat); 3994222ddf1SHong Zhang PetscErrorCode (*f)(Mat) = NULL; 4004222ddf1SHong Zhang 4014222ddf1SHong Zhang PetscFunctionBegin; 4026718818eSStefano Zampini mat->ops->productsymbolic = NULL; 4036718818eSStefano Zampini mat->ops->productnumeric = NULL; 4043ba16761SJacob Faibussowitsch if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(PETSC_SUCCESS); 40528b400f6SJacob Faibussowitsch PetscCheck(A, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing A mat"); 40628b400f6SJacob Faibussowitsch PetscCheck(B, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing B mat"); 407072cda71SBarry Smith PetscCheck(product->type != MATPRODUCT_ABC || C, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing C mat"); 4086718818eSStefano Zampini if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */ 4096718818eSStefano Zampini if (product->type == MATPRODUCT_RARt) bname = Bnames[1]; 4106718818eSStefano Zampini else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2]; 4116718818eSStefano Zampini else bname = Bnames[0]; 4126718818eSStefano Zampini 4136718818eSStefano Zampini /* Check matrices sizes */ 4146718818eSStefano Zampini Am = A->rmap->N; 4156718818eSStefano Zampini An = A->cmap->N; 4166718818eSStefano Zampini Bm = B->rmap->N; 4176718818eSStefano Zampini Bn = B->cmap->N; 4186718818eSStefano Zampini Cm = C ? C->rmap->N : 0; 4196718818eSStefano Zampini Cn = C ? C->cmap->N : 0; 4209371c9d4SSatish Balay if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { 4219371c9d4SSatish Balay PetscInt t = Bn; 4229371c9d4SSatish Balay Bn = Bm; 4239371c9d4SSatish Balay Bm = t; 4249371c9d4SSatish Balay } 425dd460d27SBarry Smith if (product->type == MATPRODUCT_AtB) An = Am; 426dd460d27SBarry Smith 4279371c9d4SSatish Balay PetscCheck(An == Bm, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Matrix dimensions of A and %s are incompatible for MatProductType %s: A %" PetscInt_FMT "x%" PetscInt_FMT ", %s %" PetscInt_FMT "x%" PetscInt_FMT, bname, 4289371c9d4SSatish Balay MatProductTypes[product->type], A->rmap->N, A->cmap->N, bname, B->rmap->N, B->cmap->N); 4299371c9d4SSatish Balay PetscCheck(!Cm || Cm == Bn, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Matrix dimensions of B and C are incompatible for MatProductType %s: B %" PetscInt_FMT "x%" PetscInt_FMT ", C %" PetscInt_FMT "x%" PetscInt_FMT, 4309371c9d4SSatish Balay MatProductTypes[product->type], B->rmap->N, B->cmap->N, Cm, Cn); 4314222ddf1SHong Zhang 4324222ddf1SHong Zhang fA = A->ops->productsetfromoptions; 4334222ddf1SHong Zhang fB = B->ops->productsetfromoptions; 4346718818eSStefano Zampini fC = C ? C->ops->productsetfromoptions : fA; 4356718818eSStefano Zampini if (C) { 4369566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, "MatProductType %s for A %s, %s %s, C %s\n", MatProductTypes[product->type], ((PetscObject)A)->type_name, bname, ((PetscObject)B)->type_name, ((PetscObject)C)->type_name)); 4376718818eSStefano Zampini } else { 4389566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, "MatProductType %s for A %s, %s %s\n", MatProductTypes[product->type], ((PetscObject)A)->type_name, bname, ((PetscObject)B)->type_name)); 4396718818eSStefano Zampini } 4404222ddf1SHong Zhang if (fA == fB && fA == fC && fA) { 4419566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " matching op\n")); 4429566063dSJacob Faibussowitsch PetscCall((*fA)(mat)); 4438d7b260cSStefano Zampini } 4448d7b260cSStefano Zampini /* We may have found f but it did not succeed */ 4458d7b260cSStefano Zampini if (!mat->ops->productsymbolic) { /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 4464222ddf1SHong Zhang char mtypes[256]; 4479566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_", sizeof(mtypes))); 4489566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)A)->type_name, sizeof(mtypes))); 4499566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4509566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)B)->type_name, sizeof(mtypes))); 4516718818eSStefano Zampini if (C) { 4529566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4539566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)C)->type_name, sizeof(mtypes))); 4546718818eSStefano Zampini } 4559566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_C", sizeof(mtypes))); 45615943bb8SPierre Jolivet #if defined(__clang__) 457a8f51744SPierre Jolivet PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat-pedantic") 45815943bb8SPierre Jolivet #elif defined(__GNUC__) || defined(__GNUG__) 459a8f51744SPierre Jolivet PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat") 46015943bb8SPierre Jolivet #endif 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4629566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4634222ddf1SHong Zhang if (!f) { 4649566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4659566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4664222ddf1SHong Zhang } 4676718818eSStefano Zampini if (!f && C) { 4689566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4699566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4704222ddf1SHong Zhang } 4719566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4726718818eSStefano Zampini 4736718818eSStefano Zampini /* We may have found f but it did not succeed */ 474013e2dc7SBarry Smith /* some matrices (i.e. MATTRANSPOSEVIRTUAL, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */ 4756718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4769566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_anytype_C", sizeof(mtypes))); 4779566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4789566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4796718818eSStefano Zampini if (!f) { 4809566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4819566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4826718818eSStefano Zampini } 4836718818eSStefano Zampini if (!f && C) { 4849566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4859566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4866718818eSStefano Zampini } 4876718818eSStefano Zampini } 4889566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4894222ddf1SHong Zhang } 490a8f51744SPierre Jolivet PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() 4916718818eSStefano Zampini /* We may have found f but it did not succeed */ 4926718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4936718818eSStefano Zampini /* we can still compute the product if B is of type dense */ 4946718818eSStefano Zampini if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) { 4956718818eSStefano Zampini PetscBool isdense; 4966718818eSStefano Zampini 4979566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 4986718818eSStefano Zampini if (isdense) { 4996718818eSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_X_Dense; 5009566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " using basic looping over columns of a dense matrix\n")); 5016718818eSStefano Zampini } 5025415d71bSStefano Zampini } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Unsafe() for triple products only */ 5036718818eSStefano Zampini /* 5046718818eSStefano Zampini TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if 5058d7b260cSStefano Zampini the combination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result 5066718818eSStefano Zampini before computing the symbolic phase 5076718818eSStefano Zampini */ 5089566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " symbolic product not supported, using MatProductSymbolic_Unsafe() implementation\n")); 5095415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_Unsafe; 5104222ddf1SHong Zhang } 5116718818eSStefano Zampini } 51248a46eb9SPierre Jolivet if (!mat->ops->productsymbolic) PetscCall(PetscInfo(mat, " symbolic product is not supported\n")); 5133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5144222ddf1SHong Zhang } 5154222ddf1SHong Zhang 516cb3ff29fSJose E. Roman /*@ 51727430b45SBarry Smith MatProductSetFromOptions - Sets the options for the computation of a matrix-matrix product operation where the type, 51827430b45SBarry Smith the algorithm etc are determined from the options database. 5194222ddf1SHong Zhang 52027430b45SBarry Smith Logically Collective 5214222ddf1SHong Zhang 5224222ddf1SHong Zhang Input Parameter: 52327430b45SBarry Smith . mat - the matrix whose values are computed via a matrix-matrix product operation 5244222ddf1SHong Zhang 5252ef1f0ffSBarry Smith Options Database Keys: 5262ef1f0ffSBarry Smith + -mat_product_clear - Clear intermediate data structures after `MatProductNumeric()` has been called 5272ef1f0ffSBarry Smith . -mat_product_algorithm <algorithm> - Sets the algorithm, see `MatProductAlgorithm` for possible values 5282ef1f0ffSBarry Smith - -mat_product_algorithm_backend_cpu - Use the CPU to perform the computation even if the matrix is a GPU matrix 5294222ddf1SHong Zhang 5306718818eSStefano Zampini Level: intermediate 5316718818eSStefano Zampini 53227430b45SBarry Smith Note: 5332ef1f0ffSBarry Smith The `-mat_product_clear` option reduces memory usage but means that the matrix cannot be re-used for a matrix-matrix product operation 53427430b45SBarry Smith 5351cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatSetFromOptions()`, `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductNumeric()`, 5362ef1f0ffSBarry Smith `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductAlgorithm` 5374222ddf1SHong Zhang @*/ 538d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions(Mat mat) 539d71ae5a4SJacob Faibussowitsch { 5404222ddf1SHong Zhang PetscFunctionBegin; 5414222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5426718818eSStefano Zampini MatCheckProduct(mat, 1); 543a0228903SHong Zhang PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot call MatProductSetFromOptions() with already present data"); 544a0228903SHong Zhang mat->product->setfromoptionscalled = PETSC_TRUE; 545d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)mat); 5469566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_product_clear", "Clear intermediate data structures after MatProductNumeric() has been called", "MatProductClear", mat->product->clear, &mat->product->clear, NULL)); 5479566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-mat_freeintermediatedatastructures", "-mat_product_clear", "3.13", "Or call MatProductClear() after MatProductNumeric()")); 548d0609cedSBarry Smith PetscOptionsEnd(); 5499566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Private(mat)); 55028b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing product after setup phase"); 5513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5526718818eSStefano Zampini } 5536718818eSStefano Zampini 554ffeef943SBarry Smith /*@ 55527430b45SBarry Smith MatProductView - View the private matrix-matrix algorithm object within a matrix 5566718818eSStefano Zampini 557c3339decSBarry Smith Logically Collective 5586718818eSStefano Zampini 55967be906fSBarry Smith Input Parameters: 56067be906fSBarry Smith + mat - the matrix obtained with `MatProductCreate()` or `MatProductCreateWithMat()` 5612ef1f0ffSBarry Smith - viewer - where the information on the matrix-matrix algorithm of `mat` should be reviewed 5626718818eSStefano Zampini 5636718818eSStefano Zampini Level: intermediate 5646718818eSStefano Zampini 565ffeef943SBarry Smith Developer Note: 566d7c1f440SPierre Jolivet Shouldn't this information be printed from an appropriate `MatView()` with perhaps certain formats set? 567ffeef943SBarry Smith 5681cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProductType`, `Mat`, `MatProductSetFromOptions()`, `MatView()`, `MatProductCreate()`, `MatProductCreateWithMat()` 5696718818eSStefano Zampini @*/ 570d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductView(Mat mat, PetscViewer viewer) 571d71ae5a4SJacob Faibussowitsch { 5726718818eSStefano Zampini PetscFunctionBegin; 5736718818eSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5743ba16761SJacob Faibussowitsch if (!mat->product) PetscFunctionReturn(PETSC_SUCCESS); 5759566063dSJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 5766718818eSStefano Zampini PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 5776718818eSStefano Zampini PetscCheckSameComm(mat, 1, viewer, 2); 5781baa6e33SBarry Smith if (mat->product->view) PetscCall((*mat->product->view)(mat, viewer)); 5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5804222ddf1SHong Zhang } 5814222ddf1SHong Zhang 5826718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 5836718818eSStefano Zampini * they are dangerous and should be removed in the future */ 584d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_AB(Mat mat) 585d71ae5a4SJacob Faibussowitsch { 5864222ddf1SHong Zhang Mat_Product *product = mat->product; 5874222ddf1SHong Zhang Mat A = product->A, B = product->B; 5884222ddf1SHong Zhang 5894222ddf1SHong Zhang PetscFunctionBegin; 5909566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, B, mat)); 5913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5924222ddf1SHong Zhang } 5934222ddf1SHong Zhang 594d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_AtB(Mat mat) 595d71ae5a4SJacob Faibussowitsch { 5964222ddf1SHong Zhang Mat_Product *product = mat->product; 5974222ddf1SHong Zhang Mat A = product->A, B = product->B; 5984222ddf1SHong Zhang 5994222ddf1SHong Zhang PetscFunctionBegin; 6009566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultnumeric)(A, B, mat)); 6013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6024222ddf1SHong Zhang } 6034222ddf1SHong Zhang 604d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_ABt(Mat mat) 605d71ae5a4SJacob Faibussowitsch { 6064222ddf1SHong Zhang Mat_Product *product = mat->product; 6074222ddf1SHong Zhang Mat A = product->A, B = product->B; 6084222ddf1SHong Zhang 6094222ddf1SHong Zhang PetscFunctionBegin; 6109566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultnumeric)(A, B, mat)); 6113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6124222ddf1SHong Zhang } 6134222ddf1SHong Zhang 614d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_PtAP(Mat mat) 615d71ae5a4SJacob Faibussowitsch { 6164222ddf1SHong Zhang Mat_Product *product = mat->product; 6174222ddf1SHong Zhang Mat A = product->A, B = product->B; 6184222ddf1SHong Zhang 6194222ddf1SHong Zhang PetscFunctionBegin; 6209566063dSJacob Faibussowitsch PetscCall((*mat->ops->ptapnumeric)(A, B, mat)); 6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6224222ddf1SHong Zhang } 6234222ddf1SHong Zhang 624d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_RARt(Mat mat) 625d71ae5a4SJacob Faibussowitsch { 6264222ddf1SHong Zhang Mat_Product *product = mat->product; 6274222ddf1SHong Zhang Mat A = product->A, B = product->B; 6284222ddf1SHong Zhang 6294222ddf1SHong Zhang PetscFunctionBegin; 6309566063dSJacob Faibussowitsch PetscCall((*mat->ops->rartnumeric)(A, B, mat)); 6313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6324222ddf1SHong Zhang } 6334222ddf1SHong Zhang 634d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_ABC(Mat mat) 635d71ae5a4SJacob Faibussowitsch { 6364222ddf1SHong Zhang Mat_Product *product = mat->product; 6374222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 6384222ddf1SHong Zhang 6394222ddf1SHong Zhang PetscFunctionBegin; 6409566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultnumeric)(A, B, C, mat)); 6413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6424222ddf1SHong Zhang } 6434222ddf1SHong Zhang 6444222ddf1SHong Zhang /*@ 6452ef1f0ffSBarry Smith MatProductNumeric - Compute a matrix-matrix product operation with the numerical values 6464222ddf1SHong Zhang 647c3339decSBarry Smith Collective 6484222ddf1SHong Zhang 6496718818eSStefano Zampini Input/Output Parameter: 65027430b45SBarry Smith . mat - the matrix whose values are computed via a matrix-matrix product operation 6514222ddf1SHong Zhang 6524222ddf1SHong Zhang Level: intermediate 6534222ddf1SHong Zhang 65411a5261eSBarry Smith Note: 65527430b45SBarry Smith `MatProductSymbolic()` must have been called on `mat` before calling this function 6566718818eSStefano Zampini 6571cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductSetAlgorithm()`, `MatProductSetType()`, `MatProductCreate()`, `MatSetType()`, `MatProductSymbolic()` 6584222ddf1SHong Zhang @*/ 659d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric(Mat mat) 660d71ae5a4SJacob Faibussowitsch { 661e017e560SStefano Zampini PetscLogEvent eventtype = -1; 6624222ddf1SHong Zhang 6634222ddf1SHong Zhang PetscFunctionBegin; 6644222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6656718818eSStefano Zampini MatCheckProduct(mat, 1); 666e017e560SStefano Zampini switch (mat->product->type) { 667d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 668d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMultNumeric; 669d71ae5a4SJacob Faibussowitsch break; 670d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 671d71ae5a4SJacob Faibussowitsch eventtype = MAT_TransposeMatMultNumeric; 672d71ae5a4SJacob Faibussowitsch break; 673d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 674d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatTransposeMultNumeric; 675d71ae5a4SJacob Faibussowitsch break; 676d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 677d71ae5a4SJacob Faibussowitsch eventtype = MAT_PtAPNumeric; 678d71ae5a4SJacob Faibussowitsch break; 679d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 680d71ae5a4SJacob Faibussowitsch eventtype = MAT_RARtNumeric; 681d71ae5a4SJacob Faibussowitsch break; 682d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 683d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMatMultNumeric; 684d71ae5a4SJacob Faibussowitsch break; 685d71ae5a4SJacob Faibussowitsch default: 686d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 687e017e560SStefano Zampini } 6888d7b260cSStefano Zampini 6894222ddf1SHong Zhang if (mat->ops->productnumeric) { 6909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 691dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 6929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 693cf3d31aeSPierre Jolivet } else if (mat->product) { 6942e105a96SStefano Zampini char errstr[256]; 6952e105a96SStefano Zampini 6962e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 6979566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(errstr, 256, "%s with A %s, B %s, C %s", MatProductTypes[mat->product->type], ((PetscObject)mat->product->A)->type_name, ((PetscObject)mat->product->B)->type_name, ((PetscObject)mat->product->C)->type_name)); 6982e105a96SStefano Zampini } else { 6999566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(errstr, 256, "%s with A %s, B %s", MatProductTypes[mat->product->type], ((PetscObject)mat->product->A)->type_name, ((PetscObject)mat->product->B)->type_name)); 7002e105a96SStefano Zampini } 701cf3d31aeSPierre Jolivet SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified numeric phase for product %s", errstr); 7022e105a96SStefano Zampini } 703cf3d31aeSPierre Jolivet PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after numeric phase for product"); 7042e105a96SStefano Zampini 7051baa6e33SBarry Smith if (mat->product->clear) PetscCall(MatProductClear(mat)); 7069566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 7073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7084222ddf1SHong Zhang } 7094222ddf1SHong Zhang 7106718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 7116718818eSStefano Zampini * they are dangerous and should be removed in the future */ 712d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_AB(Mat mat) 713d71ae5a4SJacob Faibussowitsch { 7144222ddf1SHong Zhang Mat_Product *product = mat->product; 7154222ddf1SHong Zhang Mat A = product->A, B = product->B; 7164222ddf1SHong Zhang 7174222ddf1SHong Zhang PetscFunctionBegin; 7189566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultsymbolic)(A, B, product->fill, mat)); 7194222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AB; 7203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7214222ddf1SHong Zhang } 7224222ddf1SHong Zhang 723d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_AtB(Mat mat) 724d71ae5a4SJacob Faibussowitsch { 7254222ddf1SHong Zhang Mat_Product *product = mat->product; 7264222ddf1SHong Zhang Mat A = product->A, B = product->B; 7274222ddf1SHong Zhang 7284222ddf1SHong Zhang PetscFunctionBegin; 7299566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultsymbolic)(A, B, product->fill, mat)); 7304222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AtB; 7313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7324222ddf1SHong Zhang } 7334222ddf1SHong Zhang 734d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABt(Mat mat) 735d71ae5a4SJacob Faibussowitsch { 7364222ddf1SHong Zhang Mat_Product *product = mat->product; 7374222ddf1SHong Zhang Mat A = product->A, B = product->B; 7384222ddf1SHong Zhang 7394222ddf1SHong Zhang PetscFunctionBegin; 7409566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultsymbolic)(A, B, product->fill, mat)); 7414222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABt; 7423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7434222ddf1SHong Zhang } 7444222ddf1SHong Zhang 745d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABC(Mat mat) 746d71ae5a4SJacob Faibussowitsch { 7474222ddf1SHong Zhang Mat_Product *product = mat->product; 7484222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 7494222ddf1SHong Zhang 7504222ddf1SHong Zhang PetscFunctionBegin; 7519566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultsymbolic)(A, B, C, product->fill, mat)); 7524222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABC; 7533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7544222ddf1SHong Zhang } 7554222ddf1SHong Zhang 7564222ddf1SHong Zhang /*@ 7572ef1f0ffSBarry Smith MatProductSymbolic - Perform the symbolic portion of a matrix-matrix product operation, this creates a data structure for use with the numerical 7582ef1f0ffSBarry Smith product to be done with `MatProductNumeric()` 7594222ddf1SHong Zhang 760c3339decSBarry Smith Collective 7614222ddf1SHong Zhang 7626718818eSStefano Zampini Input/Output Parameter: 7632ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 7644222ddf1SHong Zhang 7654222ddf1SHong Zhang Level: intermediate 7664222ddf1SHong Zhang 76711a5261eSBarry Smith Note: 76827430b45SBarry Smith `MatProductSetFromOptions()` must have been called on `mat` before calling this function 7696718818eSStefano Zampini 7701cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductSetFromOptions()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 7714222ddf1SHong Zhang @*/ 772d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic(Mat mat) 773d71ae5a4SJacob Faibussowitsch { 7744222ddf1SHong Zhang PetscLogEvent eventtype = -1; 7752e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 77639cfb508SMark Adams Mat_Product *product = mat->product; 77739cfb508SMark Adams Mat A = product->A; 77839cfb508SMark Adams Mat B = product->B; 77939cfb508SMark Adams Mat C = product->C; 7804222ddf1SHong Zhang 7814222ddf1SHong Zhang PetscFunctionBegin; 7824222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7836718818eSStefano Zampini MatCheckProduct(mat, 1); 78428b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot run symbolic phase. Product data not empty"); 7856718818eSStefano Zampini switch (mat->product->type) { 786d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 787d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMultSymbolic; 788d71ae5a4SJacob Faibussowitsch break; 789d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 790d71ae5a4SJacob Faibussowitsch eventtype = MAT_TransposeMatMultSymbolic; 791d71ae5a4SJacob Faibussowitsch break; 792d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 793d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatTransposeMultSymbolic; 794d71ae5a4SJacob Faibussowitsch break; 795d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 796d71ae5a4SJacob Faibussowitsch eventtype = MAT_PtAPSymbolic; 797d71ae5a4SJacob Faibussowitsch break; 798d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 799d71ae5a4SJacob Faibussowitsch eventtype = MAT_RARtSymbolic; 800d71ae5a4SJacob Faibussowitsch break; 801d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 802d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMatMultSymbolic; 803d71ae5a4SJacob Faibussowitsch break; 804d71ae5a4SJacob Faibussowitsch default: 805d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 8064222ddf1SHong Zhang } 8076718818eSStefano Zampini mat->ops->productnumeric = NULL; 8084222ddf1SHong Zhang if (mat->ops->productsymbolic) { 8099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 810dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 8119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 8122e105a96SStefano Zampini } else missing = PETSC_TRUE; 8132e105a96SStefano Zampini if (missing || !mat->product || !mat->ops->productnumeric) { 8142e105a96SStefano Zampini char errstr[256]; 8152e105a96SStefano Zampini 8162e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 8179566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(errstr, 256, "%s with A %s, B %s, C %s", MatProductTypes[mat->product->type], ((PetscObject)mat->product->A)->type_name, ((PetscObject)mat->product->B)->type_name, ((PetscObject)mat->product->C)->type_name)); 8182e105a96SStefano Zampini } else { 8199566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(errstr, 256, "%s with A %s, B %s", MatProductTypes[mat->product->type], ((PetscObject)mat->product->A)->type_name, ((PetscObject)mat->product->B)->type_name)); 8202e105a96SStefano Zampini } 821a0228903SHong Zhang PetscCheck(mat->product->setfromoptionscalled, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified symbolic phase for product %s. Call MatProductSetFromOptions() first", errstr); 822a0228903SHong Zhang PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Unspecified symbolic phase for product %s. The product is not supported", errstr); 82328b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 8242e105a96SStefano Zampini } 8253742c8caSstefanozampini #if defined(PETSC_HAVE_DEVICE) 8263742c8caSstefanozampini PetscBool bindingpropagates; 8273742c8caSstefanozampini bindingpropagates = (PetscBool)((A->boundtocpu && A->bindingpropagates) || (B->boundtocpu && B->bindingpropagates)); 8283742c8caSstefanozampini if (C) bindingpropagates = (PetscBool)(bindingpropagates || (C->boundtocpu && C->bindingpropagates)); 8293742c8caSstefanozampini if (bindingpropagates) { 8303742c8caSstefanozampini PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 8313742c8caSstefanozampini PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE)); 8323742c8caSstefanozampini } 8333742c8caSstefanozampini #endif 83439cfb508SMark Adams /* set block sizes */ 83539cfb508SMark Adams switch (product->type) { 83639cfb508SMark Adams case MATPRODUCT_PtAP: 83739cfb508SMark Adams if (B->cmap->bs > 1) PetscCall(MatSetBlockSizes(mat, B->cmap->bs, B->cmap->bs)); 83839cfb508SMark Adams break; 83939cfb508SMark Adams case MATPRODUCT_RARt: 84039cfb508SMark Adams if (B->rmap->bs > 1) PetscCall(MatSetBlockSizes(mat, B->rmap->bs, B->rmap->bs)); 84139cfb508SMark Adams break; 84239cfb508SMark Adams case MATPRODUCT_ABC: 84339cfb508SMark Adams PetscCall(MatSetBlockSizesFromMats(mat, A, C)); 84439cfb508SMark Adams break; 84539cfb508SMark Adams case MATPRODUCT_AB: 84639cfb508SMark Adams PetscCall(MatSetBlockSizesFromMats(mat, A, B)); 84739cfb508SMark Adams break; 84839cfb508SMark Adams case MATPRODUCT_AtB: 84939cfb508SMark Adams if (A->cmap->bs > 1 || B->cmap->bs > 1) PetscCall(MatSetBlockSizes(mat, A->cmap->bs, B->cmap->bs)); 85039cfb508SMark Adams break; 85139cfb508SMark Adams case MATPRODUCT_ABt: 85239cfb508SMark Adams if (A->rmap->bs > 1 || B->rmap->bs > 1) PetscCall(MatSetBlockSizes(mat, A->rmap->bs, B->rmap->bs)); 85339cfb508SMark Adams break; 85439cfb508SMark Adams default: 85539cfb508SMark Adams SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 85639cfb508SMark Adams } 8573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8584222ddf1SHong Zhang } 8594222ddf1SHong Zhang 8604222ddf1SHong Zhang /*@ 86127430b45SBarry Smith MatProductSetFill - Set an expected fill of the matrix whose values are computed via a matrix-matrix product operation 8624222ddf1SHong Zhang 86327430b45SBarry Smith Collective 8644222ddf1SHong Zhang 8654222ddf1SHong Zhang Input Parameters: 8662ef1f0ffSBarry Smith + mat - the matrix whose values are to be computed via a matrix-matrix product operation 867fb842aefSJose E. Roman - fill - expected fill as ratio of nnz(mat)/(nnz(A) + nnz(B) + nnz(C)); use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate. 86827430b45SBarry Smith If the product is a dense matrix, this value is not used. 8694222ddf1SHong Zhang 8704222ddf1SHong Zhang Level: intermediate 8714222ddf1SHong Zhang 872fb842aefSJose E. Roman Notes: 873fb842aefSJose E. Roman Use `fill` of `PETSC_DETERMINE` to use the default value. 874fb842aefSJose E. Roman 875fb842aefSJose E. Roman The deprecated `PETSC_DEFAULT` is also supported to mean use the current value. 876fb842aefSJose E. Roman 877fb842aefSJose E. Roman .seealso: [](ch_matrices), `MatProduct`, `PETSC_DETERMINE`, `Mat`, `MatProductSetFromOptions()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 8784222ddf1SHong Zhang @*/ 879d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFill(Mat mat, PetscReal fill) 880d71ae5a4SJacob Faibussowitsch { 8814222ddf1SHong Zhang PetscFunctionBegin; 8824222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8836718818eSStefano Zampini MatCheckProduct(mat, 1); 884fb842aefSJose E. Roman if (fill == (PetscReal)PETSC_DETERMINE) mat->product->fill = mat->product->default_fill; 885fb842aefSJose E. Roman else if (fill != (PetscReal)PETSC_CURRENT) mat->product->fill = fill; 8863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8874222ddf1SHong Zhang } 8884222ddf1SHong Zhang 8895d83a8b1SBarry Smith /*@ 89027430b45SBarry Smith MatProductSetAlgorithm - Requests a particular algorithm for a matrix-matrix product operation that will perform to compute the given matrix 8914222ddf1SHong Zhang 892c3339decSBarry Smith Collective 8934222ddf1SHong Zhang 8944222ddf1SHong Zhang Input Parameters: 89527430b45SBarry Smith + mat - the matrix whose values are computed via a matrix-matrix product operation 896f5368d60SBarry Smith - alg - particular implementation algorithm of the matrix product, e.g., `MATPRODUCTALGORITHMDEFAULT`. 8973e662e0bSHong Zhang 8983e662e0bSHong Zhang Options Database Key: 8992ef1f0ffSBarry Smith . -mat_product_algorithm <algorithm> - Sets the algorithm, see `MatProductAlgorithm` 9004222ddf1SHong Zhang 9014222ddf1SHong Zhang Level: intermediate 9024222ddf1SHong Zhang 9038fcac130SJose E. Roman .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductClear()`, `MatProductSetType()`, `MatProductSetFill()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MatProductGetAlgorithm()` 9044222ddf1SHong Zhang @*/ 905d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetAlgorithm(Mat mat, MatProductAlgorithm alg) 906d71ae5a4SJacob Faibussowitsch { 9074222ddf1SHong Zhang PetscFunctionBegin; 9084222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9096718818eSStefano Zampini MatCheckProduct(mat, 1); 9109566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product->alg)); 9119566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(alg, &mat->product->alg)); 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9134222ddf1SHong Zhang } 9144222ddf1SHong Zhang 9155d83a8b1SBarry Smith /*@ 9168fcac130SJose E. Roman MatProductGetAlgorithm - Returns the selected algorithm for a matrix-matrix product operation 9178fcac130SJose E. Roman 9188fcac130SJose E. Roman Not Collective 9198fcac130SJose E. Roman 9208fcac130SJose E. Roman Input Parameter: 9218fcac130SJose E. Roman . mat - the matrix whose values are computed via a matrix-matrix product operation 9228fcac130SJose E. Roman 9238fcac130SJose E. Roman Output Parameter: 9248fcac130SJose E. Roman . alg - the selected algorithm of the matrix product, e.g., `MATPRODUCTALGORITHMDEFAULT`. 9258fcac130SJose E. Roman 9268fcac130SJose E. Roman Level: intermediate 9278fcac130SJose E. Roman 9288fcac130SJose E. Roman .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductSetAlgorithm()` 9298fcac130SJose E. Roman @*/ 9308fcac130SJose E. Roman PetscErrorCode MatProductGetAlgorithm(Mat mat, MatProductAlgorithm *alg) 9318fcac130SJose E. Roman { 9328fcac130SJose E. Roman PetscFunctionBegin; 9338fcac130SJose E. Roman PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9348fcac130SJose E. Roman PetscAssertPointer(alg, 2); 9358fcac130SJose E. Roman if (mat->product) *alg = mat->product->alg; 9368fcac130SJose E. Roman else *alg = NULL; 9378fcac130SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 9388fcac130SJose E. Roman } 9398fcac130SJose E. Roman 9404222ddf1SHong Zhang /*@ 94127430b45SBarry Smith MatProductSetType - Sets a particular matrix-matrix product operation to be used to compute the values of the given matrix 9424222ddf1SHong Zhang 943c3339decSBarry Smith Collective 9444222ddf1SHong Zhang 9454222ddf1SHong Zhang Input Parameters: 94627430b45SBarry Smith + mat - the matrix whose values are computed via a matrix-matrix product operation 9472ef1f0ffSBarry Smith - productype - matrix product type, e.g., `MATPRODUCT_AB`,`MATPRODUCT_AtB`,`MATPRODUCT_ABt`,`MATPRODUCT_PtAP`,`MATPRODUCT_RARt`,`MATPRODUCT_ABC`, 9482ef1f0ffSBarry Smith see `MatProductType` 9494222ddf1SHong Zhang 9504222ddf1SHong Zhang Level: intermediate 9514222ddf1SHong Zhang 952f5368d60SBarry Smith Note: 95311a5261eSBarry Smith The small t represents the transpose operation. 954f5368d60SBarry Smith 955fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreate()`, `MatProductType`, 95611a5261eSBarry Smith `MATPRODUCT_AB`, `MATPRODUCT_AtB`, `MATPRODUCT_ABt`, `MATPRODUCT_PtAP`, `MATPRODUCT_RARt`, `MATPRODUCT_ABC` 9574222ddf1SHong Zhang @*/ 958d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetType(Mat mat, MatProductType productype) 959d71ae5a4SJacob Faibussowitsch { 9604222ddf1SHong Zhang PetscFunctionBegin; 9614222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9626718818eSStefano Zampini MatCheckProduct(mat, 1); 9637a3c3d58SStefano Zampini PetscValidLogicalCollectiveEnum(mat, productype, 2); 9646718818eSStefano Zampini if (productype != mat->product->type) { 965*cc1eb50dSBarry Smith if (mat->product->destroy) PetscCall((*mat->product->destroy)(&mat->product->data)); 9666718818eSStefano Zampini mat->product->destroy = NULL; 9676718818eSStefano Zampini mat->product->data = NULL; 9686718818eSStefano Zampini mat->ops->productsymbolic = NULL; 9696718818eSStefano Zampini mat->ops->productnumeric = NULL; 9706718818eSStefano Zampini } 9716718818eSStefano Zampini mat->product->type = productype; 9723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9734222ddf1SHong Zhang } 9744222ddf1SHong Zhang 9754417c5e8SHong Zhang /*@ 9762ef1f0ffSBarry Smith MatProductClear - Clears from the matrix any internal data structures related to the computation of the values of the matrix from matrix-matrix product operations 9774417c5e8SHong Zhang 978c3339decSBarry Smith Collective 9794417c5e8SHong Zhang 9802fe279fdSBarry Smith Input Parameter: 9812ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 98227430b45SBarry Smith 98327430b45SBarry Smith Options Database Key: 98427430b45SBarry Smith . -mat_product_clear - Clear intermediate data structures after `MatProductNumeric()` has been called 9854417c5e8SHong Zhang 9864417c5e8SHong Zhang Level: intermediate 9876718818eSStefano Zampini 988f5368d60SBarry Smith Notes: 989f5368d60SBarry Smith This function should be called to remove any intermediate data used to compute the matrix to free up memory. 990f5368d60SBarry Smith 99127430b45SBarry Smith After having called this function, matrix-matrix product operations can no longer be used on `mat` 992f5368d60SBarry Smith 9931cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreate()` 9944417c5e8SHong Zhang @*/ 995d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductClear(Mat mat) 996d71ae5a4SJacob Faibussowitsch { 9974417c5e8SHong Zhang Mat_Product *product = mat->product; 9984417c5e8SHong Zhang 9994417c5e8SHong Zhang PetscFunctionBegin; 10007a3c3d58SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10014417c5e8SHong Zhang if (product) { 10029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 10039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 10049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 10059566063dSJacob Faibussowitsch PetscCall(PetscFree(product->alg)); 10069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork)); 1007*cc1eb50dSBarry Smith if (product->destroy) PetscCall((*product->destroy)(&product->data)); 10086718818eSStefano Zampini } 10099566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product)); 10106718818eSStefano Zampini mat->ops->productsymbolic = NULL; 10116718818eSStefano Zampini mat->ops->productnumeric = NULL; 10123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10134417c5e8SHong Zhang } 10144417c5e8SHong Zhang 10154222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */ 1016d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate_Private(Mat A, Mat B, Mat C, Mat D) 1017d71ae5a4SJacob Faibussowitsch { 10184222ddf1SHong Zhang Mat_Product *product = NULL; 10194222ddf1SHong Zhang 10204222ddf1SHong Zhang PetscFunctionBegin; 10216718818eSStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 102228b400f6SJacob Faibussowitsch PetscCheck(!D->product, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product already present"); 10234dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&product)); 10244222ddf1SHong Zhang product->A = A; 10254222ddf1SHong Zhang product->B = B; 10264222ddf1SHong Zhang product->C = C; 10276718818eSStefano Zampini product->type = MATPRODUCT_UNSPECIFIED; 10284222ddf1SHong Zhang product->Dwork = NULL; 10294222ddf1SHong Zhang product->api_user = PETSC_FALSE; 10306718818eSStefano Zampini product->clear = PETSC_FALSE; 1031a0228903SHong Zhang product->setfromoptionscalled = PETSC_FALSE; 1032fb842aefSJose E. Roman PetscObjectParameterSetDefault(product, fill, 2); 10334222ddf1SHong Zhang D->product = product; 10344417c5e8SHong Zhang 10359566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(D, MATPRODUCTALGORITHMDEFAULT)); 10369566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(D, PETSC_DEFAULT)); 10377a3c3d58SStefano Zampini 10389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 10399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 10409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 10413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10424222ddf1SHong Zhang } 10434222ddf1SHong Zhang 10444222ddf1SHong Zhang /*@ 10452ef1f0ffSBarry Smith MatProductCreateWithMat - Set a given matrix to have its values computed via matrix-matrix operations on other matrices. 10464222ddf1SHong Zhang 104727430b45SBarry Smith Collective 10484222ddf1SHong Zhang 10494222ddf1SHong Zhang Input Parameters: 10504222ddf1SHong Zhang + A - the first matrix 10514222ddf1SHong Zhang . B - the second matrix 105267be906fSBarry Smith . C - the third matrix (optional, use `NULL` if not needed) 10532ef1f0ffSBarry Smith - D - the matrix whose values are to be computed via a matrix-matrix product operation 10544222ddf1SHong Zhang 105567be906fSBarry Smith Level: intermediate 10564222ddf1SHong Zhang 10576718818eSStefano Zampini Notes: 105827430b45SBarry Smith Use `MatProductCreate()` if the matrix you wish computed (the `D` matrix) does not already exist 1059f5368d60SBarry Smith 106027430b45SBarry Smith See `MatProductCreate()` for details on the usage of the matrix-matrix product operations 1061f5368d60SBarry Smith 106267be906fSBarry Smith Any product data currently attached to `D` will be cleared 10636718818eSStefano Zampini 10641cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductType`, `MatProductSetType()`, `MatProductAlgorithm`, 10652ef1f0ffSBarry Smith `MatProductSetAlgorithm`, `MatProductCreate()`, `MatProductClear()` 10664222ddf1SHong Zhang @*/ 1067d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreateWithMat(Mat A, Mat B, Mat C, Mat D) 1068d71ae5a4SJacob Faibussowitsch { 10694222ddf1SHong Zhang PetscFunctionBegin; 10704222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10714222ddf1SHong Zhang PetscValidType(A, 1); 10724222ddf1SHong Zhang MatCheckPreallocated(A, 1); 107328b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 107428b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10754222ddf1SHong Zhang 10764222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10774222ddf1SHong Zhang PetscValidType(B, 2); 10784222ddf1SHong Zhang MatCheckPreallocated(B, 2); 107928b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 108028b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10814222ddf1SHong Zhang 10824222ddf1SHong Zhang if (C) { 10834222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 10844222ddf1SHong Zhang PetscValidType(C, 3); 10854222ddf1SHong Zhang MatCheckPreallocated(C, 3); 108628b400f6SJacob Faibussowitsch PetscCheck(C->assembled, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 108728b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10884222ddf1SHong Zhang } 10894222ddf1SHong Zhang 10904222ddf1SHong Zhang PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 10914222ddf1SHong Zhang PetscValidType(D, 4); 10924222ddf1SHong Zhang MatCheckPreallocated(D, 4); 109328b400f6SJacob Faibussowitsch PetscCheck(D->assembled, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 109428b400f6SJacob Faibussowitsch PetscCheck(!D->factortype, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10954222ddf1SHong Zhang 10964222ddf1SHong Zhang /* Create a supporting struct and attach it to D */ 10979566063dSJacob Faibussowitsch PetscCall(MatProductClear(D)); 10989566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, D)); 10993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11004222ddf1SHong Zhang } 11014222ddf1SHong Zhang 11024222ddf1SHong Zhang /*@ 110311a5261eSBarry Smith MatProductCreate - create a matrix to hold the result of a matrix-matrix product operation 11044222ddf1SHong Zhang 110527430b45SBarry Smith Collective 11064222ddf1SHong Zhang 11074222ddf1SHong Zhang Input Parameters: 11084222ddf1SHong Zhang + A - the first matrix 11094222ddf1SHong Zhang . B - the second matrix 11102ef1f0ffSBarry Smith - C - the third matrix (or `NULL`) 11114222ddf1SHong Zhang 11122fe279fdSBarry Smith Output Parameter: 11132ef1f0ffSBarry Smith . D - the matrix whose values are to be computed via a matrix-matrix product operation 11144222ddf1SHong Zhang 11154222ddf1SHong Zhang Level: intermediate 11164222ddf1SHong Zhang 111727430b45SBarry Smith Example: 1118f5368d60SBarry Smith .vb 111911a5261eSBarry Smith MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 112011a5261eSBarry Smith MatProductSetType(D, MATPRODUCT_AB or MATPRODUCT_AtB or MATPRODUCT_ABt or MATPRODUCT_PtAP or MATPRODUCT_RARt or MATPRODUCT_ABC) 112111a5261eSBarry Smith MatProductSetAlgorithm(D, alg) 112211a5261eSBarry Smith MatProductSetFill(D,fill) 112311a5261eSBarry Smith MatProductSetFromOptions(D) 112411a5261eSBarry Smith MatProductSymbolic(D) 112511a5261eSBarry Smith MatProductNumeric(D) 1126f5368d60SBarry Smith Change numerical values in some of the matrices 112711a5261eSBarry Smith MatProductNumeric(D) 1128f5368d60SBarry Smith .ve 1129f5368d60SBarry Smith 1130f5368d60SBarry Smith Notes: 113127430b45SBarry Smith Use `MatProductCreateWithMat()` if the matrix you wish computed, the `D` matrix, already exists. 1132f5368d60SBarry Smith 1133f5368d60SBarry Smith The information computed during the symbolic stage can be reused for new numerical computations with the same non-zero structure 1134f5368d60SBarry Smith 1135fe59aa6dSJacob Faibussowitsch Developer Notes: 1136f5368d60SBarry Smith It is undocumented what happens if the nonzero structure of the input matrices changes. Is the symbolic stage automatically redone? Does it crash? 1137f5368d60SBarry Smith Is there error checking for it? 1138f5368d60SBarry Smith 11391cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductClear()` 11404222ddf1SHong Zhang @*/ 1141d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate(Mat A, Mat B, Mat C, Mat *D) 1142d71ae5a4SJacob Faibussowitsch { 11434222ddf1SHong Zhang PetscFunctionBegin; 11444222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11454222ddf1SHong Zhang PetscValidType(A, 1); 11464222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11474222ddf1SHong Zhang PetscValidType(B, 2); 114828b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix A"); 114928b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix B"); 11504222ddf1SHong Zhang 11514222ddf1SHong Zhang if (C) { 11524222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 11534222ddf1SHong Zhang PetscValidType(C, 3); 115428b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix C"); 11554222ddf1SHong Zhang } 11564222ddf1SHong Zhang 11574f572ea9SToby Isaac PetscAssertPointer(D, 4); 11589566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), D)); 115930203840SJunchao Zhang /* Delay setting type of D to the MatProduct symbolic phase, as we allow sparse A and dense B */ 11609566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, *D)); 11613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11624222ddf1SHong Zhang } 11635415d71bSStefano Zampini 11645415d71bSStefano Zampini /* 11655415d71bSStefano Zampini These are safe basic implementations of ABC, RARt and PtAP 11665415d71bSStefano Zampini that do not rely on mat->ops->matmatop function pointers. 11675415d71bSStefano Zampini They only use the MatProduct API and are currently used by 11685415d71bSStefano Zampini cuSPARSE and KOKKOS-KERNELS backends 11695415d71bSStefano Zampini */ 1170ec446438SStefano Zampini typedef struct { 11715415d71bSStefano Zampini Mat BC; 11725415d71bSStefano Zampini Mat ABC; 1173*cc1eb50dSBarry Smith } MatProductCtx_MatMatMatPrivate; 11745415d71bSStefano Zampini 1175*cc1eb50dSBarry Smith static PetscErrorCode MatProductCtxDestroy_MatMatMatPrivate(void **data) 1176d71ae5a4SJacob Faibussowitsch { 1177*cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmdata = *(MatProductCtx_MatMatMatPrivate **)data; 11785415d71bSStefano Zampini 11795415d71bSStefano Zampini PetscFunctionBegin; 11809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->BC)); 11819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->ABC)); 1182*cc1eb50dSBarry Smith PetscCall(PetscFree(*data)); 11833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11845415d71bSStefano Zampini } 11855415d71bSStefano Zampini 1186d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 1187d71ae5a4SJacob Faibussowitsch { 11885415d71bSStefano Zampini Mat_Product *product = mat->product; 1189*cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmabc; 11905415d71bSStefano Zampini 11915415d71bSStefano Zampini PetscFunctionBegin; 11925415d71bSStefano Zampini MatCheckProduct(mat, 1); 119328b400f6SJacob Faibussowitsch PetscCheck(mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data empty"); 1194*cc1eb50dSBarry Smith mmabc = (MatProductCtx_MatMatMatPrivate *)mat->product->data; 119528b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productnumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing numeric stage"); 1196ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 11979566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productnumeric)(mmabc->BC)); 11985415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the numeric phase on mat */ 11995415d71bSStefano Zampini mat->product = mmabc->ABC->product; 12005415d71bSStefano Zampini mat->ops->productnumeric = mmabc->ABC->ops->productnumeric; 1201ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 1202dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 12035415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 12045415d71bSStefano Zampini mat->product = product; 12053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12065415d71bSStefano Zampini } 12075415d71bSStefano Zampini 1208d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 1209d71ae5a4SJacob Faibussowitsch { 12105415d71bSStefano Zampini Mat_Product *product = mat->product; 12115415d71bSStefano Zampini Mat A, B, C; 12125415d71bSStefano Zampini MatProductType p1, p2; 1213*cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmabc; 121465e4b4d4SStefano Zampini const char *prefix; 12155415d71bSStefano Zampini 12165415d71bSStefano Zampini PetscFunctionBegin; 12175415d71bSStefano Zampini MatCheckProduct(mat, 1); 121828b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data not empty"); 12199566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(mat, &prefix)); 12209566063dSJacob Faibussowitsch PetscCall(PetscNew(&mmabc)); 12215415d71bSStefano Zampini product->data = mmabc; 1222*cc1eb50dSBarry Smith product->destroy = MatProductCtxDestroy_MatMatMatPrivate; 12235415d71bSStefano Zampini switch (product->type) { 12245415d71bSStefano Zampini case MATPRODUCT_PtAP: 12255415d71bSStefano Zampini p1 = MATPRODUCT_AB; 12265415d71bSStefano Zampini p2 = MATPRODUCT_AtB; 12275415d71bSStefano Zampini A = product->B; 12285415d71bSStefano Zampini B = product->A; 12295415d71bSStefano Zampini C = product->B; 123039cfb508SMark Adams if (A->cmap->bs > 0 && C->cmap->bs > 0) PetscCall(MatSetBlockSizes(mat, A->cmap->bs, C->cmap->bs)); 12315415d71bSStefano Zampini break; 12325415d71bSStefano Zampini case MATPRODUCT_RARt: 12335415d71bSStefano Zampini p1 = MATPRODUCT_ABt; 12345415d71bSStefano Zampini p2 = MATPRODUCT_AB; 12355415d71bSStefano Zampini A = product->B; 12365415d71bSStefano Zampini B = product->A; 12375415d71bSStefano Zampini C = product->B; 123839cfb508SMark Adams if (A->rmap->bs > 0 && C->rmap->bs > 0) PetscCall(MatSetBlockSizes(mat, A->rmap->bs, C->rmap->bs)); 12395415d71bSStefano Zampini break; 12405415d71bSStefano Zampini case MATPRODUCT_ABC: 12415415d71bSStefano Zampini p1 = MATPRODUCT_AB; 12425415d71bSStefano Zampini p2 = MATPRODUCT_AB; 12435415d71bSStefano Zampini A = product->A; 12445415d71bSStefano Zampini B = product->B; 12455415d71bSStefano Zampini C = product->C; 12460e6a1e94SMark Adams PetscCall(MatSetBlockSizesFromMats(mat, A, C)); 12475415d71bSStefano Zampini break; 1248d71ae5a4SJacob Faibussowitsch default: 1249d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 12505415d71bSStefano Zampini } 12519566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &mmabc->BC)); 12529566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->BC, prefix)); 12539566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->BC, "P1_")); 12549566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->BC, p1)); 12559566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->BC, MATPRODUCTALGORITHMDEFAULT)); 12569566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->BC, product->fill)); 12575415d71bSStefano Zampini mmabc->BC->product->api_user = product->api_user; 12589566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->BC)); 125928b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productsymbolic, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Symbolic ProductType %s not supported with %s and %s", MatProductTypes[p1], ((PetscObject)B)->type_name, ((PetscObject)C)->type_name); 1260bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 12619566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productsymbolic)(mmabc->BC)); 12625415d71bSStefano Zampini 12639566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, mmabc->BC, NULL, &mmabc->ABC)); 12649566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->ABC, prefix)); 12659566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->ABC, "P2_")); 12669566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->ABC, p2)); 12679566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->ABC, MATPRODUCTALGORITHMDEFAULT)); 12689566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->ABC, product->fill)); 12695415d71bSStefano Zampini mmabc->ABC->product->api_user = product->api_user; 12709566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->ABC)); 127128b400f6SJacob Faibussowitsch PetscCheck(mmabc->ABC->ops->productsymbolic, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Symbolic ProductType %s not supported with %s and %s", MatProductTypes[p2], ((PetscObject)A)->type_name, ((PetscObject)mmabc->BC)->type_name); 12725415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the symbolic phase on mat */ 12735415d71bSStefano Zampini mat->product = mmabc->ABC->product; 12745415d71bSStefano Zampini mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic; 1275bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 1276dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 12775415d71bSStefano Zampini mmabc->ABC->ops->productnumeric = mat->ops->productnumeric; 12785415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_ABC_Basic; 12795415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 12805415d71bSStefano Zampini mat->product = product; 12813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12825415d71bSStefano Zampini } 1283c600787bSStefano Zampini 1284c600787bSStefano Zampini /*@ 12852ef1f0ffSBarry Smith MatProductGetType - Returns the type of matrix-matrix product associated with computing values for the given matrix 1286c600787bSStefano Zampini 128727430b45SBarry Smith Not Collective 1288c600787bSStefano Zampini 1289c600787bSStefano Zampini Input Parameter: 12902ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 1291c600787bSStefano Zampini 1292c600787bSStefano Zampini Output Parameter: 129311a5261eSBarry Smith . mtype - the `MatProductType` 1294c600787bSStefano Zampini 1295c600787bSStefano Zampini Level: intermediate 1296c600787bSStefano Zampini 12971cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductCreate()`, `MatProductType`, `MatProductAlgorithm` 1298c600787bSStefano Zampini @*/ 1299d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetType(Mat mat, MatProductType *mtype) 1300d71ae5a4SJacob Faibussowitsch { 1301c600787bSStefano Zampini PetscFunctionBegin; 1302c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 13034f572ea9SToby Isaac PetscAssertPointer(mtype, 2); 1304c600787bSStefano Zampini *mtype = MATPRODUCT_UNSPECIFIED; 1305c600787bSStefano Zampini if (mat->product) *mtype = mat->product->type; 13063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1307c600787bSStefano Zampini } 1308c600787bSStefano Zampini 1309c600787bSStefano Zampini /*@ 13102ef1f0ffSBarry Smith MatProductGetMats - Returns the matrices associated with the matrix-matrix product associated with computing values for the given matrix 1311c600787bSStefano Zampini 131227430b45SBarry Smith Not Collective 1313c600787bSStefano Zampini 1314c600787bSStefano Zampini Input Parameter: 13152ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 1316c600787bSStefano Zampini 1317c600787bSStefano Zampini Output Parameters: 1318c600787bSStefano Zampini + A - the first matrix 1319c600787bSStefano Zampini . B - the second matrix 13202ef1f0ffSBarry Smith - C - the third matrix (may be `NULL` for some `MatProductType`) 1321c600787bSStefano Zampini 1322c600787bSStefano Zampini Level: intermediate 1323c600787bSStefano Zampini 13241cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 1325c600787bSStefano Zampini @*/ 1326d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetMats(Mat mat, Mat *A, Mat *B, Mat *C) 1327d71ae5a4SJacob Faibussowitsch { 1328c600787bSStefano Zampini PetscFunctionBegin; 1329c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1330c600787bSStefano Zampini if (A) *A = mat->product ? mat->product->A : NULL; 1331c600787bSStefano Zampini if (B) *B = mat->product ? mat->product->B : NULL; 1332c600787bSStefano Zampini if (C) *C = mat->product ? mat->product->C : NULL; 13333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1334c600787bSStefano Zampini } 1335