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