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 17*013e2dc7SBarry 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 */ 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 20011a5261eSBarry Smith Note: 20111a5261eSBarry Smith To reuse the symbolic phase, the 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)); 28348a46eb9SPierre Jolivet if (!iscuda) PetscCall(PetscStrcmp(vtype, VECSEQCUDA, &iscuda)); 28448a46eb9SPierre 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 */ 438*013e2dc7SBarry Smith /* some matrices (i.e. MATTRANSPOSEVIRTUAL, 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 } 47648a46eb9SPierre 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 48111a5261eSBarry 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. 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 51011a5261eSBarry Smith MatProductView - View the private `Mat_Product` algorithm object within a matrix 5116718818eSStefano Zampini 51211a5261eSBarry Smith 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 51911a5261eSBarry Smith .seealso: `MatProductSetFromOptions()`, `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 /*@ 59211a5261eSBarry Smith MatProductNumeric - Compute a matrix product with numerical values. 5934222ddf1SHong Zhang 59411a5261eSBarry Smith 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 60111a5261eSBarry Smith Note: 60211a5261eSBarry Smith `MatProductSymbolic()` must have been called on mat before calling this function 6036718818eSStefano Zampini 60411a5261eSBarry Smith .seealso: `MatProductSetAlgorithm()`, `MatProductSetType()`, `MatProductCreate()`, `MatSetType()`, `MatProductSymbolic()` 6054222ddf1SHong Zhang @*/ 6069371c9d4SSatish Balay PetscErrorCode MatProductNumeric(Mat mat) { 607e017e560SStefano Zampini PetscLogEvent eventtype = -1; 6082e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 6094222ddf1SHong Zhang 6104222ddf1SHong Zhang PetscFunctionBegin; 6114222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6126718818eSStefano Zampini MatCheckProduct(mat, 1); 613e017e560SStefano Zampini switch (mat->product->type) { 6149371c9d4SSatish Balay case MATPRODUCT_AB: eventtype = MAT_MatMultNumeric; break; 6159371c9d4SSatish Balay case MATPRODUCT_AtB: eventtype = MAT_TransposeMatMultNumeric; break; 6169371c9d4SSatish Balay case MATPRODUCT_ABt: eventtype = MAT_MatTransposeMultNumeric; break; 6179371c9d4SSatish Balay case MATPRODUCT_PtAP: eventtype = MAT_PtAPNumeric; break; 6189371c9d4SSatish Balay case MATPRODUCT_RARt: eventtype = MAT_RARtNumeric; break; 6199371c9d4SSatish Balay case MATPRODUCT_ABC: eventtype = MAT_MatMatMultNumeric; break; 62098921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 621e017e560SStefano Zampini } 6228d7b260cSStefano Zampini 6234222ddf1SHong Zhang if (mat->ops->productnumeric) { 6249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 625dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 6269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 6272e105a96SStefano Zampini } else missing = PETSC_TRUE; 6282e105a96SStefano Zampini 6292e105a96SStefano Zampini if (missing || !mat->product) { 6302e105a96SStefano Zampini char errstr[256]; 6312e105a96SStefano Zampini 6322e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 6339566063dSJacob 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)); 6342e105a96SStefano Zampini } else { 6359566063dSJacob 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)); 6362e105a96SStefano Zampini } 63728b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified numeric phase for product %s", errstr); 63828b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 6392e105a96SStefano Zampini } 6402e105a96SStefano Zampini 6411baa6e33SBarry Smith if (mat->product->clear) PetscCall(MatProductClear(mat)); 6429566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6434222ddf1SHong Zhang PetscFunctionReturn(0); 6444222ddf1SHong Zhang } 6454222ddf1SHong Zhang 6464222ddf1SHong Zhang /* ----------------------------------------------- */ 6476718818eSStefano Zampini /* these are basic implementations relying on the old function pointers 6486718818eSStefano Zampini * they are dangerous and should be removed in the future */ 6499371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_AB(Mat mat) { 6504222ddf1SHong Zhang Mat_Product *product = mat->product; 6514222ddf1SHong Zhang Mat A = product->A, B = product->B; 6524222ddf1SHong Zhang 6534222ddf1SHong Zhang PetscFunctionBegin; 6549566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmultsymbolic)(A, B, product->fill, mat)); 6554222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AB; 6564222ddf1SHong Zhang PetscFunctionReturn(0); 6574222ddf1SHong Zhang } 6584222ddf1SHong Zhang 6599371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_AtB(Mat mat) { 6604222ddf1SHong Zhang Mat_Product *product = mat->product; 6614222ddf1SHong Zhang Mat A = product->A, B = product->B; 6624222ddf1SHong Zhang 6634222ddf1SHong Zhang PetscFunctionBegin; 6649566063dSJacob Faibussowitsch PetscCall((*mat->ops->transposematmultsymbolic)(A, B, product->fill, mat)); 6654222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_AtB; 6664222ddf1SHong Zhang PetscFunctionReturn(0); 6674222ddf1SHong Zhang } 6684222ddf1SHong Zhang 6699371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABt(Mat mat) { 6704222ddf1SHong Zhang Mat_Product *product = mat->product; 6714222ddf1SHong Zhang Mat A = product->A, B = product->B; 6724222ddf1SHong Zhang 6734222ddf1SHong Zhang PetscFunctionBegin; 6749566063dSJacob Faibussowitsch PetscCall((*mat->ops->mattransposemultsymbolic)(A, B, product->fill, mat)); 6754222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABt; 6764222ddf1SHong Zhang PetscFunctionReturn(0); 6774222ddf1SHong Zhang } 6784222ddf1SHong Zhang 6799371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABC(Mat mat) { 6804222ddf1SHong Zhang Mat_Product *product = mat->product; 6814222ddf1SHong Zhang Mat A = product->A, B = product->B, C = product->C; 6824222ddf1SHong Zhang 6834222ddf1SHong Zhang PetscFunctionBegin; 6849566063dSJacob Faibussowitsch PetscCall((*mat->ops->matmatmultsymbolic)(A, B, C, product->fill, mat)); 6854222ddf1SHong Zhang mat->ops->productnumeric = MatProductNumeric_ABC; 6864222ddf1SHong Zhang PetscFunctionReturn(0); 6874222ddf1SHong Zhang } 6884222ddf1SHong Zhang 6896718818eSStefano Zampini /* ----------------------------------------------- */ 6906718818eSStefano Zampini 6914222ddf1SHong Zhang /*@ 692f5368d60SBarry Smith MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical product done with 693f5368d60SBarry Smith `MatProductNumeric()` 6944222ddf1SHong Zhang 69511a5261eSBarry Smith Collective on mat 6964222ddf1SHong Zhang 6976718818eSStefano Zampini Input/Output Parameter: 6984222ddf1SHong Zhang . mat - the matrix to hold a product 6994222ddf1SHong Zhang 7004222ddf1SHong Zhang Level: intermediate 7014222ddf1SHong Zhang 70211a5261eSBarry Smith Note: 70311a5261eSBarry Smith `MatProductSetFromOptions()` must have been called on mat before calling this function 7046718818eSStefano Zampini 705db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductCreateWithMat()`, `MatProductSetFromOptions()`, `MatProductNumeric()`, `MatProductSetType()`, `MatProductSetAlgorithm()` 7064222ddf1SHong Zhang @*/ 7079371c9d4SSatish Balay PetscErrorCode MatProductSymbolic(Mat mat) { 7084222ddf1SHong Zhang PetscLogEvent eventtype = -1; 7092e105a96SStefano Zampini PetscBool missing = PETSC_FALSE; 7104222ddf1SHong Zhang 7114222ddf1SHong Zhang PetscFunctionBegin; 7124222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7136718818eSStefano Zampini MatCheckProduct(mat, 1); 71428b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Cannot run symbolic phase. Product data not empty"); 7156718818eSStefano Zampini switch (mat->product->type) { 7169371c9d4SSatish Balay case MATPRODUCT_AB: eventtype = MAT_MatMultSymbolic; break; 7179371c9d4SSatish Balay case MATPRODUCT_AtB: eventtype = MAT_TransposeMatMultSymbolic; break; 7189371c9d4SSatish Balay case MATPRODUCT_ABt: eventtype = MAT_MatTransposeMultSymbolic; break; 7199371c9d4SSatish Balay case MATPRODUCT_PtAP: eventtype = MAT_PtAPSymbolic; break; 7209371c9d4SSatish Balay case MATPRODUCT_RARt: eventtype = MAT_RARtSymbolic; break; 7219371c9d4SSatish Balay case MATPRODUCT_ABC: eventtype = MAT_MatMatMultSymbolic; break; 72298921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[mat->product->type]); 7234222ddf1SHong Zhang } 7246718818eSStefano Zampini mat->ops->productnumeric = NULL; 7254222ddf1SHong Zhang if (mat->ops->productsymbolic) { 7269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(eventtype, mat, 0, 0, 0)); 727dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 7289566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(eventtype, mat, 0, 0, 0)); 7292e105a96SStefano Zampini } else missing = PETSC_TRUE; 7302e105a96SStefano Zampini 7312e105a96SStefano Zampini if (missing || !mat->product || !mat->ops->productnumeric) { 7322e105a96SStefano Zampini char errstr[256]; 7332e105a96SStefano Zampini 7342e105a96SStefano Zampini if (mat->product->type == MATPRODUCT_ABC) { 7359566063dSJacob 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)); 7362e105a96SStefano Zampini } else { 7379566063dSJacob 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)); 7382e105a96SStefano Zampini } 73928b400f6SJacob Faibussowitsch PetscCheck(!missing, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Unspecified symbolic phase for product %s. Call MatProductSetFromOptions() first", errstr); 74028b400f6SJacob Faibussowitsch PetscCheck(mat->product, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing struct after symbolic phase for product %s", errstr); 7412e105a96SStefano Zampini } 7424222ddf1SHong Zhang PetscFunctionReturn(0); 7434222ddf1SHong Zhang } 7444222ddf1SHong Zhang 7454222ddf1SHong Zhang /*@ 7464222ddf1SHong Zhang MatProductSetFill - Set an expected fill of the matrix product. 7474222ddf1SHong Zhang 7484222ddf1SHong Zhang Collective on Mat 7494222ddf1SHong Zhang 7504222ddf1SHong Zhang Input Parameters: 75111a5261eSBarry Smith + mat - the matrix product result matrix 752f5368d60SBarry 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. 7534222ddf1SHong Zhang 7544222ddf1SHong Zhang Level: intermediate 7554222ddf1SHong Zhang 75611a5261eSBarry Smith .seealso: `MatProductSetFromOptions()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 7574222ddf1SHong Zhang @*/ 7589371c9d4SSatish Balay PetscErrorCode MatProductSetFill(Mat mat, PetscReal fill) { 7594222ddf1SHong Zhang PetscFunctionBegin; 7604222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7616718818eSStefano Zampini MatCheckProduct(mat, 1); 7626718818eSStefano Zampini if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0; 7636718818eSStefano Zampini else mat->product->fill = fill; 7644222ddf1SHong Zhang PetscFunctionReturn(0); 7654222ddf1SHong Zhang } 7664222ddf1SHong Zhang 7674222ddf1SHong Zhang /*@ 768f5368d60SBarry Smith MatProductSetAlgorithm - Requests a particular algorithm for a matrix product computation that will perform to compute the given matrix 7694222ddf1SHong Zhang 77011a5261eSBarry Smith Collective on mat 7714222ddf1SHong Zhang 7724222ddf1SHong Zhang Input Parameters: 7734222ddf1SHong Zhang + mat - the matrix product 774f5368d60SBarry Smith - alg - particular implementation algorithm of the matrix product, e.g., `MATPRODUCTALGORITHMDEFAULT`. 7753e662e0bSHong Zhang 7763e662e0bSHong Zhang Options Database Key: 7773e662e0bSHong Zhang . -mat_product_algorithm <algorithm> - Sets the algorithm; use -help for a list 7783e662e0bSHong Zhang of available algorithms (for instance, scalable, outerproduct, etc.) 7794222ddf1SHong Zhang 7804222ddf1SHong Zhang Level: intermediate 7814222ddf1SHong Zhang 78211a5261eSBarry Smith .seealso: `MatProductSetType()`, `MatProductSetFill()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType` 7834222ddf1SHong Zhang @*/ 7849371c9d4SSatish Balay PetscErrorCode MatProductSetAlgorithm(Mat mat, MatProductAlgorithm alg) { 7854222ddf1SHong Zhang PetscFunctionBegin; 7864222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7876718818eSStefano Zampini MatCheckProduct(mat, 1); 7889566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product->alg)); 7899566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(alg, &mat->product->alg)); 7904222ddf1SHong Zhang PetscFunctionReturn(0); 7914222ddf1SHong Zhang } 7924222ddf1SHong Zhang 7934222ddf1SHong Zhang /*@ 794f5368d60SBarry Smith MatProductSetType - Sets a particular matrix product type to be used to compute the given matrix 7954222ddf1SHong Zhang 79611a5261eSBarry Smith Collective on mat 7974222ddf1SHong Zhang 7984222ddf1SHong Zhang Input Parameters: 7994222ddf1SHong Zhang + mat - the matrix 800f5368d60SBarry Smith - productype - matrix product type, e.g., `MATPRODUCT_AB`,`MATPRODUCT_AtB`,`MATPRODUCT_ABt`,`MATPRODUCT_PtAP`,`MATPRODUCT_RARt`,`MATPRODUCT_ABC`. 8014222ddf1SHong Zhang 8024222ddf1SHong Zhang Level: intermediate 8034222ddf1SHong Zhang 804f5368d60SBarry Smith Note: 80511a5261eSBarry Smith The small t represents the transpose operation. 806f5368d60SBarry Smith 80711a5261eSBarry Smith .seealso: `MatProductCreate()`, `MatProductType`, `MatProductType`, 80811a5261eSBarry Smith `MATPRODUCT_AB`, `MATPRODUCT_AtB`, `MATPRODUCT_ABt`, `MATPRODUCT_PtAP`, `MATPRODUCT_RARt`, `MATPRODUCT_ABC` 8094222ddf1SHong Zhang @*/ 8109371c9d4SSatish Balay PetscErrorCode MatProductSetType(Mat mat, MatProductType productype) { 8114222ddf1SHong Zhang PetscFunctionBegin; 8124222ddf1SHong Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8136718818eSStefano Zampini MatCheckProduct(mat, 1); 8147a3c3d58SStefano Zampini PetscValidLogicalCollectiveEnum(mat, productype, 2); 8156718818eSStefano Zampini if (productype != mat->product->type) { 8161baa6e33SBarry Smith if (mat->product->destroy) PetscCall((*mat->product->destroy)(mat->product->data)); 8176718818eSStefano Zampini mat->product->destroy = NULL; 8186718818eSStefano Zampini mat->product->data = NULL; 8196718818eSStefano Zampini mat->ops->productsymbolic = NULL; 8206718818eSStefano Zampini mat->ops->productnumeric = NULL; 8216718818eSStefano Zampini } 8226718818eSStefano Zampini mat->product->type = productype; 8234222ddf1SHong Zhang PetscFunctionReturn(0); 8244222ddf1SHong Zhang } 8254222ddf1SHong Zhang 8264417c5e8SHong Zhang /*@ 82711a5261eSBarry Smith MatProductClear - Clears matrix product internal datastructures. 8284417c5e8SHong Zhang 82911a5261eSBarry Smith Collective on mat 8304417c5e8SHong Zhang 8314417c5e8SHong Zhang Input Parameters: 8324417c5e8SHong Zhang . mat - the product matrix 8334417c5e8SHong Zhang 8344417c5e8SHong Zhang Level: intermediate 8356718818eSStefano Zampini 836f5368d60SBarry Smith Notes: 837f5368d60SBarry Smith This function should be called to remove any intermediate data used to compute the matrix to free up memory. 838f5368d60SBarry Smith 83911a5261eSBarry Smith After having called this function, matrix-matrix operations can no longer be used on mat 840f5368d60SBarry Smith 841f5368d60SBarry Smith .seealso: `MatProductCreate()` 8424417c5e8SHong Zhang @*/ 8439371c9d4SSatish Balay PetscErrorCode MatProductClear(Mat mat) { 8444417c5e8SHong Zhang Mat_Product *product = mat->product; 8454417c5e8SHong Zhang 8464417c5e8SHong Zhang PetscFunctionBegin; 8477a3c3d58SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8484417c5e8SHong Zhang if (product) { 8499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->A)); 8509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->B)); 8519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->C)); 8529566063dSJacob Faibussowitsch PetscCall(PetscFree(product->alg)); 8539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&product->Dwork)); 8541baa6e33SBarry Smith if (product->destroy) PetscCall((*product->destroy)(product->data)); 8556718818eSStefano Zampini } 8569566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->product)); 8576718818eSStefano Zampini mat->ops->productsymbolic = NULL; 8586718818eSStefano Zampini mat->ops->productnumeric = NULL; 8594417c5e8SHong Zhang PetscFunctionReturn(0); 8604417c5e8SHong Zhang } 8614417c5e8SHong Zhang 8624222ddf1SHong Zhang /* Create a supporting struct and attach it to the matrix product */ 8639371c9d4SSatish Balay PetscErrorCode MatProductCreate_Private(Mat A, Mat B, Mat C, Mat D) { 8644222ddf1SHong Zhang Mat_Product *product = NULL; 8654222ddf1SHong Zhang 8664222ddf1SHong Zhang PetscFunctionBegin; 8676718818eSStefano Zampini PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 86828b400f6SJacob Faibussowitsch PetscCheck(!D->product, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "Product already present"); 8699566063dSJacob Faibussowitsch PetscCall(PetscNewLog(D, &product)); 8704222ddf1SHong Zhang product->A = A; 8714222ddf1SHong Zhang product->B = B; 8724222ddf1SHong Zhang product->C = C; 8736718818eSStefano Zampini product->type = MATPRODUCT_UNSPECIFIED; 8744222ddf1SHong Zhang product->Dwork = NULL; 8754222ddf1SHong Zhang product->api_user = PETSC_FALSE; 8766718818eSStefano Zampini product->clear = PETSC_FALSE; 8774222ddf1SHong Zhang D->product = product; 8784417c5e8SHong Zhang 8799566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(D, MATPRODUCTALGORITHMDEFAULT)); 8809566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(D, PETSC_DEFAULT)); 8817a3c3d58SStefano Zampini 8829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 8839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 8849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C)); 8854222ddf1SHong Zhang PetscFunctionReturn(0); 8864222ddf1SHong Zhang } 8874222ddf1SHong Zhang 8884222ddf1SHong Zhang /*@ 889f5368d60SBarry Smith MatProductCreateWithMat - Setup a given matrix as a matrix product of other matrices 8904222ddf1SHong Zhang 8914222ddf1SHong Zhang Collective on Mat 8924222ddf1SHong Zhang 8934222ddf1SHong Zhang Input Parameters: 8944222ddf1SHong Zhang + A - the first matrix 8954222ddf1SHong Zhang . B - the second matrix 8964222ddf1SHong Zhang . C - the third matrix (optional) 89711a5261eSBarry Smith - D - the matrix which will be used to hold the product 8984222ddf1SHong Zhang 8994222ddf1SHong Zhang Output Parameters: 9004222ddf1SHong Zhang . D - the product matrix 9014222ddf1SHong Zhang 9026718818eSStefano Zampini Notes: 903f5368d60SBarry Smith Use `MatProductCreate()` if the matrix you wish computed (the D matrix) does not already exist 904f5368d60SBarry Smith 905f5368d60SBarry Smith See `MatProductCreate()` for details on the usage of the MatProduct routines 906f5368d60SBarry Smith 907f5368d60SBarry Smith Any product data currently attached to D will be cleared 9086718818eSStefano Zampini 9094222ddf1SHong Zhang Level: intermediate 9104222ddf1SHong Zhang 911db781477SPatrick Sanan .seealso: `MatProductCreate()`, `MatProductClear()` 9124222ddf1SHong Zhang @*/ 9139371c9d4SSatish Balay PetscErrorCode MatProductCreateWithMat(Mat A, Mat B, Mat C, Mat D) { 9144222ddf1SHong Zhang PetscFunctionBegin; 9154222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9164222ddf1SHong Zhang PetscValidType(A, 1); 9174222ddf1SHong Zhang MatCheckPreallocated(A, 1); 91828b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 91928b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9204222ddf1SHong Zhang 9214222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 9224222ddf1SHong Zhang PetscValidType(B, 2); 9234222ddf1SHong Zhang MatCheckPreallocated(B, 2); 92428b400f6SJacob Faibussowitsch PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 92528b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9264222ddf1SHong Zhang 9274222ddf1SHong Zhang if (C) { 9284222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 9294222ddf1SHong Zhang PetscValidType(C, 3); 9304222ddf1SHong Zhang MatCheckPreallocated(C, 3); 93128b400f6SJacob Faibussowitsch PetscCheck(C->assembled, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 93228b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9334222ddf1SHong Zhang } 9344222ddf1SHong Zhang 9354222ddf1SHong Zhang PetscValidHeaderSpecific(D, MAT_CLASSID, 4); 9364222ddf1SHong Zhang PetscValidType(D, 4); 9374222ddf1SHong Zhang MatCheckPreallocated(D, 4); 93828b400f6SJacob Faibussowitsch PetscCheck(D->assembled, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 93928b400f6SJacob Faibussowitsch PetscCheck(!D->factortype, PetscObjectComm((PetscObject)D), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9404222ddf1SHong Zhang 9414222ddf1SHong Zhang /* Create a supporting struct and attach it to D */ 9429566063dSJacob Faibussowitsch PetscCall(MatProductClear(D)); 9439566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, D)); 9444222ddf1SHong Zhang PetscFunctionReturn(0); 9454222ddf1SHong Zhang } 9464222ddf1SHong Zhang 9474222ddf1SHong Zhang /*@ 94811a5261eSBarry Smith MatProductCreate - create a matrix to hold the result of a matrix-matrix product operation 9494222ddf1SHong Zhang 95011a5261eSBarry Smith Collective on A 9514222ddf1SHong Zhang 9524222ddf1SHong Zhang Input Parameters: 9534222ddf1SHong Zhang + A - the first matrix 9544222ddf1SHong Zhang . B - the second matrix 9554222ddf1SHong Zhang - C - the third matrix (optional) 9564222ddf1SHong Zhang 9574222ddf1SHong Zhang Output Parameters: 9584222ddf1SHong Zhang . D - the product matrix 9594222ddf1SHong Zhang 9604222ddf1SHong Zhang Level: intermediate 9614222ddf1SHong Zhang 962f5368d60SBarry Smith Example of Usage: 963f5368d60SBarry Smith .vb 96411a5261eSBarry Smith MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D) 96511a5261eSBarry Smith MatProductSetType(D, MATPRODUCT_AB or MATPRODUCT_AtB or MATPRODUCT_ABt or MATPRODUCT_PtAP or MATPRODUCT_RARt or MATPRODUCT_ABC) 96611a5261eSBarry Smith MatProductSetAlgorithm(D, alg) 96711a5261eSBarry Smith MatProductSetFill(D,fill) 96811a5261eSBarry Smith MatProductSetFromOptions(D) 96911a5261eSBarry Smith MatProductSymbolic(D) 97011a5261eSBarry Smith MatProductNumeric(D) 971f5368d60SBarry Smith Change numerical values in some of the matrices 97211a5261eSBarry Smith MatProductNumeric(D) 973f5368d60SBarry Smith .ve 974f5368d60SBarry Smith 975f5368d60SBarry Smith Notes: 976f5368d60SBarry Smith Use `MatProductCreateWithMat()` if the matrix you wish computed, the D matrix, already exists. 977f5368d60SBarry Smith 978f5368d60SBarry Smith The information computed during the symbolic stage can be reused for new numerical computations with the same non-zero structure 979f5368d60SBarry Smith 98011a5261eSBarry Smith Developer Note: 981f5368d60SBarry Smith It is undocumented what happens if the nonzero structure of the input matrices changes. Is the symbolic stage automatically redone? Does it crash? 982f5368d60SBarry Smith Is there error checking for it? 983f5368d60SBarry Smith 984f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductClear()` 9854222ddf1SHong Zhang @*/ 9869371c9d4SSatish Balay PetscErrorCode MatProductCreate(Mat A, Mat B, Mat C, Mat *D) { 9874222ddf1SHong Zhang PetscFunctionBegin; 9884222ddf1SHong Zhang PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9894222ddf1SHong Zhang PetscValidType(A, 1); 9904222ddf1SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 9914222ddf1SHong Zhang PetscValidType(B, 2); 99228b400f6SJacob Faibussowitsch PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix A"); 99328b400f6SJacob Faibussowitsch PetscCheck(!B->factortype, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix B"); 9944222ddf1SHong Zhang 9954222ddf1SHong Zhang if (C) { 9964222ddf1SHong Zhang PetscValidHeaderSpecific(C, MAT_CLASSID, 3); 9974222ddf1SHong Zhang PetscValidType(C, 3); 99828b400f6SJacob Faibussowitsch PetscCheck(!C->factortype, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix C"); 9994222ddf1SHong Zhang } 10004222ddf1SHong Zhang 10014222ddf1SHong Zhang PetscValidPointer(D, 4); 10029566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), D)); 10039566063dSJacob Faibussowitsch PetscCall(MatProductCreate_Private(A, B, C, *D)); 10044222ddf1SHong Zhang PetscFunctionReturn(0); 10054222ddf1SHong Zhang } 10065415d71bSStefano Zampini 10075415d71bSStefano Zampini /* 10085415d71bSStefano Zampini These are safe basic implementations of ABC, RARt and PtAP 10095415d71bSStefano Zampini that do not rely on mat->ops->matmatop function pointers. 10105415d71bSStefano Zampini They only use the MatProduct API and are currently used by 10115415d71bSStefano Zampini cuSPARSE and KOKKOS-KERNELS backends 10125415d71bSStefano Zampini */ 1013ec446438SStefano Zampini typedef struct { 10145415d71bSStefano Zampini Mat BC; 10155415d71bSStefano Zampini Mat ABC; 10165415d71bSStefano Zampini } MatMatMatPrivate; 10175415d71bSStefano Zampini 10189371c9d4SSatish Balay static PetscErrorCode MatDestroy_MatMatMatPrivate(void *data) { 10195415d71bSStefano Zampini MatMatMatPrivate *mmdata = (MatMatMatPrivate *)data; 10205415d71bSStefano Zampini 10215415d71bSStefano Zampini PetscFunctionBegin; 10229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->BC)); 10239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mmdata->ABC)); 10249566063dSJacob Faibussowitsch PetscCall(PetscFree(data)); 10255415d71bSStefano Zampini PetscFunctionReturn(0); 10265415d71bSStefano Zampini } 10275415d71bSStefano Zampini 10289371c9d4SSatish Balay static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) { 10295415d71bSStefano Zampini Mat_Product *product = mat->product; 10305415d71bSStefano Zampini MatMatMatPrivate *mmabc; 10315415d71bSStefano Zampini 10325415d71bSStefano Zampini PetscFunctionBegin; 10335415d71bSStefano Zampini MatCheckProduct(mat, 1); 103428b400f6SJacob Faibussowitsch PetscCheck(mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data empty"); 10355415d71bSStefano Zampini mmabc = (MatMatMatPrivate *)mat->product->data; 103628b400f6SJacob Faibussowitsch PetscCheck(mmabc->BC->ops->productnumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Missing numeric stage"); 1037ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 10389566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productnumeric)(mmabc->BC)); 10395415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the numeric phase on mat */ 10405415d71bSStefano Zampini mat->product = mmabc->ABC->product; 10415415d71bSStefano Zampini mat->ops->productnumeric = mmabc->ABC->ops->productnumeric; 1042ec446438SStefano Zampini /* use function pointer directly to prevent logging */ 1043dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productnumeric); 10445415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 10455415d71bSStefano Zampini mat->product = product; 10465415d71bSStefano Zampini PetscFunctionReturn(0); 10475415d71bSStefano Zampini } 10485415d71bSStefano Zampini 10499371c9d4SSatish Balay PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) { 10505415d71bSStefano Zampini Mat_Product *product = mat->product; 10515415d71bSStefano Zampini Mat A, B, C; 10525415d71bSStefano Zampini MatProductType p1, p2; 10535415d71bSStefano Zampini MatMatMatPrivate *mmabc; 105465e4b4d4SStefano Zampini const char *prefix; 10555415d71bSStefano Zampini 10565415d71bSStefano Zampini PetscFunctionBegin; 10575415d71bSStefano Zampini MatCheckProduct(mat, 1); 105828b400f6SJacob Faibussowitsch PetscCheck(!mat->product->data, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Product data not empty"); 10599566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(mat, &prefix)); 10609566063dSJacob Faibussowitsch PetscCall(PetscNew(&mmabc)); 10615415d71bSStefano Zampini product->data = mmabc; 10625415d71bSStefano Zampini product->destroy = MatDestroy_MatMatMatPrivate; 10635415d71bSStefano Zampini switch (product->type) { 10645415d71bSStefano Zampini case MATPRODUCT_PtAP: 10655415d71bSStefano Zampini p1 = MATPRODUCT_AB; 10665415d71bSStefano Zampini p2 = MATPRODUCT_AtB; 10675415d71bSStefano Zampini A = product->B; 10685415d71bSStefano Zampini B = product->A; 10695415d71bSStefano Zampini C = product->B; 10705415d71bSStefano Zampini break; 10715415d71bSStefano Zampini case MATPRODUCT_RARt: 10725415d71bSStefano Zampini p1 = MATPRODUCT_ABt; 10735415d71bSStefano Zampini p2 = MATPRODUCT_AB; 10745415d71bSStefano Zampini A = product->B; 10755415d71bSStefano Zampini B = product->A; 10765415d71bSStefano Zampini C = product->B; 10775415d71bSStefano Zampini break; 10785415d71bSStefano Zampini case MATPRODUCT_ABC: 10795415d71bSStefano Zampini p1 = MATPRODUCT_AB; 10805415d71bSStefano Zampini p2 = MATPRODUCT_AB; 10815415d71bSStefano Zampini A = product->A; 10825415d71bSStefano Zampini B = product->B; 10835415d71bSStefano Zampini C = product->C; 10845415d71bSStefano Zampini break; 10859371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Not for ProductType %s", MatProductTypes[product->type]); 10865415d71bSStefano Zampini } 10879566063dSJacob Faibussowitsch PetscCall(MatProductCreate(B, C, NULL, &mmabc->BC)); 10889566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->BC, prefix)); 10899566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->BC, "P1_")); 10909566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->BC, p1)); 10919566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->BC, MATPRODUCTALGORITHMDEFAULT)); 10929566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->BC, product->fill)); 10935415d71bSStefano Zampini mmabc->BC->product->api_user = product->api_user; 10949566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->BC)); 109528b400f6SJacob 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); 1096bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 10979566063dSJacob Faibussowitsch PetscCall((*mmabc->BC->ops->productsymbolic)(mmabc->BC)); 10985415d71bSStefano Zampini 10999566063dSJacob Faibussowitsch PetscCall(MatProductCreate(A, mmabc->BC, NULL, &mmabc->ABC)); 11009566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mmabc->ABC, prefix)); 11019566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(mmabc->ABC, "P2_")); 11029566063dSJacob Faibussowitsch PetscCall(MatProductSetType(mmabc->ABC, p2)); 11039566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(mmabc->ABC, MATPRODUCTALGORITHMDEFAULT)); 11049566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(mmabc->ABC, product->fill)); 11055415d71bSStefano Zampini mmabc->ABC->product->api_user = product->api_user; 11069566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(mmabc->ABC)); 110728b400f6SJacob 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); 11085415d71bSStefano Zampini /* swap ABC product stuff with that of ABC for the symbolic phase on mat */ 11095415d71bSStefano Zampini mat->product = mmabc->ABC->product; 11105415d71bSStefano Zampini mat->ops->productsymbolic = mmabc->ABC->ops->productsymbolic; 1111bfcc3627SStefano Zampini /* use function pointer directly to prevent logging */ 1112dbbe0bcdSBarry Smith PetscUseTypeMethod(mat, productsymbolic); 11135415d71bSStefano Zampini mmabc->ABC->ops->productnumeric = mat->ops->productnumeric; 11145415d71bSStefano Zampini mat->ops->productsymbolic = MatProductSymbolic_ABC_Basic; 11155415d71bSStefano Zampini mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 11165415d71bSStefano Zampini mat->product = product; 11175415d71bSStefano Zampini PetscFunctionReturn(0); 11185415d71bSStefano Zampini } 1119c600787bSStefano Zampini 1120c600787bSStefano Zampini /*@ 112111a5261eSBarry Smith MatProductGetType - Returns the type of matrix-matrix product associated with the given matrix. 1122c600787bSStefano Zampini 1123c600787bSStefano Zampini Not collective 1124c600787bSStefano Zampini 1125c600787bSStefano Zampini Input Parameter: 1126c600787bSStefano Zampini . mat - the matrix 1127c600787bSStefano Zampini 1128c600787bSStefano Zampini Output Parameter: 112911a5261eSBarry Smith . mtype - the `MatProductType` 1130c600787bSStefano Zampini 1131c600787bSStefano Zampini Level: intermediate 1132c600787bSStefano Zampini 113311a5261eSBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductCreate()`, `MatProductType`, `MatProductAlgorithm` 1134c600787bSStefano Zampini @*/ 11359371c9d4SSatish Balay PetscErrorCode MatProductGetType(Mat mat, MatProductType *mtype) { 1136c600787bSStefano Zampini PetscFunctionBegin; 1137c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1138c600787bSStefano Zampini PetscValidPointer(mtype, 2); 1139c600787bSStefano Zampini *mtype = MATPRODUCT_UNSPECIFIED; 1140c600787bSStefano Zampini if (mat->product) *mtype = mat->product->type; 1141c600787bSStefano Zampini PetscFunctionReturn(0); 1142c600787bSStefano Zampini } 1143c600787bSStefano Zampini 1144c600787bSStefano Zampini /*@ 114511a5261eSBarry Smith MatProductGetMats - Returns the matrices associated with the matrix-matrix product this matrix can receive 1146c600787bSStefano Zampini 1147c600787bSStefano Zampini Not collective 1148c600787bSStefano Zampini 1149c600787bSStefano Zampini Input Parameter: 1150c600787bSStefano Zampini . mat - the product matrix 1151c600787bSStefano Zampini 1152c600787bSStefano Zampini Output Parameters: 1153c600787bSStefano Zampini + A - the first matrix 1154c600787bSStefano Zampini . B - the second matrix 1155c600787bSStefano Zampini - C - the third matrix (optional) 1156c600787bSStefano Zampini 1157c600787bSStefano Zampini Level: intermediate 1158c600787bSStefano Zampini 1159f5368d60SBarry Smith .seealso: `MatProductCreateWithMat()`, `MatProductSetType()`, `MatProductSetAlgorithm()`, `MatProductCreate()` 1160c600787bSStefano Zampini @*/ 11619371c9d4SSatish Balay PetscErrorCode MatProductGetMats(Mat mat, Mat *A, Mat *B, Mat *C) { 1162c600787bSStefano Zampini PetscFunctionBegin; 1163c600787bSStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1164c600787bSStefano Zampini if (A) *A = mat->product ? mat->product->A : NULL; 1165c600787bSStefano Zampini if (B) *B = mat->product ? mat->product->B : NULL; 1166c600787bSStefano Zampini if (C) *C = mat->product ? mat->product->C : NULL; 1167c600787bSStefano Zampini PetscFunctionReturn(0); 1168c600787bSStefano Zampini } 1169