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) { 276cc1eb50dSBarry 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) { 965cc1eb50dSBarry 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 9937da3f0dfSBarry Smith Developer Note: 9947da3f0dfSBarry Smith This frees the `Mat_Product` context that was attached to the matrix during `MatProductCreate()` or `MatProductCreateWithMat()` 9957da3f0dfSBarry Smith 9961cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreate()` 9974417c5e8SHong Zhang @*/ 998d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductClear(Mat mat) 999d71ae5a4SJacob Faibussowitsch { 10004417c5e8SHong Zhang Mat_Product *product = mat->product; 10014417c5e8SHong Zhang 10024417c5e8SHong Zhang PetscFunctionBegin; 10037a3c3d58SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10044417c5e8SHong Zhang if (product) { 10059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 10069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 10079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 10089566063dSJacob Faibussowitsch PetscCall(PetscFree(product->alg)); 10099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork)); 1010cc1eb50dSBarry Smith if (product->destroy) PetscCall((*product->destroy)(&product->data)); 10116718818eSStefano Zampini } 10129566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product)); 10136718818eSStefano Zampini mat->ops->productsymbolic = NULL; 10146718818eSStefano Zampini mat->ops->productnumeric = NULL; 10153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10164417c5e8SHong Zhang } 10174417c5e8SHong Zhang 10184222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */ 1019d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate_Private(Mat A, Mat B, Mat C, Mat D) 1020d71ae5a4SJacob Faibussowitsch { 10214222ddf1SHong Zhang Mat_Product *product = NULL; 10224222ddf1SHong Zhang 10234222ddf1SHong Zhang PetscFunctionBegin; 10246718818eSStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 102528b400f6SJacob Faibussowitsch PetscCheck(!D->product, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product already present"); 10264dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&product)); 10274222ddf1SHong Zhang product->A = A; 10284222ddf1SHong Zhang product->B = B; 10294222ddf1SHong Zhang product->C = C; 10306718818eSStefano Zampini product->type = MATPRODUCT_UNSPECIFIED; 10314222ddf1SHong Zhang product->Dwork = NULL; 10324222ddf1SHong Zhang product->api_user = PETSC_FALSE; 10336718818eSStefano Zampini product->clear = PETSC_FALSE; 1034a0228903SHong Zhang product->setfromoptionscalled = PETSC_FALSE; 1035fb842aefSJose E. Roman PetscObjectParameterSetDefault(product, fill, 2); 10364222ddf1SHong Zhang D->product = product; 10374417c5e8SHong Zhang 10389566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(D, MATPRODUCTALGORITHMDEFAULT)); 10399566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(D, PETSC_DEFAULT)); 10407a3c3d58SStefano Zampini 10419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 10429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 10439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 10443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10454222ddf1SHong Zhang } 10464222ddf1SHong Zhang 10474222ddf1SHong Zhang /*@ 10482ef1f0ffSBarry Smith MatProductCreateWithMat - Set a given matrix to have its values computed via matrix-matrix operations on other matrices. 10494222ddf1SHong Zhang 105027430b45SBarry Smith Collective 10514222ddf1SHong Zhang 10524222ddf1SHong Zhang Input Parameters: 10534222ddf1SHong Zhang + A - the first matrix 10544222ddf1SHong Zhang . B - the second matrix 105567be906fSBarry Smith . C - the third matrix (optional, use `NULL` if not needed) 10562ef1f0ffSBarry Smith - D - the matrix whose values are to be computed via a matrix-matrix product operation 10574222ddf1SHong Zhang 105867be906fSBarry Smith Level: intermediate 10594222ddf1SHong Zhang 10606718818eSStefano Zampini Notes: 10617da3f0dfSBarry Smith Use `MatProductCreate()` if the matrix you wish computed `D` does not exist 1062f5368d60SBarry Smith 106327430b45SBarry Smith See `MatProductCreate()` for details on the usage of the matrix-matrix product operations 1064f5368d60SBarry Smith 10657da3f0dfSBarry Smith Any product data currently attached to `D` will be freed 10666718818eSStefano Zampini 10671cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductType`, `MatProductSetType()`, `MatProductAlgorithm`, 10682ef1f0ffSBarry Smith `MatProductSetAlgorithm`, `MatProductCreate()`, `MatProductClear()` 10694222ddf1SHong Zhang @*/ 1070d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreateWithMat(Mat A, Mat B, Mat C, Mat D) 1071d71ae5a4SJacob Faibussowitsch { 10724222ddf1SHong Zhang PetscFunctionBegin; 10734222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10744222ddf1SHong Zhang PetscValidType(A, 1); 10754222ddf1SHong Zhang MatCheckPreallocated(A, 1); 107628b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 107728b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10784222ddf1SHong Zhang 10794222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10804222ddf1SHong Zhang PetscValidType(B, 2); 10814222ddf1SHong Zhang MatCheckPreallocated(B, 2); 108228b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 108328b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10844222ddf1SHong Zhang 10854222ddf1SHong Zhang if (C) { 10864222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 10874222ddf1SHong Zhang PetscValidType(C, 3); 10884222ddf1SHong Zhang MatCheckPreallocated(C, 3); 108928b400f6SJacob Faibussowitsch PetscCheck(C->assembled, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 109028b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10914222ddf1SHong Zhang } 10924222ddf1SHong Zhang 10934222ddf1SHong Zhang PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 10944222ddf1SHong Zhang PetscValidType(D, 4); 10954222ddf1SHong Zhang MatCheckPreallocated(D, 4); 109628b400f6SJacob Faibussowitsch PetscCheck(D->assembled, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 109728b400f6SJacob Faibussowitsch PetscCheck(!D->factortype, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10984222ddf1SHong Zhang 10994222ddf1SHong Zhang /* Create a supporting struct and attach it to D */ 11009566063dSJacob Faibussowitsch PetscCall(MatProductClear(D)); 11019566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, D)); 11023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11034222ddf1SHong Zhang } 11044222ddf1SHong Zhang 11054222ddf1SHong Zhang /*@ 11067da3f0dfSBarry Smith MatProductCreate - create a matrix to hold the result of a matrix-matrix (or matrix-matrix-matrix) product operation 11074222ddf1SHong Zhang 110827430b45SBarry Smith Collective 11094222ddf1SHong Zhang 11104222ddf1SHong Zhang Input Parameters: 11114222ddf1SHong Zhang + A - the first matrix 11124222ddf1SHong Zhang . B - the second matrix 11132ef1f0ffSBarry Smith - C - the third matrix (or `NULL`) 11144222ddf1SHong Zhang 11152fe279fdSBarry Smith Output Parameter: 11162ef1f0ffSBarry Smith . D - the matrix whose values are to be computed via a matrix-matrix product operation 11174222ddf1SHong Zhang 11184222ddf1SHong Zhang Level: intermediate 11194222ddf1SHong Zhang 112027430b45SBarry Smith Example: 1121f5368d60SBarry Smith .vb 112211a5261eSBarry Smith MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 112311a5261eSBarry Smith MatProductSetType(D, MATPRODUCT_AB or MATPRODUCT_AtB or MATPRODUCT_ABt or MATPRODUCT_PtAP or MATPRODUCT_RARt or MATPRODUCT_ABC) 112411a5261eSBarry Smith MatProductSetAlgorithm(D, alg) 112511a5261eSBarry Smith MatProductSetFill(D,fill) 112611a5261eSBarry Smith MatProductSetFromOptions(D) 112711a5261eSBarry Smith MatProductSymbolic(D) 112811a5261eSBarry Smith MatProductNumeric(D) 1129f5368d60SBarry Smith Change numerical values in some of the matrices 113011a5261eSBarry Smith MatProductNumeric(D) 1131f5368d60SBarry Smith .ve 1132f5368d60SBarry Smith 1133f5368d60SBarry Smith Notes: 11347da3f0dfSBarry Smith Use `MatProductCreateWithMat()` if `D` the matrix you wish computed already exists. 1135f5368d60SBarry Smith 11367da3f0dfSBarry Smith The information computed during the symbolic stage can be reused for new numerical computations with the same non-zero structure of the input matrices. 1137f5368d60SBarry Smith 1138fe59aa6dSJacob Faibussowitsch Developer Notes: 1139f5368d60SBarry Smith It is undocumented what happens if the nonzero structure of the input matrices changes. Is the symbolic stage automatically redone? Does it crash? 1140f5368d60SBarry Smith Is there error checking for it? 1141f5368d60SBarry Smith 11427da3f0dfSBarry Smith On this call, auxiliary data needed to compute the product is stored in `D` in a `Mat_Product` context. A call to `MatProductClear()` frees this 11437da3f0dfSBarry Smith information. 11447da3f0dfSBarry Smith 11457da3f0dfSBarry Smith Each `MatProductAlgorithm` associated with a particular `MatType` stores additional data needed for the product computation 11467da3f0dfSBarry Smith (generally this data is computed in `MatProductSymbolic()`) inside the `Mat_Product` context in a `MatProductCtx_XXX` data structure 11477da3f0dfSBarry Smith and provides a `MatProductCtxDestroy_XXX()` routine to free that data. The `MatProductAlgorithm` and `MatType` specific destroy routine is called by 11487da3f0dfSBarry Smith `MatProductClear()`. 11497da3f0dfSBarry Smith 11507da3f0dfSBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductClear()`, 11517da3f0dfSBarry Smith `MatProductSymbolic()`, `MatProductNumeric()`, `MatProductAlgorithm`, `MatProductType` 11524222ddf1SHong Zhang @*/ 1153d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate(Mat A, Mat B, Mat C, Mat *D) 1154d71ae5a4SJacob Faibussowitsch { 11554222ddf1SHong Zhang PetscFunctionBegin; 11564222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11574222ddf1SHong Zhang PetscValidType(A, 1); 11584222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11594222ddf1SHong Zhang PetscValidType(B, 2); 116028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix A"); 116128b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix B"); 11624222ddf1SHong Zhang 11634222ddf1SHong Zhang if (C) { 11644222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 11654222ddf1SHong Zhang PetscValidType(C, 3); 116628b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix C"); 11674222ddf1SHong Zhang } 11684222ddf1SHong Zhang 11694f572ea9SToby Isaac PetscAssertPointer(D, 4); 11709566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), D)); 117130203840SJunchao Zhang /* Delay setting type of D to the MatProduct symbolic phase, as we allow sparse A and dense B */ 11729566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, *D)); 11733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11744222ddf1SHong Zhang } 11755415d71bSStefano Zampini 11765415d71bSStefano Zampini /* 11775415d71bSStefano Zampini These are safe basic implementations of ABC, RARt and PtAP 11785415d71bSStefano Zampini that do not rely on mat->ops->matmatop function pointers. 11795415d71bSStefano Zampini They only use the MatProduct API and are currently used by 11805415d71bSStefano Zampini cuSPARSE and KOKKOS-KERNELS backends 11815415d71bSStefano Zampini */ 1182ec446438SStefano Zampini typedef struct { 11835415d71bSStefano Zampini Mat BC; 11845415d71bSStefano Zampini Mat ABC; 1185cc1eb50dSBarry Smith } MatProductCtx_MatMatMatPrivate; 11865415d71bSStefano Zampini 1187*2a8381b2SBarry Smith static PetscErrorCode MatProductCtxDestroy_MatMatMatPrivate(PetscCtxRt data) 1188d71ae5a4SJacob Faibussowitsch { 1189cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmdata = *(MatProductCtx_MatMatMatPrivate **)data; 11905415d71bSStefano Zampini 11915415d71bSStefano Zampini PetscFunctionBegin; 11929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->BC)); 11939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->ABC)); 1194*2a8381b2SBarry Smith PetscCall(PetscFree(mmdata)); 11953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11965415d71bSStefano Zampini } 11975415d71bSStefano Zampini 1198d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 1199d71ae5a4SJacob Faibussowitsch { 12005415d71bSStefano Zampini Mat_Product *product = mat->product; 1201cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmabc; 12025415d71bSStefano Zampini 12035415d71bSStefano Zampini PetscFunctionBegin; 12045415d71bSStefano Zampini MatCheckProduct(mat, 1); 120528b400f6SJacob Faibussowitsch PetscCheck(mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data empty"); 1206cc1eb50dSBarry Smith mmabc = (MatProductCtx_MatMatMatPrivate *)mat->product->data; 120728b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productnumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing numeric stage"); 1208ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 12099566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productnumeric)(mmabc->BC)); 12105415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the numeric phase on mat */ 12115415d71bSStefano Zampini mat->product = mmabc->ABC->product; 12125415d71bSStefano Zampini mat->ops->productnumeric = mmabc->ABC->ops->productnumeric; 1213ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 1214dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 12155415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 12165415d71bSStefano Zampini mat->product = product; 12173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12185415d71bSStefano Zampini } 12195415d71bSStefano Zampini 1220d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 1221d71ae5a4SJacob Faibussowitsch { 12225415d71bSStefano Zampini Mat_Product *product = mat->product; 12235415d71bSStefano Zampini Mat A, B, C; 12245415d71bSStefano Zampini MatProductType p1, p2; 1225cc1eb50dSBarry Smith MatProductCtx_MatMatMatPrivate *mmabc; 122665e4b4d4SStefano Zampini const char *prefix; 12275415d71bSStefano Zampini 12285415d71bSStefano Zampini PetscFunctionBegin; 12295415d71bSStefano Zampini MatCheckProduct(mat, 1); 123028b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data not empty"); 12319566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(mat, &prefix)); 12329566063dSJacob Faibussowitsch PetscCall(PetscNew(&mmabc)); 12335415d71bSStefano Zampini product->data = mmabc; 1234cc1eb50dSBarry Smith product->destroy = MatProductCtxDestroy_MatMatMatPrivate; 12355415d71bSStefano Zampini switch (product->type) { 12365415d71bSStefano Zampini case MATPRODUCT_PtAP: 12375415d71bSStefano Zampini p1 = MATPRODUCT_AB; 12385415d71bSStefano Zampini p2 = MATPRODUCT_AtB; 12395415d71bSStefano Zampini A = product->B; 12405415d71bSStefano Zampini B = product->A; 12415415d71bSStefano Zampini C = product->B; 124239cfb508SMark Adams if (A->cmap->bs > 0 && C->cmap->bs > 0) PetscCall(MatSetBlockSizes(mat, A->cmap->bs, C->cmap->bs)); 12435415d71bSStefano Zampini break; 12445415d71bSStefano Zampini case MATPRODUCT_RARt: 12455415d71bSStefano Zampini p1 = MATPRODUCT_ABt; 12465415d71bSStefano Zampini p2 = MATPRODUCT_AB; 12475415d71bSStefano Zampini A = product->B; 12485415d71bSStefano Zampini B = product->A; 12495415d71bSStefano Zampini C = product->B; 125039cfb508SMark Adams if (A->rmap->bs > 0 && C->rmap->bs > 0) PetscCall(MatSetBlockSizes(mat, A->rmap->bs, C->rmap->bs)); 12515415d71bSStefano Zampini break; 12525415d71bSStefano Zampini case MATPRODUCT_ABC: 12535415d71bSStefano Zampini p1 = MATPRODUCT_AB; 12545415d71bSStefano Zampini p2 = MATPRODUCT_AB; 12555415d71bSStefano Zampini A = product->A; 12565415d71bSStefano Zampini B = product->B; 12575415d71bSStefano Zampini C = product->C; 12580e6a1e94SMark Adams PetscCall(MatSetBlockSizesFromMats(mat, A, C)); 12595415d71bSStefano Zampini break; 1260d71ae5a4SJacob Faibussowitsch default: 1261d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 12625415d71bSStefano Zampini } 12639566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &mmabc->BC)); 12649566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->BC, prefix)); 12659566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->BC, "P1_")); 12669566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->BC, p1)); 12679566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->BC, MATPRODUCTALGORITHMDEFAULT)); 12689566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->BC, product->fill)); 12695415d71bSStefano Zampini mmabc->BC->product->api_user = product->api_user; 12709566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->BC)); 127128b400f6SJacob 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); 1272bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 12739566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productsymbolic)(mmabc->BC)); 12745415d71bSStefano Zampini 12759566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, mmabc->BC, NULL, &mmabc->ABC)); 12769566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->ABC, prefix)); 12779566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->ABC, "P2_")); 12789566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->ABC, p2)); 12799566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->ABC, MATPRODUCTALGORITHMDEFAULT)); 12809566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->ABC, product->fill)); 12815415d71bSStefano Zampini mmabc->ABC->product->api_user = product->api_user; 12829566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->ABC)); 128328b400f6SJacob 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); 12845415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the symbolic phase on mat */ 12855415d71bSStefano Zampini mat->product = mmabc->ABC->product; 12865415d71bSStefano Zampini mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic; 1287bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 1288dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 12895415d71bSStefano Zampini mmabc->ABC->ops->productnumeric = mat->ops->productnumeric; 12905415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_ABC_Basic; 12915415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 12925415d71bSStefano Zampini mat->product = product; 12933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12945415d71bSStefano Zampini } 1295c600787bSStefano Zampini 1296c600787bSStefano Zampini /*@ 12972ef1f0ffSBarry Smith MatProductGetType - Returns the type of matrix-matrix product associated with computing values for the given matrix 1298c600787bSStefano Zampini 129927430b45SBarry Smith Not Collective 1300c600787bSStefano Zampini 1301c600787bSStefano Zampini Input Parameter: 13022ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 1303c600787bSStefano Zampini 1304c600787bSStefano Zampini Output Parameter: 130511a5261eSBarry Smith . mtype - the `MatProductType` 1306c600787bSStefano Zampini 1307c600787bSStefano Zampini Level: intermediate 1308c600787bSStefano Zampini 13091cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductCreate()`, `MatProductType`, `MatProductAlgorithm` 1310c600787bSStefano Zampini @*/ 1311d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetType(Mat mat, MatProductType *mtype) 1312d71ae5a4SJacob Faibussowitsch { 1313c600787bSStefano Zampini PetscFunctionBegin; 1314c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 13154f572ea9SToby Isaac PetscAssertPointer(mtype, 2); 1316c600787bSStefano Zampini *mtype = MATPRODUCT_UNSPECIFIED; 1317c600787bSStefano Zampini if (mat->product) *mtype = mat->product->type; 13183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1319c600787bSStefano Zampini } 1320c600787bSStefano Zampini 1321c600787bSStefano Zampini /*@ 13222ef1f0ffSBarry Smith MatProductGetMats - Returns the matrices associated with the matrix-matrix product associated with computing values for the given matrix 1323c600787bSStefano Zampini 132427430b45SBarry Smith Not Collective 1325c600787bSStefano Zampini 1326c600787bSStefano Zampini Input Parameter: 13272ef1f0ffSBarry Smith . mat - the matrix whose values are to be computed via a matrix-matrix product operation 1328c600787bSStefano Zampini 1329c600787bSStefano Zampini Output Parameters: 1330c600787bSStefano Zampini + A - the first matrix 1331c600787bSStefano Zampini . B - the second matrix 13322ef1f0ffSBarry Smith - C - the third matrix (may be `NULL` for some `MatProductType`) 1333c600787bSStefano Zampini 1334c600787bSStefano Zampini Level: intermediate 1335c600787bSStefano Zampini 13361cc06b55SBarry Smith .seealso: [](ch_matrices), `MatProduct`, `Mat`, `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 1337c600787bSStefano Zampini @*/ 1338d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetMats(Mat mat, Mat *A, Mat *B, Mat *C) 1339d71ae5a4SJacob Faibussowitsch { 1340c600787bSStefano Zampini PetscFunctionBegin; 1341c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1342c600787bSStefano Zampini if (A) *A = mat->product ? mat->product->A : NULL; 1343c600787bSStefano Zampini if (B) *B = mat->product ? mat->product->B : NULL; 1344c600787bSStefano Zampini if (C) *C = mat->product ? mat->product->C : NULL; 13453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1346c600787bSStefano Zampini } 1347