14222ddf1SHong Zhang 24222ddf1SHong Zhang /* 34222ddf1SHong Zhang Routines for matrix products. Calling procedure: 44222ddf1SHong Zhang 56718818eSStefano Zampini MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 66718818eSStefano Zampini MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC) 76718818eSStefano Zampini MatProductSetAlgorithm(D, alg) 86718818eSStefano Zampini MatProductSetFill(D,fill) 96718818eSStefano Zampini MatProductSetFromOptions(D) 106718818eSStefano Zampini -> MatProductSetFromOptions_Private(D) 114222ddf1SHong Zhang # Check matrix global sizes 126718818eSStefano Zampini if the matrices have the same setfromoptions routine, use it 136718818eSStefano Zampini if not, try: 146718818eSStefano Zampini -> Query MatProductSetFromOptions_Atype_Btype_Ctype_C(D) from A, B and C (in order) 156718818eSStefano Zampini if found -> run the specific setup that must set the symbolic operation (these callbacks should never fail) 166718818eSStefano Zampini if callback not found or no symbolic operation set 17013e2dc7SBarry Smith -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANSPOSEVIRTUAL) 186718818eSStefano Zampini if dispatch found but combination still not present do 196718818eSStefano Zampini -> check if B is dense and product type AtB or AB -> if true, basic looping of dense columns 206718818eSStefano Zampini -> check if triple product (PtAP, RARt or ABC) -> if true, set the Basic routines 216718818eSStefano Zampini 226718818eSStefano Zampini # The setfromoptions calls MatProductSetFromOptions_Atype_Btype_Ctype should 234222ddf1SHong Zhang # Check matrix local sizes for mpi matrices 244222ddf1SHong Zhang # Set default algorithm 254222ddf1SHong Zhang # Get runtime option 266718818eSStefano Zampini # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype if found 274222ddf1SHong Zhang 286718818eSStefano Zampini MatProductSymbolic(D) 296718818eSStefano Zampini # Call MatProductSymbolic_productype_Atype_Btype_Ctype() 306718818eSStefano Zampini the callback must set the numeric phase D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype 314222ddf1SHong Zhang 326718818eSStefano Zampini MatProductNumeric(D) 336718818eSStefano Zampini # Call the numeric phase 346718818eSStefano Zampini 356718818eSStefano Zampini # The symbolic phases are allowed to set extra data structures and attach those to the product 366718818eSStefano Zampini # this additional data can be reused between multiple numeric phases with the same matrices 376718818eSStefano Zampini # if not needed, call 386718818eSStefano Zampini MatProductClear(D) 394222ddf1SHong Zhang */ 404222ddf1SHong Zhang 414222ddf1SHong Zhang #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 424222ddf1SHong Zhang 436718818eSStefano Zampini const char *const MatProductTypes[] = {"UNSPECIFIED", "AB", "AtB", "ABt", "PtAP", "RARt", "ABC"}; 44544a5e07SHong Zhang 456718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 466718818eSStefano Zampini * they are dangerous and should be removed in the future */ 47d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_PtAP_Unsafe(Mat C) 48d71ae5a4SJacob Faibussowitsch { 494222ddf1SHong Zhang Mat_Product *product = C->product; 504222ddf1SHong Zhang Mat P = product->B, AP = product->Dwork; 514222ddf1SHong Zhang 524222ddf1SHong Zhang PetscFunctionBegin; 534222ddf1SHong Zhang /* AP = A*P */ 549566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(AP)); 554222ddf1SHong Zhang /* C = P^T*AP */ 569566063dSJacob Faibussowitsch PetscCall((*C->ops->transposematmultnumeric)(P, AP, C)); 574222ddf1SHong Zhang PetscFunctionReturn(0); 584222ddf1SHong Zhang } 594222ddf1SHong Zhang 60d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_Unsafe(Mat C) 61d71ae5a4SJacob Faibussowitsch { 624222ddf1SHong Zhang Mat_Product *product = C->product; 634222ddf1SHong Zhang Mat A = product->A, P = product->B, AP; 644222ddf1SHong Zhang PetscReal fill = product->fill; 654222ddf1SHong Zhang 664222ddf1SHong Zhang PetscFunctionBegin; 679566063dSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)C, "for A %s, P %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 684222ddf1SHong Zhang /* AP = A*P */ 699566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, P, NULL, &AP)); 709566063dSJacob Faibussowitsch PetscCall(MatProductSetType(AP, MATPRODUCT_AB)); 719566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(AP, MATPRODUCTALGORITHMDEFAULT)); 729566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(AP, fill)); 739566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(AP)); 749566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(AP)); 754222ddf1SHong Zhang 764222ddf1SHong Zhang /* C = P^T*AP */ 779566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_AtB)); 789566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 794222ddf1SHong Zhang product->A = P; 804222ddf1SHong Zhang product->B = AP; 819566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 829566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 834222ddf1SHong Zhang 844222ddf1SHong Zhang /* resume user's original input matrix setting for A and B */ 854222ddf1SHong Zhang product->A = A; 864222ddf1SHong Zhang product->B = P; 874222ddf1SHong Zhang product->Dwork = AP; 884222ddf1SHong Zhang 895415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_PtAP_Unsafe; 904222ddf1SHong Zhang PetscFunctionReturn(0); 914222ddf1SHong Zhang } 924222ddf1SHong Zhang 93d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_RARt_Unsafe(Mat C) 94d71ae5a4SJacob Faibussowitsch { 954222ddf1SHong Zhang Mat_Product *product = C->product; 964222ddf1SHong Zhang Mat R = product->B, RA = product->Dwork; 974222ddf1SHong Zhang 984222ddf1SHong Zhang PetscFunctionBegin; 994222ddf1SHong Zhang /* RA = R*A */ 1009566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(RA)); 1014222ddf1SHong Zhang /* C = RA*R^T */ 1029566063dSJacob Faibussowitsch PetscCall((*C->ops->mattransposemultnumeric)(RA, R, C)); 1034222ddf1SHong Zhang PetscFunctionReturn(0); 1044222ddf1SHong Zhang } 1054222ddf1SHong Zhang 106d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_RARt_Unsafe(Mat C) 107d71ae5a4SJacob Faibussowitsch { 1084222ddf1SHong Zhang Mat_Product *product = C->product; 1094222ddf1SHong Zhang Mat A = product->A, R = product->B, RA; 1104222ddf1SHong Zhang PetscReal fill = product->fill; 1114222ddf1SHong Zhang 1124222ddf1SHong Zhang PetscFunctionBegin; 1139566063dSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)C, "for A %s, R %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 1144222ddf1SHong Zhang /* RA = R*A */ 1159566063dSJacob Faibussowitsch PetscCall(MatProductCreate(R, A, NULL, &RA)); 1169566063dSJacob Faibussowitsch PetscCall(MatProductSetType(RA, MATPRODUCT_AB)); 1179566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(RA, MATPRODUCTALGORITHMDEFAULT)); 1189566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(RA, fill)); 1199566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(RA)); 1209566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(RA)); 1214222ddf1SHong Zhang 1224222ddf1SHong Zhang /* C = RA*R^T */ 1239566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_ABt)); 1249566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 1254222ddf1SHong Zhang product->A = RA; 1269566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 1279566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 1284222ddf1SHong Zhang 1294222ddf1SHong Zhang /* resume user's original input matrix setting for A */ 1304222ddf1SHong Zhang product->A = A; 1314222ddf1SHong Zhang product->Dwork = RA; /* save here so it will be destroyed with product C */ 1325415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_RARt_Unsafe; 1334222ddf1SHong Zhang PetscFunctionReturn(0); 1344222ddf1SHong Zhang } 1354222ddf1SHong Zhang 136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_ABC_Unsafe(Mat mat) 137d71ae5a4SJacob Faibussowitsch { 1384222ddf1SHong Zhang Mat_Product *product = mat->product; 1394222ddf1SHong Zhang Mat A = product->A, BC = product->Dwork; 1404222ddf1SHong Zhang 1414222ddf1SHong Zhang PetscFunctionBegin; 1424222ddf1SHong Zhang /* Numeric BC = B*C */ 1439566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(BC)); 1444222ddf1SHong Zhang /* Numeric mat = A*BC */ 1459566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, BC, mat)); 1464222ddf1SHong Zhang PetscFunctionReturn(0); 1474222ddf1SHong Zhang } 1484222ddf1SHong Zhang 149d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_ABC_Unsafe(Mat mat) 150d71ae5a4SJacob Faibussowitsch { 1514222ddf1SHong Zhang Mat_Product *product = mat->product; 1524222ddf1SHong Zhang Mat B = product->B, C = product->C, BC; 1534222ddf1SHong Zhang PetscReal fill = product->fill; 1544222ddf1SHong Zhang 1554222ddf1SHong Zhang PetscFunctionBegin; 1569566063dSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)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)); 1574222ddf1SHong Zhang /* Symbolic BC = B*C */ 1589566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &BC)); 1599566063dSJacob Faibussowitsch PetscCall(MatProductSetType(BC, MATPRODUCT_AB)); 1609566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(BC, MATPRODUCTALGORITHMDEFAULT)); 1619566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(BC, fill)); 1629566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(BC)); 1639566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(BC)); 1644222ddf1SHong Zhang 1654222ddf1SHong Zhang /* Symbolic mat = A*BC */ 1669566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mat, MATPRODUCT_AB)); 1679566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mat, MATPRODUCTALGORITHMDEFAULT)); 1684222ddf1SHong Zhang product->B = BC; 1694222ddf1SHong Zhang product->Dwork = BC; 1709566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mat)); 1719566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(mat)); 1724222ddf1SHong Zhang 1734222ddf1SHong Zhang /* resume user's original input matrix setting for B */ 1744222ddf1SHong Zhang product->B = B; 1755415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Unsafe; 1764222ddf1SHong Zhang PetscFunctionReturn(0); 1774222ddf1SHong Zhang } 1784222ddf1SHong Zhang 179d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_Unsafe(Mat mat) 180d71ae5a4SJacob Faibussowitsch { 1814222ddf1SHong Zhang Mat_Product *product = mat->product; 1824222ddf1SHong Zhang 1834222ddf1SHong Zhang PetscFunctionBegin; 1844222ddf1SHong Zhang switch (product->type) { 185d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 186d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_PtAP_Unsafe(mat)); 187d71ae5a4SJacob Faibussowitsch break; 188d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 189d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_RARt_Unsafe(mat)); 190d71ae5a4SJacob Faibussowitsch break; 191d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 192d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSymbolic_ABC_Unsafe(mat)); 193d71ae5a4SJacob Faibussowitsch break; 194d71ae5a4SJacob Faibussowitsch default: 195d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[product->type]); 1964222ddf1SHong Zhang } 1974222ddf1SHong Zhang PetscFunctionReturn(0); 1984222ddf1SHong Zhang } 1994222ddf1SHong Zhang 2004222ddf1SHong Zhang /* ----------------------------------------------- */ 2014222ddf1SHong Zhang /*@C 2024222ddf1SHong Zhang MatProductReplaceMats - Replace input matrices for a matrix product. 2034222ddf1SHong Zhang 2044222ddf1SHong Zhang Collective on Mat 2054222ddf1SHong Zhang 2064222ddf1SHong Zhang Input Parameters: 2074222ddf1SHong Zhang + A - the matrix or NULL if not being replaced 2084222ddf1SHong Zhang . B - the matrix or NULL if not being replaced 2094222ddf1SHong Zhang . C - the matrix or NULL if not being replaced 2104222ddf1SHong Zhang - D - the matrix product 2114222ddf1SHong Zhang 2124222ddf1SHong Zhang Level: intermediate 2134222ddf1SHong Zhang 21411a5261eSBarry Smith Note: 21511a5261eSBarry Smith To reuse the symbolic phase, the input matrices must have exactly the same data structure as the replaced one. 2161cdffd5eSHong Zhang If the type of any of the input matrices is different than what was previously used, or their symmetry flag changed but 217f5368d60SBarry Smith the symbolic phase took advantage of their symmetry, the product is cleared and `MatProductSetFromOptions()` and `MatProductSymbolic()` are invoked again. 2184222ddf1SHong Zhang 219db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductSetFromOptions()`, `MatProductSymbolic().` `MatProductClear()` 2204222ddf1SHong Zhang @*/ 221d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductReplaceMats(Mat A, Mat B, Mat C, Mat D) 222d71ae5a4SJacob Faibussowitsch { 2236718818eSStefano Zampini Mat_Product *product; 224b94d7dedSBarry Smith PetscBool flgA = PETSC_TRUE, flgB = PETSC_TRUE, flgC = PETSC_TRUE, isset, issym; 2254222ddf1SHong Zhang 2264222ddf1SHong Zhang PetscFunctionBegin; 2277a3c3d58SStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 2286718818eSStefano Zampini MatCheckProduct(D, 4); 2296718818eSStefano Zampini product = D->product; 2304222ddf1SHong Zhang if (A) { 2317a3c3d58SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 2339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, ((PetscObject)A)->type_name, &flgA)); 234b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(A, &isset, &issym)); 235b94d7dedSBarry 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 */ 236fa046f9fSJunchao Zhang flgA = PETSC_FALSE; 237fa046f9fSJunchao Zhang product->symbolic_used_the_fact_A_is_symmetric = PETSC_FALSE; /* reinit */ 238fa046f9fSJunchao Zhang } 2399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 2404222ddf1SHong Zhang product->A = A; 2414222ddf1SHong Zhang } 2424222ddf1SHong Zhang if (B) { 2437a3c3d58SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 2449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 2459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->B, ((PetscObject)B)->type_name, &flgB)); 246b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(B, &isset, &issym)); 247b94d7dedSBarry Smith if (product->symbolic_used_the_fact_B_is_symmetric && isset && !issym) { 248fa046f9fSJunchao Zhang flgB = PETSC_FALSE; 249fa046f9fSJunchao Zhang product->symbolic_used_the_fact_B_is_symmetric = PETSC_FALSE; /* reinit */ 250fa046f9fSJunchao Zhang } 2519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 2524222ddf1SHong Zhang product->B = B; 2534222ddf1SHong Zhang } 2544417c5e8SHong Zhang if (C) { 2557a3c3d58SStefano Zampini PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 2569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 2579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->C, ((PetscObject)C)->type_name, &flgC)); 258b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(C, &isset, &issym)); 259b94d7dedSBarry Smith if (product->symbolic_used_the_fact_C_is_symmetric && isset && !issym) { 260fa046f9fSJunchao Zhang flgC = PETSC_FALSE; 261fa046f9fSJunchao Zhang product->symbolic_used_the_fact_C_is_symmetric = PETSC_FALSE; /* reinit */ 262fa046f9fSJunchao Zhang } 2639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 2644417c5e8SHong Zhang product->C = C; 2654417c5e8SHong Zhang } 2666718818eSStefano Zampini /* Any of the replaced mats is of a different type, reset */ 2676718818eSStefano Zampini if (!flgA || !flgB || !flgC) { 2681baa6e33SBarry Smith if (D->product->destroy) PetscCall((*D->product->destroy)(D->product->data)); 2696718818eSStefano Zampini D->product->destroy = NULL; 2706718818eSStefano Zampini D->product->data = NULL; 2716718818eSStefano Zampini if (D->ops->productnumeric || D->ops->productsymbolic) { 2729566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(D)); 2739566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(D)); 2746718818eSStefano Zampini } 2756718818eSStefano Zampini } 2764222ddf1SHong Zhang PetscFunctionReturn(0); 2774222ddf1SHong Zhang } 2784222ddf1SHong Zhang 279d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_X_Dense(Mat C) 280d71ae5a4SJacob Faibussowitsch { 2817a3c3d58SStefano Zampini Mat_Product *product = C->product; 2827a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 2837a3c3d58SStefano Zampini PetscInt k, K = B->cmap->N; 2847a3c3d58SStefano Zampini PetscBool t = PETSC_TRUE, iscuda = PETSC_FALSE; 2857a3c3d58SStefano Zampini PetscBool Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE; 2867a3c3d58SStefano Zampini char *Btype = NULL, *Ctype = NULL; 2877a3c3d58SStefano Zampini 2887a3c3d58SStefano Zampini PetscFunctionBegin; 2897a3c3d58SStefano Zampini switch (product->type) { 290d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 291d71ae5a4SJacob Faibussowitsch t = PETSC_FALSE; 292d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 293d71ae5a4SJacob Faibussowitsch break; 294d71ae5a4SJacob Faibussowitsch default: 295d71ae5a4SJacob 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); 2967a3c3d58SStefano Zampini } 2977a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 2987a3c3d58SStefano Zampini VecType vtype; 2997a3c3d58SStefano Zampini 3009566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A, &vtype)); 3019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype, VECCUDA, &iscuda)); 30248a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECSEQCUDA, &iscuda)); 30348a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECMPICUDA, &iscuda)); 3047a3c3d58SStefano Zampini if (iscuda) { /* Make sure we have up-to-date data on the GPU */ 3059566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)B)->type_name, &Btype)); 3069566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)C)->type_name, &Ctype)); 3079566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3087a3c3d58SStefano Zampini if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */ 3099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 3109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 3117a3c3d58SStefano Zampini } 3129566063dSJacob Faibussowitsch PetscCall(MatConvert(C, MATDENSECUDA, MAT_INPLACE_MATRIX, &C)); 3137a3c3d58SStefano Zampini } else { /* Make sure we have up-to-date data on the CPU */ 3147a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL) 3157a3c3d58SStefano Zampini Bcpu = B->boundtocpu; 3167a3c3d58SStefano Zampini Ccpu = C->boundtocpu; 3177a3c3d58SStefano Zampini #endif 3189566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, PETSC_TRUE)); 3199566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, PETSC_TRUE)); 3207a3c3d58SStefano Zampini } 3217a3c3d58SStefano Zampini } 3227a3c3d58SStefano Zampini for (k = 0; k < K; k++) { 3237a3c3d58SStefano Zampini Vec x, y; 3247a3c3d58SStefano Zampini 3259566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(B, k, &x)); 3269566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecWrite(C, k, &y)); 3277a3c3d58SStefano Zampini if (t) { 3289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, x, y)); 3297a3c3d58SStefano Zampini } else { 3309566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, y)); 3317a3c3d58SStefano Zampini } 3329566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(B, k, &x)); 3339566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecWrite(C, k, &y)); 3347a3c3d58SStefano Zampini } 3359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 3369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 3377a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 3387a3c3d58SStefano Zampini if (iscuda) { 3399566063dSJacob Faibussowitsch PetscCall(MatConvert(B, Btype, MAT_INPLACE_MATRIX, &B)); 3409566063dSJacob Faibussowitsch PetscCall(MatConvert(C, Ctype, MAT_INPLACE_MATRIX, &C)); 3417a3c3d58SStefano Zampini } else { 3429566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, Bcpu)); 3439566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, Ccpu)); 3447a3c3d58SStefano Zampini } 3457a3c3d58SStefano Zampini } 3469566063dSJacob Faibussowitsch PetscCall(PetscFree(Btype)); 3479566063dSJacob Faibussowitsch PetscCall(PetscFree(Ctype)); 3487a3c3d58SStefano Zampini PetscFunctionReturn(0); 3497a3c3d58SStefano Zampini } 3507a3c3d58SStefano Zampini 351d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_X_Dense(Mat C) 352d71ae5a4SJacob Faibussowitsch { 3537a3c3d58SStefano Zampini Mat_Product *product = C->product; 3547a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 3557a3c3d58SStefano Zampini PetscBool isdense; 3567a3c3d58SStefano Zampini 3577a3c3d58SStefano Zampini PetscFunctionBegin; 3587a3c3d58SStefano Zampini switch (product->type) { 359d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 360d71ae5a4SJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->n, B->cmap->n, A->rmap->N, B->cmap->N)); 361d71ae5a4SJacob Faibussowitsch break; 362d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 363d71ae5a4SJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, B->cmap->n, A->cmap->N, B->cmap->N)); 364d71ae5a4SJacob Faibussowitsch break; 365d71ae5a4SJacob Faibussowitsch default: 366d71ae5a4SJacob 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); 3677a3c3d58SStefano Zampini } 3689566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)C, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 3697a3c3d58SStefano Zampini if (!isdense) { 3709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)B)->type_name)); 3716718818eSStefano Zampini /* If matrix type of C was not set or not dense, we need to reset the pointer */ 3727a3c3d58SStefano Zampini C->ops->productsymbolic = MatProductSymbolic_X_Dense; 3737a3c3d58SStefano Zampini } 3746718818eSStefano Zampini C->ops->productnumeric = MatProductNumeric_X_Dense; 3759566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 3767a3c3d58SStefano Zampini PetscFunctionReturn(0); 3777a3c3d58SStefano Zampini } 3787a3c3d58SStefano Zampini 3796718818eSStefano Zampini /* a single driver to query the dispatching */ 380d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Private(Mat mat) 381d71ae5a4SJacob Faibussowitsch { 3824222ddf1SHong Zhang Mat_Product *product = mat->product; 3836718818eSStefano Zampini PetscInt Am, An, Bm, Bn, Cm, Cn; 3844222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 3856718818eSStefano Zampini const char *const Bnames[] = {"B", "R", "P"}; 3866718818eSStefano Zampini const char *bname; 3874222ddf1SHong Zhang PetscErrorCode (*fA)(Mat); 3884222ddf1SHong Zhang PetscErrorCode (*fB)(Mat); 3894222ddf1SHong Zhang PetscErrorCode (*fC)(Mat); 3904222ddf1SHong Zhang PetscErrorCode (*f)(Mat) = NULL; 3914222ddf1SHong Zhang 3924222ddf1SHong Zhang PetscFunctionBegin; 3936718818eSStefano Zampini mat->ops->productsymbolic = NULL; 3946718818eSStefano Zampini mat->ops->productnumeric = NULL; 3956718818eSStefano Zampini if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(0); 39628b400f6SJacob Faibussowitsch PetscCheck(A, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing A mat"); 39728b400f6SJacob Faibussowitsch PetscCheck(B, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing B mat"); 398072cda71SBarry Smith PetscCheck(product->type != MATPRODUCT_ABC || C, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing C mat"); 3996718818eSStefano Zampini if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */ 4006718818eSStefano Zampini if (product->type == MATPRODUCT_RARt) bname = Bnames[1]; 4016718818eSStefano Zampini else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2]; 4026718818eSStefano Zampini else bname = Bnames[0]; 4036718818eSStefano Zampini 4046718818eSStefano Zampini /* Check matrices sizes */ 4056718818eSStefano Zampini Am = A->rmap->N; 4066718818eSStefano Zampini An = A->cmap->N; 4076718818eSStefano Zampini Bm = B->rmap->N; 4086718818eSStefano Zampini Bn = B->cmap->N; 4096718818eSStefano Zampini Cm = C ? C->rmap->N : 0; 4106718818eSStefano Zampini Cn = C ? C->cmap->N : 0; 4119371c9d4SSatish Balay if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { 4129371c9d4SSatish Balay PetscInt t = Bn; 4139371c9d4SSatish Balay Bn = Bm; 4149371c9d4SSatish Balay Bm = t; 4159371c9d4SSatish Balay } 4169371c9d4SSatish Balay if (product->type == MATPRODUCT_AtB) { 4179371c9d4SSatish Balay PetscInt t = An; 4189371c9d4SSatish Balay An = Am; 4199371c9d4SSatish Balay Am = t; 4209371c9d4SSatish Balay } 4219371c9d4SSatish 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, 4229371c9d4SSatish Balay MatProductTypes[product->type], A->rmap->N, A->cmap->N, bname, B->rmap->N, B->cmap->N); 4239371c9d4SSatish 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, 4249371c9d4SSatish Balay MatProductTypes[product->type], B->rmap->N, B->cmap->N, Cm, Cn); 4254222ddf1SHong Zhang 4264222ddf1SHong Zhang fA = A->ops->productsetfromoptions; 4274222ddf1SHong Zhang fB = B->ops->productsetfromoptions; 4286718818eSStefano Zampini fC = C ? C->ops->productsetfromoptions : fA; 4296718818eSStefano Zampini if (C) { 4309566063dSJacob 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)); 4316718818eSStefano Zampini } else { 4329566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, "MatProductType %s for A %s, %s %s\n", MatProductTypes[product->type], ((PetscObject)A)->type_name, bname, ((PetscObject)B)->type_name)); 4336718818eSStefano Zampini } 4344222ddf1SHong Zhang if (fA == fB && fA == fC && fA) { 4359566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " matching op\n")); 4369566063dSJacob Faibussowitsch PetscCall((*fA)(mat)); 4378d7b260cSStefano Zampini } 4388d7b260cSStefano Zampini /* We may have found f but it did not succeed */ 4398d7b260cSStefano Zampini if (!mat->ops->productsymbolic) { /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 4404222ddf1SHong Zhang char mtypes[256]; 4419566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_", sizeof(mtypes))); 4429566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)A)->type_name, sizeof(mtypes))); 4439566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4449566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)B)->type_name, sizeof(mtypes))); 4456718818eSStefano Zampini if (C) { 4469566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4479566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)C)->type_name, sizeof(mtypes))); 4486718818eSStefano Zampini } 4499566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_C", sizeof(mtypes))); 4504222ddf1SHong Zhang 4519566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4529566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4534222ddf1SHong Zhang if (!f) { 4549566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4559566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4564222ddf1SHong Zhang } 4576718818eSStefano Zampini if (!f && C) { 4589566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4599566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4604222ddf1SHong Zhang } 4619566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4626718818eSStefano Zampini 4636718818eSStefano Zampini /* We may have found f but it did not succeed */ 464013e2dc7SBarry Smith /* some matrices (i.e. MATTRANSPOSEVIRTUAL, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */ 4656718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4669566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_anytype_C", sizeof(mtypes))); 4679566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4689566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4696718818eSStefano Zampini if (!f) { 4709566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4719566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4726718818eSStefano Zampini } 4736718818eSStefano Zampini if (!f && C) { 4749566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4759566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4766718818eSStefano Zampini } 4776718818eSStefano Zampini } 4789566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4794222ddf1SHong Zhang } 4804222ddf1SHong Zhang 4816718818eSStefano Zampini /* We may have found f but it did not succeed */ 4826718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4836718818eSStefano Zampini /* we can still compute the product if B is of type dense */ 4846718818eSStefano Zampini if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) { 4856718818eSStefano Zampini PetscBool isdense; 4866718818eSStefano Zampini 4879566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 4886718818eSStefano Zampini if (isdense) { 4896718818eSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_X_Dense; 4909566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " using basic looping over columns of a dense matrix\n")); 4916718818eSStefano Zampini } 4925415d71bSStefano Zampini } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Unsafe() for triple products only */ 4936718818eSStefano Zampini /* 4946718818eSStefano Zampini TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if 4958d7b260cSStefano Zampini the combination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result 4966718818eSStefano Zampini before computing the symbolic phase 4976718818eSStefano Zampini */ 4989566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " symbolic product not supported, using MatProductSymbolic_Unsafe() implementation\n")); 4995415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_Unsafe; 5004222ddf1SHong Zhang } 5016718818eSStefano Zampini } 50248a46eb9SPierre Jolivet if (!mat->ops->productsymbolic) PetscCall(PetscInfo(mat, " symbolic product is not supported\n")); 5034222ddf1SHong Zhang PetscFunctionReturn(0); 5044222ddf1SHong Zhang } 5054222ddf1SHong Zhang 5064222ddf1SHong Zhang /*@C 50711a5261eSBarry Smith MatProductSetFromOptions - Sets the options for the computation of a matrix-matrix product where the type, the algorithm etc are determined from the options database. 5084222ddf1SHong Zhang 5094222ddf1SHong Zhang Logically Collective on Mat 5104222ddf1SHong Zhang 5114222ddf1SHong Zhang Input Parameter: 5124222ddf1SHong Zhang . mat - the matrix 5134222ddf1SHong Zhang 5146718818eSStefano Zampini Options Database Keys: 515f5368d60SBarry Smith . -mat_product_clear - Clear intermediate data structures after `MatProductNumeric()` has been called 5164222ddf1SHong Zhang 5176718818eSStefano Zampini Level: intermediate 5186718818eSStefano Zampini 519f5368d60SBarry Smith .seealso: `MatSetFromOptions()`, `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 5204222ddf1SHong Zhang @*/ 521d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions(Mat mat) 522d71ae5a4SJacob Faibussowitsch { 5234222ddf1SHong Zhang PetscFunctionBegin; 5244222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5256718818eSStefano Zampini MatCheckProduct(mat, 1); 52628b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot call MatProductSetFromOptions with already present data"); 527d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)mat); 5289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_product_clear", "Clear intermediate data structures after MatProductNumeric() has been called", "MatProductClear", mat->product->clear, &mat->product->clear, NULL)); 5299566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-mat_freeintermediatedatastructures", "-mat_product_clear", "3.13", "Or call MatProductClear() after MatProductNumeric()")); 530d0609cedSBarry Smith PetscOptionsEnd(); 5319566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Private(mat)); 53228b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing product after setup phase"); 5336718818eSStefano Zampini PetscFunctionReturn(0); 5346718818eSStefano Zampini } 5356718818eSStefano Zampini 5366718818eSStefano Zampini /*@C 53711a5261eSBarry Smith MatProductView - View the private `Mat_Product` algorithm object within a matrix 5386718818eSStefano Zampini 539*c3339decSBarry Smith Logically Collective 5406718818eSStefano Zampini 5416718818eSStefano Zampini Input Parameter: 542f5368d60SBarry Smith . mat - the matrix obtained with `MatProductCreate()` or `MatProductCreateWithMat()` 5436718818eSStefano Zampini 5446718818eSStefano Zampini Level: intermediate 5456718818eSStefano Zampini 54611a5261eSBarry Smith .seealso: `MatProductSetFromOptions()`, `MatView()`, `MatProductCreate()`, `MatProductCreateWithMat()` 5476718818eSStefano Zampini @*/ 548d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductView(Mat mat, PetscViewer viewer) 549d71ae5a4SJacob Faibussowitsch { 5506718818eSStefano Zampini PetscFunctionBegin; 5516718818eSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5526718818eSStefano Zampini if (!mat->product) PetscFunctionReturn(0); 5539566063dSJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 5546718818eSStefano Zampini PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 5556718818eSStefano Zampini PetscCheckSameComm(mat, 1, viewer, 2); 5561baa6e33SBarry Smith if (mat->product->view) PetscCall((*mat->product->view)(mat, viewer)); 5574222ddf1SHong Zhang PetscFunctionReturn(0); 5584222ddf1SHong Zhang } 5594222ddf1SHong Zhang 5604222ddf1SHong Zhang /* ----------------------------------------------- */ 5616718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 5626718818eSStefano Zampini * they are dangerous and should be removed in the future */ 563d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_AB(Mat mat) 564d71ae5a4SJacob Faibussowitsch { 5654222ddf1SHong Zhang Mat_Product *product = mat->product; 5664222ddf1SHong Zhang Mat A = product->A, B = product->B; 5674222ddf1SHong Zhang 5684222ddf1SHong Zhang PetscFunctionBegin; 5699566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, B, mat)); 5704222ddf1SHong Zhang PetscFunctionReturn(0); 5714222ddf1SHong Zhang } 5724222ddf1SHong Zhang 573d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_AtB(Mat mat) 574d71ae5a4SJacob Faibussowitsch { 5754222ddf1SHong Zhang Mat_Product *product = mat->product; 5764222ddf1SHong Zhang Mat A = product->A, B = product->B; 5774222ddf1SHong Zhang 5784222ddf1SHong Zhang PetscFunctionBegin; 5799566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultnumeric)(A, B, mat)); 5804222ddf1SHong Zhang PetscFunctionReturn(0); 5814222ddf1SHong Zhang } 5824222ddf1SHong Zhang 583d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_ABt(Mat mat) 584d71ae5a4SJacob Faibussowitsch { 5854222ddf1SHong Zhang Mat_Product *product = mat->product; 5864222ddf1SHong Zhang Mat A = product->A, B = product->B; 5874222ddf1SHong Zhang 5884222ddf1SHong Zhang PetscFunctionBegin; 5899566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultnumeric)(A, B, mat)); 5904222ddf1SHong Zhang PetscFunctionReturn(0); 5914222ddf1SHong Zhang } 5924222ddf1SHong Zhang 593d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_PtAP(Mat mat) 594d71ae5a4SJacob Faibussowitsch { 5954222ddf1SHong Zhang Mat_Product *product = mat->product; 5964222ddf1SHong Zhang Mat A = product->A, B = product->B; 5974222ddf1SHong Zhang 5984222ddf1SHong Zhang PetscFunctionBegin; 5999566063dSJacob Faibussowitsch PetscCall((*mat->ops->ptapnumeric)(A, B, mat)); 6004222ddf1SHong Zhang PetscFunctionReturn(0); 6014222ddf1SHong Zhang } 6024222ddf1SHong Zhang 603d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_RARt(Mat mat) 604d71ae5a4SJacob Faibussowitsch { 6054222ddf1SHong Zhang Mat_Product *product = mat->product; 6064222ddf1SHong Zhang Mat A = product->A, B = product->B; 6074222ddf1SHong Zhang 6084222ddf1SHong Zhang PetscFunctionBegin; 6099566063dSJacob Faibussowitsch PetscCall((*mat->ops->rartnumeric)(A, B, mat)); 6104222ddf1SHong Zhang PetscFunctionReturn(0); 6114222ddf1SHong Zhang } 6124222ddf1SHong Zhang 613d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric_ABC(Mat mat) 614d71ae5a4SJacob Faibussowitsch { 6154222ddf1SHong Zhang Mat_Product *product = mat->product; 6164222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 6174222ddf1SHong Zhang 6184222ddf1SHong Zhang PetscFunctionBegin; 6199566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultnumeric)(A, B, C, mat)); 6204222ddf1SHong Zhang PetscFunctionReturn(0); 6214222ddf1SHong Zhang } 6224222ddf1SHong Zhang 6236718818eSStefano Zampini /* ----------------------------------------------- */ 6246718818eSStefano Zampini 6254222ddf1SHong Zhang /*@ 62611a5261eSBarry Smith MatProductNumeric - Compute a matrix product with numerical values. 6274222ddf1SHong Zhang 628*c3339decSBarry Smith Collective 6294222ddf1SHong Zhang 6306718818eSStefano Zampini Input/Output Parameter: 6316718818eSStefano Zampini . mat - the matrix holding the product 6324222ddf1SHong Zhang 6334222ddf1SHong Zhang Level: intermediate 6344222ddf1SHong Zhang 63511a5261eSBarry Smith Note: 63611a5261eSBarry Smith `MatProductSymbolic()` must have been called on mat before calling this function 6376718818eSStefano Zampini 63811a5261eSBarry Smith .seealso: `MatProductSetAlgorithm()`, `MatProductSetType()`, `MatProductCreate()`, `MatSetType()`, `MatProductSymbolic()` 6394222ddf1SHong Zhang @*/ 640d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductNumeric(Mat mat) 641d71ae5a4SJacob Faibussowitsch { 642e017e560SStefano Zampini PetscLogEvent eventtype = -1; 6432e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 6444222ddf1SHong Zhang 6454222ddf1SHong Zhang PetscFunctionBegin; 6464222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6476718818eSStefano Zampini MatCheckProduct(mat, 1); 648e017e560SStefano Zampini switch (mat->product->type) { 649d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 650d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMultNumeric; 651d71ae5a4SJacob Faibussowitsch break; 652d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 653d71ae5a4SJacob Faibussowitsch eventtype = MAT_TransposeMatMultNumeric; 654d71ae5a4SJacob Faibussowitsch break; 655d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 656d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatTransposeMultNumeric; 657d71ae5a4SJacob Faibussowitsch break; 658d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 659d71ae5a4SJacob Faibussowitsch eventtype = MAT_PtAPNumeric; 660d71ae5a4SJacob Faibussowitsch break; 661d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 662d71ae5a4SJacob Faibussowitsch eventtype = MAT_RARtNumeric; 663d71ae5a4SJacob Faibussowitsch break; 664d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 665d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMatMultNumeric; 666d71ae5a4SJacob Faibussowitsch break; 667d71ae5a4SJacob Faibussowitsch default: 668d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 669e017e560SStefano Zampini } 6708d7b260cSStefano Zampini 6714222ddf1SHong Zhang if (mat->ops->productnumeric) { 6729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 673dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 6749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 6752e105a96SStefano Zampini } else missing = PETSC_TRUE; 6762e105a96SStefano Zampini 6772e105a96SStefano Zampini if (missing || !mat->product) { 6782e105a96SStefano Zampini char errstr[256]; 6792e105a96SStefano Zampini 6802e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 6819566063dSJacob 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)); 6822e105a96SStefano Zampini } else { 6839566063dSJacob 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)); 6842e105a96SStefano Zampini } 68528b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified numeric phase for product %s", errstr); 68628b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 6872e105a96SStefano Zampini } 6882e105a96SStefano Zampini 6891baa6e33SBarry Smith if (mat->product->clear) PetscCall(MatProductClear(mat)); 6909566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6914222ddf1SHong Zhang PetscFunctionReturn(0); 6924222ddf1SHong Zhang } 6934222ddf1SHong Zhang 6944222ddf1SHong Zhang /* ----------------------------------------------- */ 6956718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 6966718818eSStefano Zampini * they are dangerous and should be removed in the future */ 697d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_AB(Mat mat) 698d71ae5a4SJacob Faibussowitsch { 6994222ddf1SHong Zhang Mat_Product *product = mat->product; 7004222ddf1SHong Zhang Mat A = product->A, B = product->B; 7014222ddf1SHong Zhang 7024222ddf1SHong Zhang PetscFunctionBegin; 7039566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultsymbolic)(A, B, product->fill, mat)); 7044222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AB; 7054222ddf1SHong Zhang PetscFunctionReturn(0); 7064222ddf1SHong Zhang } 7074222ddf1SHong Zhang 708d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_AtB(Mat mat) 709d71ae5a4SJacob Faibussowitsch { 7104222ddf1SHong Zhang Mat_Product *product = mat->product; 7114222ddf1SHong Zhang Mat A = product->A, B = product->B; 7124222ddf1SHong Zhang 7134222ddf1SHong Zhang PetscFunctionBegin; 7149566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultsymbolic)(A, B, product->fill, mat)); 7154222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AtB; 7164222ddf1SHong Zhang PetscFunctionReturn(0); 7174222ddf1SHong Zhang } 7184222ddf1SHong Zhang 719d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABt(Mat mat) 720d71ae5a4SJacob Faibussowitsch { 7214222ddf1SHong Zhang Mat_Product *product = mat->product; 7224222ddf1SHong Zhang Mat A = product->A, B = product->B; 7234222ddf1SHong Zhang 7244222ddf1SHong Zhang PetscFunctionBegin; 7259566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultsymbolic)(A, B, product->fill, mat)); 7264222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABt; 7274222ddf1SHong Zhang PetscFunctionReturn(0); 7284222ddf1SHong Zhang } 7294222ddf1SHong Zhang 730d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABC(Mat mat) 731d71ae5a4SJacob Faibussowitsch { 7324222ddf1SHong Zhang Mat_Product *product = mat->product; 7334222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 7344222ddf1SHong Zhang 7354222ddf1SHong Zhang PetscFunctionBegin; 7369566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultsymbolic)(A, B, C, product->fill, mat)); 7374222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABC; 7384222ddf1SHong Zhang PetscFunctionReturn(0); 7394222ddf1SHong Zhang } 7404222ddf1SHong Zhang 7416718818eSStefano Zampini /* ----------------------------------------------- */ 7426718818eSStefano Zampini 7434222ddf1SHong Zhang /*@ 744f5368d60SBarry Smith MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical product done with 745f5368d60SBarry Smith `MatProductNumeric()` 7464222ddf1SHong Zhang 747*c3339decSBarry Smith Collective 7484222ddf1SHong Zhang 7496718818eSStefano Zampini Input/Output Parameter: 7504222ddf1SHong Zhang . mat - the matrix to hold a product 7514222ddf1SHong Zhang 7524222ddf1SHong Zhang Level: intermediate 7534222ddf1SHong Zhang 75411a5261eSBarry Smith Note: 75511a5261eSBarry Smith `MatProductSetFromOptions()` must have been called on mat before calling this function 7566718818eSStefano Zampini 757db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductSetFromOptions()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 7584222ddf1SHong Zhang @*/ 759d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic(Mat mat) 760d71ae5a4SJacob Faibussowitsch { 7614222ddf1SHong Zhang PetscLogEvent eventtype = -1; 7622e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 7634222ddf1SHong Zhang 7644222ddf1SHong Zhang PetscFunctionBegin; 7654222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7666718818eSStefano Zampini MatCheckProduct(mat, 1); 76728b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot run symbolic phase. Product data not empty"); 7686718818eSStefano Zampini switch (mat->product->type) { 769d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 770d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMultSymbolic; 771d71ae5a4SJacob Faibussowitsch break; 772d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AtB: 773d71ae5a4SJacob Faibussowitsch eventtype = MAT_TransposeMatMultSymbolic; 774d71ae5a4SJacob Faibussowitsch break; 775d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 776d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatTransposeMultSymbolic; 777d71ae5a4SJacob Faibussowitsch break; 778d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 779d71ae5a4SJacob Faibussowitsch eventtype = MAT_PtAPSymbolic; 780d71ae5a4SJacob Faibussowitsch break; 781d71ae5a4SJacob Faibussowitsch case MATPRODUCT_RARt: 782d71ae5a4SJacob Faibussowitsch eventtype = MAT_RARtSymbolic; 783d71ae5a4SJacob Faibussowitsch break; 784d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABC: 785d71ae5a4SJacob Faibussowitsch eventtype = MAT_MatMatMultSymbolic; 786d71ae5a4SJacob Faibussowitsch break; 787d71ae5a4SJacob Faibussowitsch default: 788d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 7894222ddf1SHong Zhang } 7906718818eSStefano Zampini mat->ops->productnumeric = NULL; 7914222ddf1SHong Zhang if (mat->ops->productsymbolic) { 7929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 793dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 7949566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 7952e105a96SStefano Zampini } else missing = PETSC_TRUE; 7962e105a96SStefano Zampini 7972e105a96SStefano Zampini if (missing || !mat->product || !mat->ops->productnumeric) { 7982e105a96SStefano Zampini char errstr[256]; 7992e105a96SStefano Zampini 8002e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 8019566063dSJacob 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)); 8022e105a96SStefano Zampini } else { 8039566063dSJacob 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)); 8042e105a96SStefano Zampini } 80528b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified symbolic phase for product %s. Call MatProductSetFromOptions() first", errstr); 80628b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 8072e105a96SStefano Zampini } 8084222ddf1SHong Zhang PetscFunctionReturn(0); 8094222ddf1SHong Zhang } 8104222ddf1SHong Zhang 8114222ddf1SHong Zhang /*@ 8124222ddf1SHong Zhang MatProductSetFill - Set an expected fill of the matrix product. 8134222ddf1SHong Zhang 8144222ddf1SHong Zhang Collective on Mat 8154222ddf1SHong Zhang 8164222ddf1SHong Zhang Input Parameters: 81711a5261eSBarry Smith + mat - the matrix product result matrix 818f5368d60SBarry Smith - fill - expected fill as ratio of nnz(mat)/(nnz(A) + nnz(B) + nnz(C)); use `PETSC_DEFAULT` if you do not have a good estimate. If the product is a dense matrix, this value is not used. 8194222ddf1SHong Zhang 8204222ddf1SHong Zhang Level: intermediate 8214222ddf1SHong Zhang 82211a5261eSBarry Smith .seealso: `MatProductSetFromOptions()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 8234222ddf1SHong Zhang @*/ 824d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFill(Mat mat, PetscReal fill) 825d71ae5a4SJacob Faibussowitsch { 8264222ddf1SHong Zhang PetscFunctionBegin; 8274222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8286718818eSStefano Zampini MatCheckProduct(mat, 1); 8296718818eSStefano Zampini if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0; 8306718818eSStefano Zampini else mat->product->fill = fill; 8314222ddf1SHong Zhang PetscFunctionReturn(0); 8324222ddf1SHong Zhang } 8334222ddf1SHong Zhang 8344222ddf1SHong Zhang /*@ 835f5368d60SBarry Smith MatProductSetAlgorithm - Requests a particular algorithm for a matrix product computation that will perform to compute the given matrix 8364222ddf1SHong Zhang 837*c3339decSBarry Smith Collective 8384222ddf1SHong Zhang 8394222ddf1SHong Zhang Input Parameters: 8404222ddf1SHong Zhang + mat - the matrix product 841f5368d60SBarry Smith - alg - particular implementation algorithm of the matrix product, e.g., `MATPRODUCTALGORITHMDEFAULT`. 8423e662e0bSHong Zhang 8433e662e0bSHong Zhang Options Database Key: 8443e662e0bSHong Zhang . -mat_product_algorithm <algorithm> - Sets the algorithm; use -help for a list 8453e662e0bSHong Zhang of available algorithms (for instance, scalable, outerproduct, etc.) 8464222ddf1SHong Zhang 8474222ddf1SHong Zhang Level: intermediate 8484222ddf1SHong Zhang 84911a5261eSBarry Smith .seealso: `MatProductSetType()`, `MatProductSetFill()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType` 8504222ddf1SHong Zhang @*/ 851d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetAlgorithm(Mat mat, MatProductAlgorithm alg) 852d71ae5a4SJacob Faibussowitsch { 8534222ddf1SHong Zhang PetscFunctionBegin; 8544222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8556718818eSStefano Zampini MatCheckProduct(mat, 1); 8569566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product->alg)); 8579566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(alg, &mat->product->alg)); 8584222ddf1SHong Zhang PetscFunctionReturn(0); 8594222ddf1SHong Zhang } 8604222ddf1SHong Zhang 8614222ddf1SHong Zhang /*@ 862f5368d60SBarry Smith MatProductSetType - Sets a particular matrix product type to be used to compute the given matrix 8634222ddf1SHong Zhang 864*c3339decSBarry Smith Collective 8654222ddf1SHong Zhang 8664222ddf1SHong Zhang Input Parameters: 8674222ddf1SHong Zhang + mat - the matrix 868f5368d60SBarry Smith - productype - matrix product type, e.g., `MATPRODUCT_AB`,`MATPRODUCT_AtB`,`MATPRODUCT_ABt`,`MATPRODUCT_PtAP`,`MATPRODUCT_RARt`,`MATPRODUCT_ABC`. 8694222ddf1SHong Zhang 8704222ddf1SHong Zhang Level: intermediate 8714222ddf1SHong Zhang 872f5368d60SBarry Smith Note: 87311a5261eSBarry Smith The small t represents the transpose operation. 874f5368d60SBarry Smith 87511a5261eSBarry Smith .seealso: `MatProductCreate()`, `MatProductType`, `MatProductType`, 87611a5261eSBarry Smith `MATPRODUCT_AB`, `MATPRODUCT_AtB`, `MATPRODUCT_ABt`, `MATPRODUCT_PtAP`, `MATPRODUCT_RARt`, `MATPRODUCT_ABC` 8774222ddf1SHong Zhang @*/ 878d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetType(Mat mat, MatProductType productype) 879d71ae5a4SJacob Faibussowitsch { 8804222ddf1SHong Zhang PetscFunctionBegin; 8814222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8826718818eSStefano Zampini MatCheckProduct(mat, 1); 8837a3c3d58SStefano Zampini PetscValidLogicalCollectiveEnum(mat, productype, 2); 8846718818eSStefano Zampini if (productype != mat->product->type) { 8851baa6e33SBarry Smith if (mat->product->destroy) PetscCall((*mat->product->destroy)(mat->product->data)); 8866718818eSStefano Zampini mat->product->destroy = NULL; 8876718818eSStefano Zampini mat->product->data = NULL; 8886718818eSStefano Zampini mat->ops->productsymbolic = NULL; 8896718818eSStefano Zampini mat->ops->productnumeric = NULL; 8906718818eSStefano Zampini } 8916718818eSStefano Zampini mat->product->type = productype; 8924222ddf1SHong Zhang PetscFunctionReturn(0); 8934222ddf1SHong Zhang } 8944222ddf1SHong Zhang 8954417c5e8SHong Zhang /*@ 89611a5261eSBarry Smith MatProductClear - Clears matrix product internal datastructures. 8974417c5e8SHong Zhang 898*c3339decSBarry Smith Collective 8994417c5e8SHong Zhang 9004417c5e8SHong Zhang Input Parameters: 9014417c5e8SHong Zhang . mat - the product matrix 9024417c5e8SHong Zhang 9034417c5e8SHong Zhang Level: intermediate 9046718818eSStefano Zampini 905f5368d60SBarry Smith Notes: 906f5368d60SBarry Smith This function should be called to remove any intermediate data used to compute the matrix to free up memory. 907f5368d60SBarry Smith 90811a5261eSBarry Smith After having called this function, matrix-matrix operations can no longer be used on mat 909f5368d60SBarry Smith 910f5368d60SBarry Smith .seealso: `MatProductCreate()` 9114417c5e8SHong Zhang @*/ 912d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductClear(Mat mat) 913d71ae5a4SJacob Faibussowitsch { 9144417c5e8SHong Zhang Mat_Product *product = mat->product; 9154417c5e8SHong Zhang 9164417c5e8SHong Zhang PetscFunctionBegin; 9177a3c3d58SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9184417c5e8SHong Zhang if (product) { 9199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 9209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 9219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 9229566063dSJacob Faibussowitsch PetscCall(PetscFree(product->alg)); 9239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork)); 9241baa6e33SBarry Smith if (product->destroy) PetscCall((*product->destroy)(product->data)); 9256718818eSStefano Zampini } 9269566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product)); 9276718818eSStefano Zampini mat->ops->productsymbolic = NULL; 9286718818eSStefano Zampini mat->ops->productnumeric = NULL; 9294417c5e8SHong Zhang PetscFunctionReturn(0); 9304417c5e8SHong Zhang } 9314417c5e8SHong Zhang 9324222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */ 933d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate_Private(Mat A, Mat B, Mat C, Mat D) 934d71ae5a4SJacob Faibussowitsch { 9354222ddf1SHong Zhang Mat_Product *product = NULL; 9364222ddf1SHong Zhang 9374222ddf1SHong Zhang PetscFunctionBegin; 9386718818eSStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 93928b400f6SJacob Faibussowitsch PetscCheck(!D->product, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product already present"); 9404dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&product)); 9414222ddf1SHong Zhang product->A = A; 9424222ddf1SHong Zhang product->B = B; 9434222ddf1SHong Zhang product->C = C; 9446718818eSStefano Zampini product->type = MATPRODUCT_UNSPECIFIED; 9454222ddf1SHong Zhang product->Dwork = NULL; 9464222ddf1SHong Zhang product->api_user = PETSC_FALSE; 9476718818eSStefano Zampini product->clear = PETSC_FALSE; 9484222ddf1SHong Zhang D->product = product; 9494417c5e8SHong Zhang 9509566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(D, MATPRODUCTALGORITHMDEFAULT)); 9519566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(D, PETSC_DEFAULT)); 9527a3c3d58SStefano Zampini 9539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 9549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 9559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 9564222ddf1SHong Zhang PetscFunctionReturn(0); 9574222ddf1SHong Zhang } 9584222ddf1SHong Zhang 9594222ddf1SHong Zhang /*@ 960f5368d60SBarry Smith MatProductCreateWithMat - Setup a given matrix as a matrix product of other matrices 9614222ddf1SHong Zhang 9624222ddf1SHong Zhang Collective on Mat 9634222ddf1SHong Zhang 9644222ddf1SHong Zhang Input Parameters: 9654222ddf1SHong Zhang + A - the first matrix 9664222ddf1SHong Zhang . B - the second matrix 9674222ddf1SHong Zhang . C - the third matrix (optional) 96811a5261eSBarry Smith - D - the matrix which will be used to hold the product 9694222ddf1SHong Zhang 9704222ddf1SHong Zhang Output Parameters: 9714222ddf1SHong Zhang . D - the product matrix 9724222ddf1SHong Zhang 9736718818eSStefano Zampini Notes: 974f5368d60SBarry Smith Use `MatProductCreate()` if the matrix you wish computed (the D matrix) does not already exist 975f5368d60SBarry Smith 976f5368d60SBarry Smith See `MatProductCreate()` for details on the usage of the MatProduct routines 977f5368d60SBarry Smith 978f5368d60SBarry Smith Any product data currently attached to D will be cleared 9796718818eSStefano Zampini 9804222ddf1SHong Zhang Level: intermediate 9814222ddf1SHong Zhang 982db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductClear()` 9834222ddf1SHong Zhang @*/ 984d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreateWithMat(Mat A, Mat B, Mat C, Mat D) 985d71ae5a4SJacob Faibussowitsch { 9864222ddf1SHong Zhang PetscFunctionBegin; 9874222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9884222ddf1SHong Zhang PetscValidType(A, 1); 9894222ddf1SHong Zhang MatCheckPreallocated(A, 1); 99028b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 99128b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9924222ddf1SHong Zhang 9934222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 9944222ddf1SHong Zhang PetscValidType(B, 2); 9954222ddf1SHong Zhang MatCheckPreallocated(B, 2); 99628b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 99728b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9984222ddf1SHong Zhang 9994222ddf1SHong Zhang if (C) { 10004222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 10014222ddf1SHong Zhang PetscValidType(C, 3); 10024222ddf1SHong Zhang MatCheckPreallocated(C, 3); 100328b400f6SJacob Faibussowitsch PetscCheck(C->assembled, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 100428b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10054222ddf1SHong Zhang } 10064222ddf1SHong Zhang 10074222ddf1SHong Zhang PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 10084222ddf1SHong Zhang PetscValidType(D, 4); 10094222ddf1SHong Zhang MatCheckPreallocated(D, 4); 101028b400f6SJacob Faibussowitsch PetscCheck(D->assembled, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 101128b400f6SJacob Faibussowitsch PetscCheck(!D->factortype, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10124222ddf1SHong Zhang 10134222ddf1SHong Zhang /* Create a supporting struct and attach it to D */ 10149566063dSJacob Faibussowitsch PetscCall(MatProductClear(D)); 10159566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, D)); 10164222ddf1SHong Zhang PetscFunctionReturn(0); 10174222ddf1SHong Zhang } 10184222ddf1SHong Zhang 10194222ddf1SHong Zhang /*@ 102011a5261eSBarry Smith MatProductCreate - create a matrix to hold the result of a matrix-matrix product operation 10214222ddf1SHong Zhang 102211a5261eSBarry Smith Collective on A 10234222ddf1SHong Zhang 10244222ddf1SHong Zhang Input Parameters: 10254222ddf1SHong Zhang + A - the first matrix 10264222ddf1SHong Zhang . B - the second matrix 10274222ddf1SHong Zhang - C - the third matrix (optional) 10284222ddf1SHong Zhang 10294222ddf1SHong Zhang Output Parameters: 10304222ddf1SHong Zhang . D - the product matrix 10314222ddf1SHong Zhang 10324222ddf1SHong Zhang Level: intermediate 10334222ddf1SHong Zhang 1034f5368d60SBarry Smith Example of Usage: 1035f5368d60SBarry Smith .vb 103611a5261eSBarry Smith MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 103711a5261eSBarry Smith MatProductSetType(D, MATPRODUCT_AB or MATPRODUCT_AtB or MATPRODUCT_ABt or MATPRODUCT_PtAP or MATPRODUCT_RARt or MATPRODUCT_ABC) 103811a5261eSBarry Smith MatProductSetAlgorithm(D, alg) 103911a5261eSBarry Smith MatProductSetFill(D,fill) 104011a5261eSBarry Smith MatProductSetFromOptions(D) 104111a5261eSBarry Smith MatProductSymbolic(D) 104211a5261eSBarry Smith MatProductNumeric(D) 1043f5368d60SBarry Smith Change numerical values in some of the matrices 104411a5261eSBarry Smith MatProductNumeric(D) 1045f5368d60SBarry Smith .ve 1046f5368d60SBarry Smith 1047f5368d60SBarry Smith Notes: 1048f5368d60SBarry Smith Use `MatProductCreateWithMat()` if the matrix you wish computed, the D matrix, already exists. 1049f5368d60SBarry Smith 1050f5368d60SBarry Smith The information computed during the symbolic stage can be reused for new numerical computations with the same non-zero structure 1051f5368d60SBarry Smith 105211a5261eSBarry Smith Developer Note: 1053f5368d60SBarry Smith It is undocumented what happens if the nonzero structure of the input matrices changes. Is the symbolic stage automatically redone? Does it crash? 1054f5368d60SBarry Smith Is there error checking for it? 1055f5368d60SBarry Smith 1056f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductClear()` 10574222ddf1SHong Zhang @*/ 1058d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductCreate(Mat A, Mat B, Mat C, Mat *D) 1059d71ae5a4SJacob Faibussowitsch { 10604222ddf1SHong Zhang PetscFunctionBegin; 10614222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10624222ddf1SHong Zhang PetscValidType(A, 1); 10634222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10644222ddf1SHong Zhang PetscValidType(B, 2); 106528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix A"); 106628b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix B"); 10674222ddf1SHong Zhang 10684222ddf1SHong Zhang if (C) { 10694222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 10704222ddf1SHong Zhang PetscValidType(C, 3); 107128b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix C"); 10724222ddf1SHong Zhang } 10734222ddf1SHong Zhang 10744222ddf1SHong Zhang PetscValidPointer(D, 4); 10759566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), D)); 10769566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, *D)); 10774222ddf1SHong Zhang PetscFunctionReturn(0); 10784222ddf1SHong Zhang } 10795415d71bSStefano Zampini 10805415d71bSStefano Zampini /* 10815415d71bSStefano Zampini These are safe basic implementations of ABC, RARt and PtAP 10825415d71bSStefano Zampini that do not rely on mat->ops->matmatop function pointers. 10835415d71bSStefano Zampini They only use the MatProduct API and are currently used by 10845415d71bSStefano Zampini cuSPARSE and KOKKOS-KERNELS backends 10855415d71bSStefano Zampini */ 1086ec446438SStefano Zampini typedef struct { 10875415d71bSStefano Zampini Mat BC; 10885415d71bSStefano Zampini Mat ABC; 10895415d71bSStefano Zampini } MatMatMatPrivate; 10905415d71bSStefano Zampini 1091d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_MatMatMatPrivate(void *data) 1092d71ae5a4SJacob Faibussowitsch { 10935415d71bSStefano Zampini MatMatMatPrivate *mmdata = (MatMatMatPrivate *)data; 10945415d71bSStefano Zampini 10955415d71bSStefano Zampini PetscFunctionBegin; 10969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->BC)); 10979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->ABC)); 10989566063dSJacob Faibussowitsch PetscCall(PetscFree(data)); 10995415d71bSStefano Zampini PetscFunctionReturn(0); 11005415d71bSStefano Zampini } 11015415d71bSStefano Zampini 1102d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 1103d71ae5a4SJacob Faibussowitsch { 11045415d71bSStefano Zampini Mat_Product *product = mat->product; 11055415d71bSStefano Zampini MatMatMatPrivate *mmabc; 11065415d71bSStefano Zampini 11075415d71bSStefano Zampini PetscFunctionBegin; 11085415d71bSStefano Zampini MatCheckProduct(mat, 1); 110928b400f6SJacob Faibussowitsch PetscCheck(mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data empty"); 11105415d71bSStefano Zampini mmabc = (MatMatMatPrivate *)mat->product->data; 111128b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productnumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing numeric stage"); 1112ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 11139566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productnumeric)(mmabc->BC)); 11145415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the numeric phase on mat */ 11155415d71bSStefano Zampini mat->product = mmabc->ABC->product; 11165415d71bSStefano Zampini mat->ops->productnumeric = mmabc->ABC->ops->productnumeric; 1117ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 1118dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 11195415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 11205415d71bSStefano Zampini mat->product = product; 11215415d71bSStefano Zampini PetscFunctionReturn(0); 11225415d71bSStefano Zampini } 11235415d71bSStefano Zampini 1124d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 1125d71ae5a4SJacob Faibussowitsch { 11265415d71bSStefano Zampini Mat_Product *product = mat->product; 11275415d71bSStefano Zampini Mat A, B, C; 11285415d71bSStefano Zampini MatProductType p1, p2; 11295415d71bSStefano Zampini MatMatMatPrivate *mmabc; 113065e4b4d4SStefano Zampini const char *prefix; 11315415d71bSStefano Zampini 11325415d71bSStefano Zampini PetscFunctionBegin; 11335415d71bSStefano Zampini MatCheckProduct(mat, 1); 113428b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data not empty"); 11359566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(mat, &prefix)); 11369566063dSJacob Faibussowitsch PetscCall(PetscNew(&mmabc)); 11375415d71bSStefano Zampini product->data = mmabc; 11385415d71bSStefano Zampini product->destroy = MatDestroy_MatMatMatPrivate; 11395415d71bSStefano Zampini switch (product->type) { 11405415d71bSStefano Zampini case MATPRODUCT_PtAP: 11415415d71bSStefano Zampini p1 = MATPRODUCT_AB; 11425415d71bSStefano Zampini p2 = MATPRODUCT_AtB; 11435415d71bSStefano Zampini A = product->B; 11445415d71bSStefano Zampini B = product->A; 11455415d71bSStefano Zampini C = product->B; 11465415d71bSStefano Zampini break; 11475415d71bSStefano Zampini case MATPRODUCT_RARt: 11485415d71bSStefano Zampini p1 = MATPRODUCT_ABt; 11495415d71bSStefano Zampini p2 = MATPRODUCT_AB; 11505415d71bSStefano Zampini A = product->B; 11515415d71bSStefano Zampini B = product->A; 11525415d71bSStefano Zampini C = product->B; 11535415d71bSStefano Zampini break; 11545415d71bSStefano Zampini case MATPRODUCT_ABC: 11555415d71bSStefano Zampini p1 = MATPRODUCT_AB; 11565415d71bSStefano Zampini p2 = MATPRODUCT_AB; 11575415d71bSStefano Zampini A = product->A; 11585415d71bSStefano Zampini B = product->B; 11595415d71bSStefano Zampini C = product->C; 11605415d71bSStefano Zampini break; 1161d71ae5a4SJacob Faibussowitsch default: 1162d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 11635415d71bSStefano Zampini } 11649566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &mmabc->BC)); 11659566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->BC, prefix)); 11669566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->BC, "P1_")); 11679566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->BC, p1)); 11689566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->BC, MATPRODUCTALGORITHMDEFAULT)); 11699566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->BC, product->fill)); 11705415d71bSStefano Zampini mmabc->BC->product->api_user = product->api_user; 11719566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->BC)); 117228b400f6SJacob 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); 1173bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 11749566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productsymbolic)(mmabc->BC)); 11755415d71bSStefano Zampini 11769566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, mmabc->BC, NULL, &mmabc->ABC)); 11779566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->ABC, prefix)); 11789566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->ABC, "P2_")); 11799566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->ABC, p2)); 11809566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->ABC, MATPRODUCTALGORITHMDEFAULT)); 11819566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->ABC, product->fill)); 11825415d71bSStefano Zampini mmabc->ABC->product->api_user = product->api_user; 11839566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->ABC)); 118428b400f6SJacob 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); 11855415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the symbolic phase on mat */ 11865415d71bSStefano Zampini mat->product = mmabc->ABC->product; 11875415d71bSStefano Zampini mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic; 1188bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 1189dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 11905415d71bSStefano Zampini mmabc->ABC->ops->productnumeric = mat->ops->productnumeric; 11915415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_ABC_Basic; 11925415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 11935415d71bSStefano Zampini mat->product = product; 11945415d71bSStefano Zampini PetscFunctionReturn(0); 11955415d71bSStefano Zampini } 1196c600787bSStefano Zampini 1197c600787bSStefano Zampini /*@ 119811a5261eSBarry Smith MatProductGetType - Returns the type of matrix-matrix product associated with the given matrix. 1199c600787bSStefano Zampini 1200c600787bSStefano Zampini Not collective 1201c600787bSStefano Zampini 1202c600787bSStefano Zampini Input Parameter: 1203c600787bSStefano Zampini . mat - the matrix 1204c600787bSStefano Zampini 1205c600787bSStefano Zampini Output Parameter: 120611a5261eSBarry Smith . mtype - the `MatProductType` 1207c600787bSStefano Zampini 1208c600787bSStefano Zampini Level: intermediate 1209c600787bSStefano Zampini 121011a5261eSBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductCreate()`, `MatProductType`, `MatProductAlgorithm` 1211c600787bSStefano Zampini @*/ 1212d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetType(Mat mat, MatProductType *mtype) 1213d71ae5a4SJacob Faibussowitsch { 1214c600787bSStefano Zampini PetscFunctionBegin; 1215c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1216c600787bSStefano Zampini PetscValidPointer(mtype, 2); 1217c600787bSStefano Zampini *mtype = MATPRODUCT_UNSPECIFIED; 1218c600787bSStefano Zampini if (mat->product) *mtype = mat->product->type; 1219c600787bSStefano Zampini PetscFunctionReturn(0); 1220c600787bSStefano Zampini } 1221c600787bSStefano Zampini 1222c600787bSStefano Zampini /*@ 122311a5261eSBarry Smith MatProductGetMats - Returns the matrices associated with the matrix-matrix product this matrix can receive 1224c600787bSStefano Zampini 1225c600787bSStefano Zampini Not collective 1226c600787bSStefano Zampini 1227c600787bSStefano Zampini Input Parameter: 1228c600787bSStefano Zampini . mat - the product matrix 1229c600787bSStefano Zampini 1230c600787bSStefano Zampini Output Parameters: 1231c600787bSStefano Zampini + A - the first matrix 1232c600787bSStefano Zampini . B - the second matrix 1233c600787bSStefano Zampini - C - the third matrix (optional) 1234c600787bSStefano Zampini 1235c600787bSStefano Zampini Level: intermediate 1236c600787bSStefano Zampini 1237f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 1238c600787bSStefano Zampini @*/ 1239d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductGetMats(Mat mat, Mat *A, Mat *B, Mat *C) 1240d71ae5a4SJacob Faibussowitsch { 1241c600787bSStefano Zampini PetscFunctionBegin; 1242c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1243c600787bSStefano Zampini if (A) *A = mat->product ? mat->product->A : NULL; 1244c600787bSStefano Zampini if (B) *B = mat->product ? mat->product->B : NULL; 1245c600787bSStefano Zampini if (C) *C = mat->product ? mat->product->C : NULL; 1246c600787bSStefano Zampini PetscFunctionReturn(0); 1247c600787bSStefano Zampini } 1248