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 177301b172SPierre Jolivet -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANSPOSEMAT) 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 */ 479371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_PtAP_Unsafe(Mat C) { 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 */ 559566063dSJacob Faibussowitsch PetscCall((*C->ops->transposematmultnumeric)(P, AP, C)); 564222ddf1SHong Zhang PetscFunctionReturn(0); 574222ddf1SHong Zhang } 584222ddf1SHong Zhang 599371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_PtAP_Unsafe(Mat C) { 604222ddf1SHong Zhang Mat_Product *product = C->product; 614222ddf1SHong Zhang Mat A = product->A, P = product->B, AP; 624222ddf1SHong Zhang PetscReal fill = product->fill; 634222ddf1SHong Zhang 644222ddf1SHong Zhang PetscFunctionBegin; 659566063dSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)C, "for A %s, P %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 664222ddf1SHong Zhang /* AP = A*P */ 679566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, P, NULL, &AP)); 689566063dSJacob Faibussowitsch PetscCall(MatProductSetType(AP, MATPRODUCT_AB)); 699566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(AP, MATPRODUCTALGORITHMDEFAULT)); 709566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(AP, fill)); 719566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(AP)); 729566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(AP)); 734222ddf1SHong Zhang 744222ddf1SHong Zhang /* C = P^T*AP */ 759566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_AtB)); 769566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 774222ddf1SHong Zhang product->A = P; 784222ddf1SHong Zhang product->B = AP; 799566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 809566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 814222ddf1SHong Zhang 824222ddf1SHong Zhang /* resume user's original input matrix setting for A and B */ 834222ddf1SHong Zhang product->A = A; 844222ddf1SHong Zhang product->B = P; 854222ddf1SHong Zhang product->Dwork = AP; 864222ddf1SHong Zhang 875415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_PtAP_Unsafe; 884222ddf1SHong Zhang PetscFunctionReturn(0); 894222ddf1SHong Zhang } 904222ddf1SHong Zhang 919371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_RARt_Unsafe(Mat C) { 924222ddf1SHong Zhang Mat_Product *product = C->product; 934222ddf1SHong Zhang Mat R = product->B, RA = product->Dwork; 944222ddf1SHong Zhang 954222ddf1SHong Zhang PetscFunctionBegin; 964222ddf1SHong Zhang /* RA = R*A */ 979566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(RA)); 984222ddf1SHong Zhang /* C = RA*R^T */ 999566063dSJacob Faibussowitsch PetscCall((*C->ops->mattransposemultnumeric)(RA, R, C)); 1004222ddf1SHong Zhang PetscFunctionReturn(0); 1014222ddf1SHong Zhang } 1024222ddf1SHong Zhang 1039371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_RARt_Unsafe(Mat C) { 1044222ddf1SHong Zhang Mat_Product *product = C->product; 1054222ddf1SHong Zhang Mat A = product->A, R = product->B, RA; 1064222ddf1SHong Zhang PetscReal fill = product->fill; 1074222ddf1SHong Zhang 1084222ddf1SHong Zhang PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)C, "for A %s, R %s is used\n", ((PetscObject)product->A)->type_name, ((PetscObject)product->B)->type_name)); 1104222ddf1SHong Zhang /* RA = R*A */ 1119566063dSJacob Faibussowitsch PetscCall(MatProductCreate(R, A, NULL, &RA)); 1129566063dSJacob Faibussowitsch PetscCall(MatProductSetType(RA, MATPRODUCT_AB)); 1139566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(RA, MATPRODUCTALGORITHMDEFAULT)); 1149566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(RA, fill)); 1159566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(RA)); 1169566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(RA)); 1174222ddf1SHong Zhang 1184222ddf1SHong Zhang /* C = RA*R^T */ 1199566063dSJacob Faibussowitsch PetscCall(MatProductSetType(C, MATPRODUCT_ABt)); 1209566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(C, MATPRODUCTALGORITHMDEFAULT)); 1214222ddf1SHong Zhang product->A = RA; 1229566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(C)); 1239566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(C)); 1244222ddf1SHong Zhang 1254222ddf1SHong Zhang /* resume user's original input matrix setting for A */ 1264222ddf1SHong Zhang product->A = A; 1274222ddf1SHong Zhang product->Dwork = RA; /* save here so it will be destroyed with product C */ 1285415d71bSStefano Zampini C->ops->productnumeric = MatProductNumeric_RARt_Unsafe; 1294222ddf1SHong Zhang PetscFunctionReturn(0); 1304222ddf1SHong Zhang } 1314222ddf1SHong Zhang 1329371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_ABC_Unsafe(Mat mat) { 1334222ddf1SHong Zhang Mat_Product *product = mat->product; 1344222ddf1SHong Zhang Mat A = product->A, BC = product->Dwork; 1354222ddf1SHong Zhang 1364222ddf1SHong Zhang PetscFunctionBegin; 1374222ddf1SHong Zhang /* Numeric BC = B*C */ 1389566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(BC)); 1394222ddf1SHong Zhang /* Numeric mat = A*BC */ 1409566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, BC, mat)); 1414222ddf1SHong Zhang PetscFunctionReturn(0); 1424222ddf1SHong Zhang } 1434222ddf1SHong Zhang 1449371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_ABC_Unsafe(Mat mat) { 1454222ddf1SHong Zhang Mat_Product *product = mat->product; 1464222ddf1SHong Zhang Mat B = product->B, C = product->C, BC; 1474222ddf1SHong Zhang PetscReal fill = product->fill; 1484222ddf1SHong Zhang 1494222ddf1SHong Zhang PetscFunctionBegin; 1509566063dSJacob 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)); 1514222ddf1SHong Zhang /* Symbolic BC = B*C */ 1529566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &BC)); 1539566063dSJacob Faibussowitsch PetscCall(MatProductSetType(BC, MATPRODUCT_AB)); 1549566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(BC, MATPRODUCTALGORITHMDEFAULT)); 1559566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(BC, fill)); 1569566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(BC)); 1579566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(BC)); 1584222ddf1SHong Zhang 1594222ddf1SHong Zhang /* Symbolic mat = A*BC */ 1609566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mat, MATPRODUCT_AB)); 1619566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mat, MATPRODUCTALGORITHMDEFAULT)); 1624222ddf1SHong Zhang product->B = BC; 1634222ddf1SHong Zhang product->Dwork = BC; 1649566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mat)); 1659566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(mat)); 1664222ddf1SHong Zhang 1674222ddf1SHong Zhang /* resume user's original input matrix setting for B */ 1684222ddf1SHong Zhang product->B = B; 1695415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Unsafe; 1704222ddf1SHong Zhang PetscFunctionReturn(0); 1714222ddf1SHong Zhang } 1724222ddf1SHong Zhang 1739371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_Unsafe(Mat mat) { 1744222ddf1SHong Zhang Mat_Product *product = mat->product; 1754222ddf1SHong Zhang 1764222ddf1SHong Zhang PetscFunctionBegin; 1774222ddf1SHong Zhang switch (product->type) { 1789371c9d4SSatish Balay case MATPRODUCT_PtAP: PetscCall(MatProductSymbolic_PtAP_Unsafe(mat)); break; 1799371c9d4SSatish Balay case MATPRODUCT_RARt: PetscCall(MatProductSymbolic_RARt_Unsafe(mat)); break; 1809371c9d4SSatish Balay case MATPRODUCT_ABC: PetscCall(MatProductSymbolic_ABC_Unsafe(mat)); break; 18198921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[product->type]); 1824222ddf1SHong Zhang } 1834222ddf1SHong Zhang PetscFunctionReturn(0); 1844222ddf1SHong Zhang } 1854222ddf1SHong Zhang 1864222ddf1SHong Zhang /* ----------------------------------------------- */ 1874222ddf1SHong Zhang /*@C 1884222ddf1SHong Zhang MatProductReplaceMats - Replace input matrices for a matrix product. 1894222ddf1SHong Zhang 1904222ddf1SHong Zhang Collective on Mat 1914222ddf1SHong Zhang 1924222ddf1SHong Zhang Input Parameters: 1934222ddf1SHong Zhang + A - the matrix or NULL if not being replaced 1944222ddf1SHong Zhang . B - the matrix or NULL if not being replaced 1954222ddf1SHong Zhang . C - the matrix or NULL if not being replaced 1964222ddf1SHong Zhang - D - the matrix product 1974222ddf1SHong Zhang 1984222ddf1SHong Zhang Level: intermediate 1994222ddf1SHong Zhang 2004222ddf1SHong Zhang Notes: 2016718818eSStefano Zampini To reuse the symbolic phase, input matrices must have exactly the same data structure as the replaced one. 2021cdffd5eSHong Zhang If the type of any of the input matrices is different than what was previously used, or their symmetry flag changed but 203f5368d60SBarry Smith the symbolic phase took advantage of their symmetry, the product is cleared and `MatProductSetFromOptions()` and `MatProductSymbolic()` are invoked again. 2044222ddf1SHong Zhang 205db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductSetFromOptions()`, `MatProductSymbolic().` `MatProductClear()` 2064222ddf1SHong Zhang @*/ 2079371c9d4SSatish Balay PetscErrorCode MatProductReplaceMats(Mat A, Mat B, Mat C, Mat D) { 2086718818eSStefano Zampini Mat_Product *product; 209b94d7dedSBarry Smith PetscBool flgA = PETSC_TRUE, flgB = PETSC_TRUE, flgC = PETSC_TRUE, isset, issym; 2104222ddf1SHong Zhang 2114222ddf1SHong Zhang PetscFunctionBegin; 2127a3c3d58SStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 2136718818eSStefano Zampini MatCheckProduct(D, 4); 2146718818eSStefano Zampini product = D->product; 2154222ddf1SHong Zhang if (A) { 2167a3c3d58SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 2189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, ((PetscObject)A)->type_name, &flgA)); 219b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(A, &isset, &issym)); 220b94d7dedSBarry 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 */ 221fa046f9fSJunchao Zhang flgA = PETSC_FALSE; 222fa046f9fSJunchao Zhang product->symbolic_used_the_fact_A_is_symmetric = PETSC_FALSE; /* reinit */ 223fa046f9fSJunchao Zhang } 2249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 2254222ddf1SHong Zhang product->A = A; 2264222ddf1SHong Zhang } 2274222ddf1SHong Zhang if (B) { 2287a3c3d58SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 2299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 2309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->B, ((PetscObject)B)->type_name, &flgB)); 231b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(B, &isset, &issym)); 232b94d7dedSBarry Smith if (product->symbolic_used_the_fact_B_is_symmetric && isset && !issym) { 233fa046f9fSJunchao Zhang flgB = PETSC_FALSE; 234fa046f9fSJunchao Zhang product->symbolic_used_the_fact_B_is_symmetric = PETSC_FALSE; /* reinit */ 235fa046f9fSJunchao Zhang } 2369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 2374222ddf1SHong Zhang product->B = B; 2384222ddf1SHong Zhang } 2394417c5e8SHong Zhang if (C) { 2407a3c3d58SStefano Zampini PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 2419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 2429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->C, ((PetscObject)C)->type_name, &flgC)); 243b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(C, &isset, &issym)); 244b94d7dedSBarry Smith if (product->symbolic_used_the_fact_C_is_symmetric && isset && !issym) { 245fa046f9fSJunchao Zhang flgC = PETSC_FALSE; 246fa046f9fSJunchao Zhang product->symbolic_used_the_fact_C_is_symmetric = PETSC_FALSE; /* reinit */ 247fa046f9fSJunchao Zhang } 2489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 2494417c5e8SHong Zhang product->C = C; 2504417c5e8SHong Zhang } 2516718818eSStefano Zampini /* Any of the replaced mats is of a different type, reset */ 2526718818eSStefano Zampini if (!flgA || !flgB || !flgC) { 2531baa6e33SBarry Smith if (D->product->destroy) PetscCall((*D->product->destroy)(D->product->data)); 2546718818eSStefano Zampini D->product->destroy = NULL; 2556718818eSStefano Zampini D->product->data = NULL; 2566718818eSStefano Zampini if (D->ops->productnumeric || D->ops->productsymbolic) { 2579566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(D)); 2589566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(D)); 2596718818eSStefano Zampini } 2606718818eSStefano Zampini } 2614222ddf1SHong Zhang PetscFunctionReturn(0); 2624222ddf1SHong Zhang } 2634222ddf1SHong Zhang 2649371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_X_Dense(Mat C) { 2657a3c3d58SStefano Zampini Mat_Product *product = C->product; 2667a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 2677a3c3d58SStefano Zampini PetscInt k, K = B->cmap->N; 2687a3c3d58SStefano Zampini PetscBool t = PETSC_TRUE, iscuda = PETSC_FALSE; 2697a3c3d58SStefano Zampini PetscBool Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE; 2707a3c3d58SStefano Zampini char *Btype = NULL, *Ctype = NULL; 2717a3c3d58SStefano Zampini 2727a3c3d58SStefano Zampini PetscFunctionBegin; 2737a3c3d58SStefano Zampini switch (product->type) { 2749371c9d4SSatish Balay case MATPRODUCT_AB: t = PETSC_FALSE; 2759371c9d4SSatish Balay case MATPRODUCT_AtB: break; 27698921bdaSJacob Faibussowitsch default: 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); 2777a3c3d58SStefano Zampini } 2787a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 2797a3c3d58SStefano Zampini VecType vtype; 2807a3c3d58SStefano Zampini 2819566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A, &vtype)); 2829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype, VECCUDA, &iscuda)); 283*48a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECSEQCUDA, &iscuda)); 284*48a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECMPICUDA, &iscuda)); 2857a3c3d58SStefano Zampini if (iscuda) { /* Make sure we have up-to-date data on the GPU */ 2869566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)B)->type_name, &Btype)); 2879566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(((PetscObject)C)->type_name, &Ctype)); 2889566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 2897a3c3d58SStefano Zampini if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */ 2909566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 2919566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 2927a3c3d58SStefano Zampini } 2939566063dSJacob Faibussowitsch PetscCall(MatConvert(C, MATDENSECUDA, MAT_INPLACE_MATRIX, &C)); 2947a3c3d58SStefano Zampini } else { /* Make sure we have up-to-date data on the CPU */ 2957a3c3d58SStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL) 2967a3c3d58SStefano Zampini Bcpu = B->boundtocpu; 2977a3c3d58SStefano Zampini Ccpu = C->boundtocpu; 2987a3c3d58SStefano Zampini #endif 2999566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, PETSC_TRUE)); 3009566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, PETSC_TRUE)); 3017a3c3d58SStefano Zampini } 3027a3c3d58SStefano Zampini } 3037a3c3d58SStefano Zampini for (k = 0; k < K; k++) { 3047a3c3d58SStefano Zampini Vec x, y; 3057a3c3d58SStefano Zampini 3069566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(B, k, &x)); 3079566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecWrite(C, k, &y)); 3087a3c3d58SStefano Zampini if (t) { 3099566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, x, y)); 3107a3c3d58SStefano Zampini } else { 3119566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, y)); 3127a3c3d58SStefano Zampini } 3139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(B, k, &x)); 3149566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecWrite(C, k, &y)); 3157a3c3d58SStefano Zampini } 3169566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 3179566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 3187a3c3d58SStefano Zampini if (PetscDefined(HAVE_CUDA)) { 3197a3c3d58SStefano Zampini if (iscuda) { 3209566063dSJacob Faibussowitsch PetscCall(MatConvert(B, Btype, MAT_INPLACE_MATRIX, &B)); 3219566063dSJacob Faibussowitsch PetscCall(MatConvert(C, Ctype, MAT_INPLACE_MATRIX, &C)); 3227a3c3d58SStefano Zampini } else { 3239566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(B, Bcpu)); 3249566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C, Ccpu)); 3257a3c3d58SStefano Zampini } 3267a3c3d58SStefano Zampini } 3279566063dSJacob Faibussowitsch PetscCall(PetscFree(Btype)); 3289566063dSJacob Faibussowitsch PetscCall(PetscFree(Ctype)); 3297a3c3d58SStefano Zampini PetscFunctionReturn(0); 3307a3c3d58SStefano Zampini } 3317a3c3d58SStefano Zampini 3329371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_X_Dense(Mat C) { 3337a3c3d58SStefano Zampini Mat_Product *product = C->product; 3347a3c3d58SStefano Zampini Mat A = product->A, B = product->B; 3357a3c3d58SStefano Zampini PetscBool isdense; 3367a3c3d58SStefano Zampini 3377a3c3d58SStefano Zampini PetscFunctionBegin; 3387a3c3d58SStefano Zampini switch (product->type) { 3399371c9d4SSatish Balay case MATPRODUCT_AB: PetscCall(MatSetSizes(C, A->rmap->n, B->cmap->n, A->rmap->N, B->cmap->N)); break; 3409371c9d4SSatish Balay case MATPRODUCT_AtB: PetscCall(MatSetSizes(C, A->cmap->n, B->cmap->n, A->cmap->N, B->cmap->N)); break; 34198921bdaSJacob Faibussowitsch default: 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); 3427a3c3d58SStefano Zampini } 3439566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)C, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 3447a3c3d58SStefano Zampini if (!isdense) { 3459566063dSJacob Faibussowitsch PetscCall(MatSetType(C, ((PetscObject)B)->type_name)); 3466718818eSStefano Zampini /* If matrix type of C was not set or not dense, we need to reset the pointer */ 3477a3c3d58SStefano Zampini C->ops->productsymbolic = MatProductSymbolic_X_Dense; 3487a3c3d58SStefano Zampini } 3496718818eSStefano Zampini C->ops->productnumeric = MatProductNumeric_X_Dense; 3509566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 3517a3c3d58SStefano Zampini PetscFunctionReturn(0); 3527a3c3d58SStefano Zampini } 3537a3c3d58SStefano Zampini 3546718818eSStefano Zampini /* a single driver to query the dispatching */ 3559371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_Private(Mat mat) { 3564222ddf1SHong Zhang Mat_Product *product = mat->product; 3576718818eSStefano Zampini PetscInt Am, An, Bm, Bn, Cm, Cn; 3584222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 3596718818eSStefano Zampini const char *const Bnames[] = {"B", "R", "P"}; 3606718818eSStefano Zampini const char *bname; 3614222ddf1SHong Zhang PetscErrorCode (*fA)(Mat); 3624222ddf1SHong Zhang PetscErrorCode (*fB)(Mat); 3634222ddf1SHong Zhang PetscErrorCode (*fC)(Mat); 3644222ddf1SHong Zhang PetscErrorCode (*f)(Mat) = NULL; 3654222ddf1SHong Zhang 3664222ddf1SHong Zhang PetscFunctionBegin; 3676718818eSStefano Zampini mat->ops->productsymbolic = NULL; 3686718818eSStefano Zampini mat->ops->productnumeric = NULL; 3696718818eSStefano Zampini if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(0); 37028b400f6SJacob Faibussowitsch PetscCheck(A, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing A mat"); 37128b400f6SJacob Faibussowitsch PetscCheck(B, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing B mat"); 372072cda71SBarry Smith PetscCheck(product->type != MATPRODUCT_ABC || C, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing C mat"); 3736718818eSStefano Zampini if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */ 3746718818eSStefano Zampini if (product->type == MATPRODUCT_RARt) bname = Bnames[1]; 3756718818eSStefano Zampini else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2]; 3766718818eSStefano Zampini else bname = Bnames[0]; 3776718818eSStefano Zampini 3786718818eSStefano Zampini /* Check matrices sizes */ 3796718818eSStefano Zampini Am = A->rmap->N; 3806718818eSStefano Zampini An = A->cmap->N; 3816718818eSStefano Zampini Bm = B->rmap->N; 3826718818eSStefano Zampini Bn = B->cmap->N; 3836718818eSStefano Zampini Cm = C ? C->rmap->N : 0; 3846718818eSStefano Zampini Cn = C ? C->cmap->N : 0; 3859371c9d4SSatish Balay if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { 3869371c9d4SSatish Balay PetscInt t = Bn; 3879371c9d4SSatish Balay Bn = Bm; 3889371c9d4SSatish Balay Bm = t; 3899371c9d4SSatish Balay } 3909371c9d4SSatish Balay if (product->type == MATPRODUCT_AtB) { 3919371c9d4SSatish Balay PetscInt t = An; 3929371c9d4SSatish Balay An = Am; 3939371c9d4SSatish Balay Am = t; 3949371c9d4SSatish Balay } 3959371c9d4SSatish 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, 3969371c9d4SSatish Balay MatProductTypes[product->type], A->rmap->N, A->cmap->N, bname, B->rmap->N, B->cmap->N); 3979371c9d4SSatish 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, 3989371c9d4SSatish Balay MatProductTypes[product->type], B->rmap->N, B->cmap->N, Cm, Cn); 3994222ddf1SHong Zhang 4004222ddf1SHong Zhang fA = A->ops->productsetfromoptions; 4014222ddf1SHong Zhang fB = B->ops->productsetfromoptions; 4026718818eSStefano Zampini fC = C ? C->ops->productsetfromoptions : fA; 4036718818eSStefano Zampini if (C) { 4049566063dSJacob 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)); 4056718818eSStefano Zampini } else { 4069566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, "MatProductType %s for A %s, %s %s\n", MatProductTypes[product->type], ((PetscObject)A)->type_name, bname, ((PetscObject)B)->type_name)); 4076718818eSStefano Zampini } 4084222ddf1SHong Zhang if (fA == fB && fA == fC && fA) { 4099566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " matching op\n")); 4109566063dSJacob Faibussowitsch PetscCall((*fA)(mat)); 4118d7b260cSStefano Zampini } 4128d7b260cSStefano Zampini /* We may have found f but it did not succeed */ 4138d7b260cSStefano Zampini if (!mat->ops->productsymbolic) { /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 4144222ddf1SHong Zhang char mtypes[256]; 4159566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_", sizeof(mtypes))); 4169566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)A)->type_name, sizeof(mtypes))); 4179566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4189566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)B)->type_name, sizeof(mtypes))); 4196718818eSStefano Zampini if (C) { 4209566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_", sizeof(mtypes))); 4219566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, ((PetscObject)C)->type_name, sizeof(mtypes))); 4226718818eSStefano Zampini } 4239566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(mtypes, "_C", sizeof(mtypes))); 4244222ddf1SHong Zhang 4259566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4269566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4274222ddf1SHong Zhang if (!f) { 4289566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4299566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4304222ddf1SHong Zhang } 4316718818eSStefano Zampini if (!f && C) { 4329566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4339566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4344222ddf1SHong Zhang } 4359566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4366718818eSStefano Zampini 4376718818eSStefano Zampini /* We may have found f but it did not succeed */ 4386718818eSStefano Zampini /* some matrices (i.e. MATTRANSPOSE, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */ 4396718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4409566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mtypes, "MatProductSetFromOptions_anytype_C", sizeof(mtypes))); 4419566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, mtypes, &f)); 4429566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from A? %p\n", mtypes, f)); 4436718818eSStefano Zampini if (!f) { 4449566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)B, mtypes, &f)); 4459566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from %s? %p\n", mtypes, bname, f)); 4466718818eSStefano Zampini } 4476718818eSStefano Zampini if (!f && C) { 4489566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)C, mtypes, &f)); 4499566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " querying %s from C? %p\n", mtypes, f)); 4506718818eSStefano Zampini } 4516718818eSStefano Zampini } 4529566063dSJacob Faibussowitsch if (f) PetscCall((*f)(mat)); 4534222ddf1SHong Zhang } 4544222ddf1SHong Zhang 4556718818eSStefano Zampini /* We may have found f but it did not succeed */ 4566718818eSStefano Zampini if (!mat->ops->productsymbolic) { 4576718818eSStefano Zampini /* we can still compute the product if B is of type dense */ 4586718818eSStefano Zampini if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) { 4596718818eSStefano Zampini PetscBool isdense; 4606718818eSStefano Zampini 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 4626718818eSStefano Zampini if (isdense) { 4636718818eSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_X_Dense; 4649566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " using basic looping over columns of a dense matrix\n")); 4656718818eSStefano Zampini } 4665415d71bSStefano Zampini } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Unsafe() for triple products only */ 4676718818eSStefano Zampini /* 4686718818eSStefano Zampini TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if 4698d7b260cSStefano Zampini the combination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result 4706718818eSStefano Zampini before computing the symbolic phase 4716718818eSStefano Zampini */ 4729566063dSJacob Faibussowitsch PetscCall(PetscInfo(mat, " symbolic product not supported, using MatProductSymbolic_Unsafe() implementation\n")); 4735415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_Unsafe; 4744222ddf1SHong Zhang } 4756718818eSStefano Zampini } 476*48a46eb9SPierre Jolivet if (!mat->ops->productsymbolic) PetscCall(PetscInfo(mat, " symbolic product is not supported\n")); 4774222ddf1SHong Zhang PetscFunctionReturn(0); 4784222ddf1SHong Zhang } 4794222ddf1SHong Zhang 4804222ddf1SHong Zhang /*@C 481f5368d60SBarry Smith MatProductSetFromOptions - Sets the options for the computation of a matrix product where the type, the algorithm etc are determined from the options database. 4824222ddf1SHong Zhang 4834222ddf1SHong Zhang Logically Collective on Mat 4844222ddf1SHong Zhang 4854222ddf1SHong Zhang Input Parameter: 4864222ddf1SHong Zhang . mat - the matrix 4874222ddf1SHong Zhang 4886718818eSStefano Zampini Options Database Keys: 489f5368d60SBarry Smith . -mat_product_clear - Clear intermediate data structures after `MatProductNumeric()` has been called 4904222ddf1SHong Zhang 4916718818eSStefano Zampini Level: intermediate 4926718818eSStefano Zampini 493f5368d60SBarry Smith .seealso: `MatSetFromOptions()`, `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 4944222ddf1SHong Zhang @*/ 4959371c9d4SSatish Balay PetscErrorCode MatProductSetFromOptions(Mat mat) { 4964222ddf1SHong Zhang PetscFunctionBegin; 4974222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4986718818eSStefano Zampini MatCheckProduct(mat, 1); 49928b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot call MatProductSetFromOptions with already present data"); 500d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)mat); 5019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_product_clear", "Clear intermediate data structures after MatProductNumeric() has been called", "MatProductClear", mat->product->clear, &mat->product->clear, NULL)); 5029566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-mat_freeintermediatedatastructures", "-mat_product_clear", "3.13", "Or call MatProductClear() after MatProductNumeric()")); 503d0609cedSBarry Smith PetscOptionsEnd(); 5049566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Private(mat)); 50528b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing product after setup phase"); 5066718818eSStefano Zampini PetscFunctionReturn(0); 5076718818eSStefano Zampini } 5086718818eSStefano Zampini 5096718818eSStefano Zampini /*@C 510f5368d60SBarry Smith MatProductView - View the MatProduct algorithm object within a matrix 5116718818eSStefano Zampini 5126718818eSStefano Zampini Logically Collective on Mat 5136718818eSStefano Zampini 5146718818eSStefano Zampini Input Parameter: 515f5368d60SBarry Smith . mat - the matrix obtained with `MatProductCreate()` or `MatProductCreateWithMat()` 5166718818eSStefano Zampini 5176718818eSStefano Zampini Level: intermediate 5186718818eSStefano Zampini 519db781477SPatrick Sanan .seealso: `MatView()`, `MatProductCreate()`, `MatProductCreateWithMat()` 5206718818eSStefano Zampini @*/ 5219371c9d4SSatish Balay PetscErrorCode MatProductView(Mat mat, PetscViewer viewer) { 5226718818eSStefano Zampini PetscFunctionBegin; 5236718818eSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5246718818eSStefano Zampini if (!mat->product) PetscFunctionReturn(0); 5259566063dSJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 5266718818eSStefano Zampini PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 5276718818eSStefano Zampini PetscCheckSameComm(mat, 1, viewer, 2); 5281baa6e33SBarry Smith if (mat->product->view) PetscCall((*mat->product->view)(mat, viewer)); 5294222ddf1SHong Zhang PetscFunctionReturn(0); 5304222ddf1SHong Zhang } 5314222ddf1SHong Zhang 5324222ddf1SHong Zhang /* ----------------------------------------------- */ 5336718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 5346718818eSStefano Zampini * they are dangerous and should be removed in the future */ 5359371c9d4SSatish Balay PetscErrorCode MatProductNumeric_AB(Mat mat) { 5364222ddf1SHong Zhang Mat_Product *product = mat->product; 5374222ddf1SHong Zhang Mat A = product->A, B = product->B; 5384222ddf1SHong Zhang 5394222ddf1SHong Zhang PetscFunctionBegin; 5409566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultnumeric)(A, B, mat)); 5414222ddf1SHong Zhang PetscFunctionReturn(0); 5424222ddf1SHong Zhang } 5434222ddf1SHong Zhang 5449371c9d4SSatish Balay PetscErrorCode MatProductNumeric_AtB(Mat mat) { 5454222ddf1SHong Zhang Mat_Product *product = mat->product; 5464222ddf1SHong Zhang Mat A = product->A, B = product->B; 5474222ddf1SHong Zhang 5484222ddf1SHong Zhang PetscFunctionBegin; 5499566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultnumeric)(A, B, mat)); 5504222ddf1SHong Zhang PetscFunctionReturn(0); 5514222ddf1SHong Zhang } 5524222ddf1SHong Zhang 5539371c9d4SSatish Balay PetscErrorCode MatProductNumeric_ABt(Mat mat) { 5544222ddf1SHong Zhang Mat_Product *product = mat->product; 5554222ddf1SHong Zhang Mat A = product->A, B = product->B; 5564222ddf1SHong Zhang 5574222ddf1SHong Zhang PetscFunctionBegin; 5589566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultnumeric)(A, B, mat)); 5594222ddf1SHong Zhang PetscFunctionReturn(0); 5604222ddf1SHong Zhang } 5614222ddf1SHong Zhang 5629371c9d4SSatish Balay PetscErrorCode MatProductNumeric_PtAP(Mat mat) { 5634222ddf1SHong Zhang Mat_Product *product = mat->product; 5644222ddf1SHong Zhang Mat A = product->A, B = product->B; 5654222ddf1SHong Zhang 5664222ddf1SHong Zhang PetscFunctionBegin; 5679566063dSJacob Faibussowitsch PetscCall((*mat->ops->ptapnumeric)(A, B, mat)); 5684222ddf1SHong Zhang PetscFunctionReturn(0); 5694222ddf1SHong Zhang } 5704222ddf1SHong Zhang 5719371c9d4SSatish Balay PetscErrorCode MatProductNumeric_RARt(Mat mat) { 5724222ddf1SHong Zhang Mat_Product *product = mat->product; 5734222ddf1SHong Zhang Mat A = product->A, B = product->B; 5744222ddf1SHong Zhang 5754222ddf1SHong Zhang PetscFunctionBegin; 5769566063dSJacob Faibussowitsch PetscCall((*mat->ops->rartnumeric)(A, B, mat)); 5774222ddf1SHong Zhang PetscFunctionReturn(0); 5784222ddf1SHong Zhang } 5794222ddf1SHong Zhang 5809371c9d4SSatish Balay PetscErrorCode MatProductNumeric_ABC(Mat mat) { 5814222ddf1SHong Zhang Mat_Product *product = mat->product; 5824222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 5834222ddf1SHong Zhang 5844222ddf1SHong Zhang PetscFunctionBegin; 5859566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultnumeric)(A, B, C, mat)); 5864222ddf1SHong Zhang PetscFunctionReturn(0); 5874222ddf1SHong Zhang } 5884222ddf1SHong Zhang 5896718818eSStefano Zampini /* ----------------------------------------------- */ 5906718818eSStefano Zampini 5914222ddf1SHong Zhang /*@ 5924222ddf1SHong Zhang MatProductNumeric - Implement a matrix product with numerical values. 5934222ddf1SHong Zhang 5944222ddf1SHong Zhang Collective on Mat 5954222ddf1SHong Zhang 5966718818eSStefano Zampini Input/Output Parameter: 5976718818eSStefano Zampini . mat - the matrix holding the product 5984222ddf1SHong Zhang 5994222ddf1SHong Zhang Level: intermediate 6004222ddf1SHong Zhang 601f5368d60SBarry Smith Notes: `MatProductSymbolic()` must have been called on mat before calling this function 6026718818eSStefano Zampini 603db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatSetType()`, `MatProductSymbolic()` 6044222ddf1SHong Zhang @*/ 6059371c9d4SSatish Balay PetscErrorCode MatProductNumeric(Mat mat) { 606e017e560SStefano Zampini PetscLogEvent eventtype = -1; 6072e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 6084222ddf1SHong Zhang 6094222ddf1SHong Zhang PetscFunctionBegin; 6104222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6116718818eSStefano Zampini MatCheckProduct(mat, 1); 612e017e560SStefano Zampini switch (mat->product->type) { 6139371c9d4SSatish Balay case MATPRODUCT_AB: eventtype = MAT_MatMultNumeric; break; 6149371c9d4SSatish Balay case MATPRODUCT_AtB: eventtype = MAT_TransposeMatMultNumeric; break; 6159371c9d4SSatish Balay case MATPRODUCT_ABt: eventtype = MAT_MatTransposeMultNumeric; break; 6169371c9d4SSatish Balay case MATPRODUCT_PtAP: eventtype = MAT_PtAPNumeric; break; 6179371c9d4SSatish Balay case MATPRODUCT_RARt: eventtype = MAT_RARtNumeric; break; 6189371c9d4SSatish Balay case MATPRODUCT_ABC: eventtype = MAT_MatMatMultNumeric; break; 61998921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 620e017e560SStefano Zampini } 6218d7b260cSStefano Zampini 6224222ddf1SHong Zhang if (mat->ops->productnumeric) { 6239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 624dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 6259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 6262e105a96SStefano Zampini } else missing = PETSC_TRUE; 6272e105a96SStefano Zampini 6282e105a96SStefano Zampini if (missing || !mat->product) { 6292e105a96SStefano Zampini char errstr[256]; 6302e105a96SStefano Zampini 6312e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 6329566063dSJacob 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)); 6332e105a96SStefano Zampini } else { 6349566063dSJacob 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)); 6352e105a96SStefano Zampini } 63628b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified numeric phase for product %s", errstr); 63728b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 6382e105a96SStefano Zampini } 6392e105a96SStefano Zampini 6401baa6e33SBarry Smith if (mat->product->clear) PetscCall(MatProductClear(mat)); 6419566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6424222ddf1SHong Zhang PetscFunctionReturn(0); 6434222ddf1SHong Zhang } 6444222ddf1SHong Zhang 6454222ddf1SHong Zhang /* ----------------------------------------------- */ 6466718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 6476718818eSStefano Zampini * they are dangerous and should be removed in the future */ 6489371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_AB(Mat mat) { 6494222ddf1SHong Zhang Mat_Product *product = mat->product; 6504222ddf1SHong Zhang Mat A = product->A, B = product->B; 6514222ddf1SHong Zhang 6524222ddf1SHong Zhang PetscFunctionBegin; 6539566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultsymbolic)(A, B, product->fill, mat)); 6544222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AB; 6554222ddf1SHong Zhang PetscFunctionReturn(0); 6564222ddf1SHong Zhang } 6574222ddf1SHong Zhang 6589371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_AtB(Mat mat) { 6594222ddf1SHong Zhang Mat_Product *product = mat->product; 6604222ddf1SHong Zhang Mat A = product->A, B = product->B; 6614222ddf1SHong Zhang 6624222ddf1SHong Zhang PetscFunctionBegin; 6639566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultsymbolic)(A, B, product->fill, mat)); 6644222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AtB; 6654222ddf1SHong Zhang PetscFunctionReturn(0); 6664222ddf1SHong Zhang } 6674222ddf1SHong Zhang 6689371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABt(Mat mat) { 6694222ddf1SHong Zhang Mat_Product *product = mat->product; 6704222ddf1SHong Zhang Mat A = product->A, B = product->B; 6714222ddf1SHong Zhang 6724222ddf1SHong Zhang PetscFunctionBegin; 6739566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultsymbolic)(A, B, product->fill, mat)); 6744222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABt; 6754222ddf1SHong Zhang PetscFunctionReturn(0); 6764222ddf1SHong Zhang } 6774222ddf1SHong Zhang 6789371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABC(Mat mat) { 6794222ddf1SHong Zhang Mat_Product *product = mat->product; 6804222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 6814222ddf1SHong Zhang 6824222ddf1SHong Zhang PetscFunctionBegin; 6839566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultsymbolic)(A, B, C, product->fill, mat)); 6844222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABC; 6854222ddf1SHong Zhang PetscFunctionReturn(0); 6864222ddf1SHong Zhang } 6874222ddf1SHong Zhang 6886718818eSStefano Zampini /* ----------------------------------------------- */ 6896718818eSStefano Zampini 6904222ddf1SHong Zhang /*@ 691f5368d60SBarry Smith MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical product done with 692f5368d60SBarry Smith `MatProductNumeric()` 6934222ddf1SHong Zhang 6944222ddf1SHong Zhang Collective on Mat 6954222ddf1SHong Zhang 6966718818eSStefano Zampini Input/Output Parameter: 6974222ddf1SHong Zhang . mat - the matrix to hold a product 6984222ddf1SHong Zhang 6994222ddf1SHong Zhang Level: intermediate 7004222ddf1SHong Zhang 701f5368d60SBarry Smith Notes: `MatProductSetFromOptions()` must have been called on mat before calling this function 7026718818eSStefano Zampini 703db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductSetFromOptions()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 7044222ddf1SHong Zhang @*/ 7059371c9d4SSatish Balay PetscErrorCode MatProductSymbolic(Mat mat) { 7064222ddf1SHong Zhang PetscLogEvent eventtype = -1; 7072e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 7084222ddf1SHong Zhang 7094222ddf1SHong Zhang PetscFunctionBegin; 7104222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7116718818eSStefano Zampini MatCheckProduct(mat, 1); 71228b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot run symbolic phase. Product data not empty"); 7136718818eSStefano Zampini switch (mat->product->type) { 7149371c9d4SSatish Balay case MATPRODUCT_AB: eventtype = MAT_MatMultSymbolic; break; 7159371c9d4SSatish Balay case MATPRODUCT_AtB: eventtype = MAT_TransposeMatMultSymbolic; break; 7169371c9d4SSatish Balay case MATPRODUCT_ABt: eventtype = MAT_MatTransposeMultSymbolic; break; 7179371c9d4SSatish Balay case MATPRODUCT_PtAP: eventtype = MAT_PtAPSymbolic; break; 7189371c9d4SSatish Balay case MATPRODUCT_RARt: eventtype = MAT_RARtSymbolic; break; 7199371c9d4SSatish Balay case MATPRODUCT_ABC: eventtype = MAT_MatMatMultSymbolic; break; 72098921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 7214222ddf1SHong Zhang } 7226718818eSStefano Zampini mat->ops->productnumeric = NULL; 7234222ddf1SHong Zhang if (mat->ops->productsymbolic) { 7249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 725dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 7269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 7272e105a96SStefano Zampini } else missing = PETSC_TRUE; 7282e105a96SStefano Zampini 7292e105a96SStefano Zampini if (missing || !mat->product || !mat->ops->productnumeric) { 7302e105a96SStefano Zampini char errstr[256]; 7312e105a96SStefano Zampini 7322e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 7339566063dSJacob 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)); 7342e105a96SStefano Zampini } else { 7359566063dSJacob 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)); 7362e105a96SStefano Zampini } 73728b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified symbolic phase for product %s. Call MatProductSetFromOptions() first", errstr); 73828b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 7392e105a96SStefano Zampini } 7404222ddf1SHong Zhang PetscFunctionReturn(0); 7414222ddf1SHong Zhang } 7424222ddf1SHong Zhang 7434222ddf1SHong Zhang /*@ 7444222ddf1SHong Zhang MatProductSetFill - Set an expected fill of the matrix product. 7454222ddf1SHong Zhang 7464222ddf1SHong Zhang Collective on Mat 7474222ddf1SHong Zhang 7484222ddf1SHong Zhang Input Parameters: 7494222ddf1SHong Zhang + mat - the matrix product 750f5368d60SBarry 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. 7514222ddf1SHong Zhang 7524222ddf1SHong Zhang Level: intermediate 7534222ddf1SHong Zhang 754db781477SPatrick Sanan .seealso: `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 7554222ddf1SHong Zhang @*/ 7569371c9d4SSatish Balay PetscErrorCode MatProductSetFill(Mat mat, PetscReal fill) { 7574222ddf1SHong Zhang PetscFunctionBegin; 7584222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7596718818eSStefano Zampini MatCheckProduct(mat, 1); 7606718818eSStefano Zampini if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0; 7616718818eSStefano Zampini else mat->product->fill = fill; 7624222ddf1SHong Zhang PetscFunctionReturn(0); 7634222ddf1SHong Zhang } 7644222ddf1SHong Zhang 7654222ddf1SHong Zhang /*@ 766f5368d60SBarry Smith MatProductSetAlgorithm - Requests a particular algorithm for a matrix product computation that will perform to compute the given matrix 7674222ddf1SHong Zhang 7684222ddf1SHong Zhang Collective on Mat 7694222ddf1SHong Zhang 7704222ddf1SHong Zhang Input Parameters: 7714222ddf1SHong Zhang + mat - the matrix product 772f5368d60SBarry Smith - alg - particular implementation algorithm of the matrix product, e.g., `MATPRODUCTALGORITHMDEFAULT`. 7733e662e0bSHong Zhang 7743e662e0bSHong Zhang Options Database Key: 7753e662e0bSHong Zhang . -mat_product_algorithm <algorithm> - Sets the algorithm; use -help for a list 7763e662e0bSHong Zhang of available algorithms (for instance, scalable, outerproduct, etc.) 7774222ddf1SHong Zhang 7784222ddf1SHong Zhang Level: intermediate 7794222ddf1SHong Zhang 780db781477SPatrick Sanan .seealso: `MatProductSetType()`, `MatProductSetFill()`, `MatProductCreate()`, `MatProductAlgorithm` 7814222ddf1SHong Zhang @*/ 7829371c9d4SSatish Balay PetscErrorCode MatProductSetAlgorithm(Mat mat, MatProductAlgorithm alg) { 7834222ddf1SHong Zhang PetscFunctionBegin; 7844222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7856718818eSStefano Zampini MatCheckProduct(mat, 1); 7869566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product->alg)); 7879566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(alg, &mat->product->alg)); 7884222ddf1SHong Zhang PetscFunctionReturn(0); 7894222ddf1SHong Zhang } 7904222ddf1SHong Zhang 7914222ddf1SHong Zhang /*@ 792f5368d60SBarry Smith MatProductSetType - Sets a particular matrix product type to be used to compute the given matrix 7934222ddf1SHong Zhang 7944222ddf1SHong Zhang Collective on Mat 7954222ddf1SHong Zhang 7964222ddf1SHong Zhang Input Parameters: 7974222ddf1SHong Zhang + mat - the matrix 798f5368d60SBarry Smith - productype - matrix product type, e.g., `MATPRODUCT_AB`,`MATPRODUCT_AtB`,`MATPRODUCT_ABt`,`MATPRODUCT_PtAP`,`MATPRODUCT_RARt`,`MATPRODUCT_ABC`. 7994222ddf1SHong Zhang 8004222ddf1SHong Zhang Level: intermediate 8014222ddf1SHong Zhang 802f5368d60SBarry Smith Note: 803f5368d60SBarry Smith The small t represents the traspose operation. 804f5368d60SBarry Smith 805db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductType` 8064222ddf1SHong Zhang @*/ 8079371c9d4SSatish Balay PetscErrorCode MatProductSetType(Mat mat, MatProductType productype) { 8084222ddf1SHong Zhang PetscFunctionBegin; 8094222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8106718818eSStefano Zampini MatCheckProduct(mat, 1); 8117a3c3d58SStefano Zampini PetscValidLogicalCollectiveEnum(mat, productype, 2); 8126718818eSStefano Zampini if (productype != mat->product->type) { 8131baa6e33SBarry Smith if (mat->product->destroy) PetscCall((*mat->product->destroy)(mat->product->data)); 8146718818eSStefano Zampini mat->product->destroy = NULL; 8156718818eSStefano Zampini mat->product->data = NULL; 8166718818eSStefano Zampini mat->ops->productsymbolic = NULL; 8176718818eSStefano Zampini mat->ops->productnumeric = NULL; 8186718818eSStefano Zampini } 8196718818eSStefano Zampini mat->product->type = productype; 8204222ddf1SHong Zhang PetscFunctionReturn(0); 8214222ddf1SHong Zhang } 8224222ddf1SHong Zhang 8234417c5e8SHong Zhang /*@ 8244417c5e8SHong Zhang MatProductClear - Clears matrix product internal structure. 8254417c5e8SHong Zhang 8264417c5e8SHong Zhang Collective on Mat 8274417c5e8SHong Zhang 8284417c5e8SHong Zhang Input Parameters: 8294417c5e8SHong Zhang . mat - the product matrix 8304417c5e8SHong Zhang 8314417c5e8SHong Zhang Level: intermediate 8326718818eSStefano Zampini 833f5368d60SBarry Smith Notes: 834f5368d60SBarry Smith This function should be called to remove any intermediate data used to compute the matrix to free up memory. 835f5368d60SBarry Smith 8366718818eSStefano Zampini After having called this function, MatProduct operations can no longer be used on mat 837f5368d60SBarry Smith 838f5368d60SBarry Smith .seealso: `MatProductCreate()` 8394417c5e8SHong Zhang @*/ 8409371c9d4SSatish Balay PetscErrorCode MatProductClear(Mat mat) { 8414417c5e8SHong Zhang Mat_Product *product = mat->product; 8424417c5e8SHong Zhang 8434417c5e8SHong Zhang PetscFunctionBegin; 8447a3c3d58SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8454417c5e8SHong Zhang if (product) { 8469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 8479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 8489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 8499566063dSJacob Faibussowitsch PetscCall(PetscFree(product->alg)); 8509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork)); 8511baa6e33SBarry Smith if (product->destroy) PetscCall((*product->destroy)(product->data)); 8526718818eSStefano Zampini } 8539566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product)); 8546718818eSStefano Zampini mat->ops->productsymbolic = NULL; 8556718818eSStefano Zampini mat->ops->productnumeric = NULL; 8564417c5e8SHong Zhang PetscFunctionReturn(0); 8574417c5e8SHong Zhang } 8584417c5e8SHong Zhang 8594222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */ 8609371c9d4SSatish Balay PetscErrorCode MatProductCreate_Private(Mat A, Mat B, Mat C, Mat D) { 8614222ddf1SHong Zhang Mat_Product *product = NULL; 8624222ddf1SHong Zhang 8634222ddf1SHong Zhang PetscFunctionBegin; 8646718818eSStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 86528b400f6SJacob Faibussowitsch PetscCheck(!D->product, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product already present"); 8669566063dSJacob Faibussowitsch PetscCall(PetscNewLog(D, &product)); 8674222ddf1SHong Zhang product->A = A; 8684222ddf1SHong Zhang product->B = B; 8694222ddf1SHong Zhang product->C = C; 8706718818eSStefano Zampini product->type = MATPRODUCT_UNSPECIFIED; 8714222ddf1SHong Zhang product->Dwork = NULL; 8724222ddf1SHong Zhang product->api_user = PETSC_FALSE; 8736718818eSStefano Zampini product->clear = PETSC_FALSE; 8744222ddf1SHong Zhang D->product = product; 8754417c5e8SHong Zhang 8769566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(D, MATPRODUCTALGORITHMDEFAULT)); 8779566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(D, PETSC_DEFAULT)); 8787a3c3d58SStefano Zampini 8799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 8809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 8819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 8824222ddf1SHong Zhang PetscFunctionReturn(0); 8834222ddf1SHong Zhang } 8844222ddf1SHong Zhang 8854222ddf1SHong Zhang /*@ 886f5368d60SBarry Smith MatProductCreateWithMat - Setup a given matrix as a matrix product of other matrices 8874222ddf1SHong Zhang 8884222ddf1SHong Zhang Collective on Mat 8894222ddf1SHong Zhang 8904222ddf1SHong Zhang Input Parameters: 8914222ddf1SHong Zhang + A - the first matrix 8924222ddf1SHong Zhang . B - the second matrix 8934222ddf1SHong Zhang . C - the third matrix (optional) 8944222ddf1SHong Zhang - D - the matrix which will be used as a product 8954222ddf1SHong Zhang 8964222ddf1SHong Zhang Output Parameters: 8974222ddf1SHong Zhang . D - the product matrix 8984222ddf1SHong Zhang 8996718818eSStefano Zampini Notes: 900f5368d60SBarry Smith Use `MatProductCreate()` if the matrix you wish computed (the D matrix) does not already exist 901f5368d60SBarry Smith 902f5368d60SBarry Smith See `MatProductCreate()` for details on the usage of the MatProduct routines 903f5368d60SBarry Smith 904f5368d60SBarry Smith Any product data currently attached to D will be cleared 9056718818eSStefano Zampini 9064222ddf1SHong Zhang Level: intermediate 9074222ddf1SHong Zhang 908db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductClear()` 9094222ddf1SHong Zhang @*/ 9109371c9d4SSatish Balay PetscErrorCode MatProductCreateWithMat(Mat A, Mat B, Mat C, Mat D) { 9114222ddf1SHong Zhang PetscFunctionBegin; 9124222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9134222ddf1SHong Zhang PetscValidType(A, 1); 9144222ddf1SHong Zhang MatCheckPreallocated(A, 1); 91528b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 91628b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9174222ddf1SHong Zhang 9184222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 9194222ddf1SHong Zhang PetscValidType(B, 2); 9204222ddf1SHong Zhang MatCheckPreallocated(B, 2); 92128b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 92228b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9234222ddf1SHong Zhang 9244222ddf1SHong Zhang if (C) { 9254222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 9264222ddf1SHong Zhang PetscValidType(C, 3); 9274222ddf1SHong Zhang MatCheckPreallocated(C, 3); 92828b400f6SJacob Faibussowitsch PetscCheck(C->assembled, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 92928b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9304222ddf1SHong Zhang } 9314222ddf1SHong Zhang 9324222ddf1SHong Zhang PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 9334222ddf1SHong Zhang PetscValidType(D, 4); 9344222ddf1SHong Zhang MatCheckPreallocated(D, 4); 93528b400f6SJacob Faibussowitsch PetscCheck(D->assembled, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 93628b400f6SJacob Faibussowitsch PetscCheck(!D->factortype, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9374222ddf1SHong Zhang 9384222ddf1SHong Zhang /* Create a supporting struct and attach it to D */ 9399566063dSJacob Faibussowitsch PetscCall(MatProductClear(D)); 9409566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, D)); 9414222ddf1SHong Zhang PetscFunctionReturn(0); 9424222ddf1SHong Zhang } 9434222ddf1SHong Zhang 9444222ddf1SHong Zhang /*@ 945f5368d60SBarry Smith MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations such as A*B, R*A*P 9464222ddf1SHong Zhang 9474222ddf1SHong Zhang Collective on Mat 9484222ddf1SHong Zhang 9494222ddf1SHong Zhang Input Parameters: 9504222ddf1SHong Zhang + A - the first matrix 9514222ddf1SHong Zhang . B - the second matrix 9524222ddf1SHong Zhang - C - the third matrix (optional) 9534222ddf1SHong Zhang 9544222ddf1SHong Zhang Output Parameters: 9554222ddf1SHong Zhang . D - the product matrix 9564222ddf1SHong Zhang 9574222ddf1SHong Zhang Level: intermediate 9584222ddf1SHong Zhang 959f5368d60SBarry Smith Example of Usage: 960f5368d60SBarry Smith .vb 961f5368d60SBarry Smith `MatProductCreate`(A,B,C,&D); or `MatProductCreateWithMat`(A,B,C,D) 962f5368d60SBarry Smith `MatProductSetType`(D, `MATPRODUCT_AB` or `MATPRODUCT_AtB` or `MATPRODUCT_ABt` or `MATPRODUCT_PtAP` or `MATPRODUCT_RARt` or `MATPRODUCT_ABC`) 963f5368d60SBarry Smith `MatProductSetAlgorithm`(D, alg) 964f5368d60SBarry Smith `MatProductSetFill`(D,fill) 965f5368d60SBarry Smith `MatProductSetFromOptions`(D) 966f5368d60SBarry Smith `MatProductSymbolic`(D) 967f5368d60SBarry Smith `MatProductNumeric`(D) 968f5368d60SBarry Smith Change numerical values in some of the matrices 969f5368d60SBarry Smith `MatProductNumeric`(D) 970f5368d60SBarry Smith .ve 971f5368d60SBarry Smith 972f5368d60SBarry Smith Notes: 973f5368d60SBarry Smith Use `MatProductCreateWithMat()` if the matrix you wish computed, the D matrix, already exists. 974f5368d60SBarry Smith 975f5368d60SBarry Smith The information computed during the symbolic stage can be reused for new numerical computations with the same non-zero structure 976f5368d60SBarry Smith 977f5368d60SBarry Smith Developer Notes: 978f5368d60SBarry Smith It is undocumented what happens if the nonzero structure of the input matrices changes. Is the symbolic stage automatically redone? Does it crash? 979f5368d60SBarry Smith Is there error checking for it? 980f5368d60SBarry Smith 981f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductClear()` 9824222ddf1SHong Zhang @*/ 9839371c9d4SSatish Balay PetscErrorCode MatProductCreate(Mat A, Mat B, Mat C, Mat *D) { 9844222ddf1SHong Zhang PetscFunctionBegin; 9854222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9864222ddf1SHong Zhang PetscValidType(A, 1); 9874222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 9884222ddf1SHong Zhang PetscValidType(B, 2); 98928b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix A"); 99028b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix B"); 9914222ddf1SHong Zhang 9924222ddf1SHong Zhang if (C) { 9934222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 9944222ddf1SHong Zhang PetscValidType(C, 3); 99528b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix C"); 9964222ddf1SHong Zhang } 9974222ddf1SHong Zhang 9984222ddf1SHong Zhang PetscValidPointer(D, 4); 9999566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), D)); 10009566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, *D)); 10014222ddf1SHong Zhang PetscFunctionReturn(0); 10024222ddf1SHong Zhang } 10035415d71bSStefano Zampini 10045415d71bSStefano Zampini /* 10055415d71bSStefano Zampini These are safe basic implementations of ABC, RARt and PtAP 10065415d71bSStefano Zampini that do not rely on mat->ops->matmatop function pointers. 10075415d71bSStefano Zampini They only use the MatProduct API and are currently used by 10085415d71bSStefano Zampini cuSPARSE and KOKKOS-KERNELS backends 10095415d71bSStefano Zampini */ 1010ec446438SStefano Zampini typedef struct { 10115415d71bSStefano Zampini Mat BC; 10125415d71bSStefano Zampini Mat ABC; 10135415d71bSStefano Zampini } MatMatMatPrivate; 10145415d71bSStefano Zampini 10159371c9d4SSatish Balay static PetscErrorCode MatDestroy_MatMatMatPrivate(void *data) { 10165415d71bSStefano Zampini MatMatMatPrivate *mmdata = (MatMatMatPrivate *)data; 10175415d71bSStefano Zampini 10185415d71bSStefano Zampini PetscFunctionBegin; 10199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->BC)); 10209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->ABC)); 10219566063dSJacob Faibussowitsch PetscCall(PetscFree(data)); 10225415d71bSStefano Zampini PetscFunctionReturn(0); 10235415d71bSStefano Zampini } 10245415d71bSStefano Zampini 10259371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) { 10265415d71bSStefano Zampini Mat_Product *product = mat->product; 10275415d71bSStefano Zampini MatMatMatPrivate *mmabc; 10285415d71bSStefano Zampini 10295415d71bSStefano Zampini PetscFunctionBegin; 10305415d71bSStefano Zampini MatCheckProduct(mat, 1); 103128b400f6SJacob Faibussowitsch PetscCheck(mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data empty"); 10325415d71bSStefano Zampini mmabc = (MatMatMatPrivate *)mat->product->data; 103328b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productnumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing numeric stage"); 1034ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 10359566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productnumeric)(mmabc->BC)); 10365415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the numeric phase on mat */ 10375415d71bSStefano Zampini mat->product = mmabc->ABC->product; 10385415d71bSStefano Zampini mat->ops->productnumeric = mmabc->ABC->ops->productnumeric; 1039ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 1040dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 10415415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 10425415d71bSStefano Zampini mat->product = product; 10435415d71bSStefano Zampini PetscFunctionReturn(0); 10445415d71bSStefano Zampini } 10455415d71bSStefano Zampini 10469371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) { 10475415d71bSStefano Zampini Mat_Product *product = mat->product; 10485415d71bSStefano Zampini Mat A, B, C; 10495415d71bSStefano Zampini MatProductType p1, p2; 10505415d71bSStefano Zampini MatMatMatPrivate *mmabc; 105165e4b4d4SStefano Zampini const char *prefix; 10525415d71bSStefano Zampini 10535415d71bSStefano Zampini PetscFunctionBegin; 10545415d71bSStefano Zampini MatCheckProduct(mat, 1); 105528b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data not empty"); 10569566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(mat, &prefix)); 10579566063dSJacob Faibussowitsch PetscCall(PetscNew(&mmabc)); 10585415d71bSStefano Zampini product->data = mmabc; 10595415d71bSStefano Zampini product->destroy = MatDestroy_MatMatMatPrivate; 10605415d71bSStefano Zampini switch (product->type) { 10615415d71bSStefano Zampini case MATPRODUCT_PtAP: 10625415d71bSStefano Zampini p1 = MATPRODUCT_AB; 10635415d71bSStefano Zampini p2 = MATPRODUCT_AtB; 10645415d71bSStefano Zampini A = product->B; 10655415d71bSStefano Zampini B = product->A; 10665415d71bSStefano Zampini C = product->B; 10675415d71bSStefano Zampini break; 10685415d71bSStefano Zampini case MATPRODUCT_RARt: 10695415d71bSStefano Zampini p1 = MATPRODUCT_ABt; 10705415d71bSStefano Zampini p2 = MATPRODUCT_AB; 10715415d71bSStefano Zampini A = product->B; 10725415d71bSStefano Zampini B = product->A; 10735415d71bSStefano Zampini C = product->B; 10745415d71bSStefano Zampini break; 10755415d71bSStefano Zampini case MATPRODUCT_ABC: 10765415d71bSStefano Zampini p1 = MATPRODUCT_AB; 10775415d71bSStefano Zampini p2 = MATPRODUCT_AB; 10785415d71bSStefano Zampini A = product->A; 10795415d71bSStefano Zampini B = product->B; 10805415d71bSStefano Zampini C = product->C; 10815415d71bSStefano Zampini break; 10829371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 10835415d71bSStefano Zampini } 10849566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &mmabc->BC)); 10859566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->BC, prefix)); 10869566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->BC, "P1_")); 10879566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->BC, p1)); 10889566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->BC, MATPRODUCTALGORITHMDEFAULT)); 10899566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->BC, product->fill)); 10905415d71bSStefano Zampini mmabc->BC->product->api_user = product->api_user; 10919566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->BC)); 109228b400f6SJacob 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); 1093bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 10949566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productsymbolic)(mmabc->BC)); 10955415d71bSStefano Zampini 10969566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, mmabc->BC, NULL, &mmabc->ABC)); 10979566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->ABC, prefix)); 10989566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->ABC, "P2_")); 10999566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->ABC, p2)); 11009566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->ABC, MATPRODUCTALGORITHMDEFAULT)); 11019566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->ABC, product->fill)); 11025415d71bSStefano Zampini mmabc->ABC->product->api_user = product->api_user; 11039566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->ABC)); 110428b400f6SJacob 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); 11055415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the symbolic phase on mat */ 11065415d71bSStefano Zampini mat->product = mmabc->ABC->product; 11075415d71bSStefano Zampini mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic; 1108bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 1109dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 11105415d71bSStefano Zampini mmabc->ABC->ops->productnumeric = mat->ops->productnumeric; 11115415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_ABC_Basic; 11125415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 11135415d71bSStefano Zampini mat->product = product; 11145415d71bSStefano Zampini PetscFunctionReturn(0); 11155415d71bSStefano Zampini } 1116c600787bSStefano Zampini 1117c600787bSStefano Zampini /*@ 1118c600787bSStefano Zampini MatProductGetType - Returns the type of the MatProduct. 1119c600787bSStefano Zampini 1120c600787bSStefano Zampini Not collective 1121c600787bSStefano Zampini 1122c600787bSStefano Zampini Input Parameter: 1123c600787bSStefano Zampini . mat - the matrix 1124c600787bSStefano Zampini 1125c600787bSStefano Zampini Output Parameter: 1126c600787bSStefano Zampini . mtype - the MatProduct type 1127c600787bSStefano Zampini 1128c600787bSStefano Zampini Level: intermediate 1129c600787bSStefano Zampini 1130f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductCreate()`, `MatProductType` 1131c600787bSStefano Zampini @*/ 11329371c9d4SSatish Balay PetscErrorCode MatProductGetType(Mat mat, MatProductType *mtype) { 1133c600787bSStefano Zampini PetscFunctionBegin; 1134c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1135c600787bSStefano Zampini PetscValidPointer(mtype, 2); 1136c600787bSStefano Zampini *mtype = MATPRODUCT_UNSPECIFIED; 1137c600787bSStefano Zampini if (mat->product) *mtype = mat->product->type; 1138c600787bSStefano Zampini PetscFunctionReturn(0); 1139c600787bSStefano Zampini } 1140c600787bSStefano Zampini 1141c600787bSStefano Zampini /*@ 1142c600787bSStefano Zampini MatProductGetMats - Returns the matrices associated with the MatProduct. 1143c600787bSStefano Zampini 1144c600787bSStefano Zampini Not collective 1145c600787bSStefano Zampini 1146c600787bSStefano Zampini Input Parameter: 1147c600787bSStefano Zampini . mat - the product matrix 1148c600787bSStefano Zampini 1149c600787bSStefano Zampini Output Parameters: 1150c600787bSStefano Zampini + A - the first matrix 1151c600787bSStefano Zampini . B - the second matrix 1152c600787bSStefano Zampini - C - the third matrix (optional) 1153c600787bSStefano Zampini 1154c600787bSStefano Zampini Level: intermediate 1155c600787bSStefano Zampini 1156f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 1157c600787bSStefano Zampini @*/ 11589371c9d4SSatish Balay PetscErrorCode MatProductGetMats(Mat mat, Mat *A, Mat *B, Mat *C) { 1159c600787bSStefano Zampini PetscFunctionBegin; 1160c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1161c600787bSStefano Zampini if (A) *A = mat->product ? mat->product->A : NULL; 1162c600787bSStefano Zampini if (B) *B = mat->product ? mat->product->B : NULL; 1163c600787bSStefano Zampini if (C) *C = mat->product ? mat->product->C : NULL; 1164c600787bSStefano Zampini PetscFunctionReturn(0); 1165c600787bSStefano Zampini } 1166