1a1f56445SPierre Jolivet #include <../src/mat/impls/shell/shell.h> /*I "petscmat.h" I*/ 285e3dda7SBarry Smith 366976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_Transpose(Mat N, Vec x, Vec y) 4d71ae5a4SJacob Faibussowitsch { 5bf477422SJose E. Roman Mat A; 685e3dda7SBarry Smith 785e3dda7SBarry Smith PetscFunctionBegin; 8bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 9bf477422SJose E. Roman PetscCall(MatMultTranspose(A, x, y)); 103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1185e3dda7SBarry Smith } 1285e3dda7SBarry Smith 1366976f2fSJacob Faibussowitsch static PetscErrorCode MatMultTranspose_Transpose(Mat N, Vec x, Vec y) 14d71ae5a4SJacob Faibussowitsch { 15bf477422SJose E. Roman Mat A; 1647a9afc9SBarry Smith 1747a9afc9SBarry Smith PetscFunctionBegin; 18bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 19bf477422SJose E. Roman PetscCall(MatMult(A, x, y)); 203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2147a9afc9SBarry Smith } 2247a9afc9SBarry Smith 23*f1769f9dSJose E. Roman static PetscErrorCode MatSolve_Transpose_LU(Mat N, Vec b, Vec x) 24*f1769f9dSJose E. Roman { 25*f1769f9dSJose E. Roman Mat A; 26*f1769f9dSJose E. Roman 27*f1769f9dSJose E. Roman PetscFunctionBegin; 28*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 29*f1769f9dSJose E. Roman PetscCall(MatSolveTranspose(A, b, x)); 30*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 31*f1769f9dSJose E. Roman } 32*f1769f9dSJose E. Roman 33*f1769f9dSJose E. Roman static PetscErrorCode MatSolveAdd_Transpose_LU(Mat N, Vec b, Vec y, Vec x) 34*f1769f9dSJose E. Roman { 35*f1769f9dSJose E. Roman Mat A; 36*f1769f9dSJose E. Roman 37*f1769f9dSJose E. Roman PetscFunctionBegin; 38*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 39*f1769f9dSJose E. Roman PetscCall(MatSolveTransposeAdd(A, b, y, x)); 40*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 41*f1769f9dSJose E. Roman } 42*f1769f9dSJose E. Roman 43*f1769f9dSJose E. Roman static PetscErrorCode MatSolveTranspose_Transpose_LU(Mat N, Vec b, Vec x) 44*f1769f9dSJose E. Roman { 45*f1769f9dSJose E. Roman Mat A; 46*f1769f9dSJose E. Roman 47*f1769f9dSJose E. Roman PetscFunctionBegin; 48*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 49*f1769f9dSJose E. Roman PetscCall(MatSolve(A, b, x)); 50*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 51*f1769f9dSJose E. Roman } 52*f1769f9dSJose E. Roman 53*f1769f9dSJose E. Roman static PetscErrorCode MatSolveTransposeAdd_Transpose_LU(Mat N, Vec b, Vec y, Vec x) 54*f1769f9dSJose E. Roman { 55*f1769f9dSJose E. Roman Mat A; 56*f1769f9dSJose E. Roman 57*f1769f9dSJose E. Roman PetscFunctionBegin; 58*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 59*f1769f9dSJose E. Roman PetscCall(MatSolveAdd(A, b, y, x)); 60*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 61*f1769f9dSJose E. Roman } 62*f1769f9dSJose E. Roman 63*f1769f9dSJose E. Roman static PetscErrorCode MatMatSolve_Transpose_LU(Mat N, Mat B, Mat X) 64*f1769f9dSJose E. Roman { 65*f1769f9dSJose E. Roman Mat A; 66*f1769f9dSJose E. Roman 67*f1769f9dSJose E. Roman PetscFunctionBegin; 68*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 69*f1769f9dSJose E. Roman PetscCall(MatMatSolveTranspose(A, B, X)); 70*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 71*f1769f9dSJose E. Roman } 72*f1769f9dSJose E. Roman 73*f1769f9dSJose E. Roman static PetscErrorCode MatMatSolveTranspose_Transpose_LU(Mat N, Mat B, Mat X) 74*f1769f9dSJose E. Roman { 75*f1769f9dSJose E. Roman Mat A; 76*f1769f9dSJose E. Roman 77*f1769f9dSJose E. Roman PetscFunctionBegin; 78*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 79*f1769f9dSJose E. Roman PetscCall(MatMatSolve(A, B, X)); 80*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 81*f1769f9dSJose E. Roman } 82*f1769f9dSJose E. Roman 83*f1769f9dSJose E. Roman static PetscErrorCode MatLUFactor_Transpose(Mat N, IS row, IS col, const MatFactorInfo *minfo) 84*f1769f9dSJose E. Roman { 85*f1769f9dSJose E. Roman Mat A; 86*f1769f9dSJose E. Roman 87*f1769f9dSJose E. Roman PetscFunctionBegin; 88*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 89*f1769f9dSJose E. Roman PetscCall(MatLUFactor(A, col, row, minfo)); 90*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_LU)); 91*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_LU)); 92*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_LU)); 93*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_LU)); 94*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_LU)); 95*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_LU)); 96*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 97*f1769f9dSJose E. Roman } 98*f1769f9dSJose E. Roman 99*f1769f9dSJose E. Roman static PetscErrorCode MatSolve_Transpose_Cholesky(Mat N, Vec b, Vec x) 100*f1769f9dSJose E. Roman { 101*f1769f9dSJose E. Roman Mat A; 102*f1769f9dSJose E. Roman 103*f1769f9dSJose E. Roman PetscFunctionBegin; 104*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 105*f1769f9dSJose E. Roman PetscCall(MatSolveTranspose(A, b, x)); 106*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 107*f1769f9dSJose E. Roman } 108*f1769f9dSJose E. Roman 109*f1769f9dSJose E. Roman static PetscErrorCode MatSolveAdd_Transpose_Cholesky(Mat N, Vec b, Vec y, Vec x) 110*f1769f9dSJose E. Roman { 111*f1769f9dSJose E. Roman Mat A; 112*f1769f9dSJose E. Roman 113*f1769f9dSJose E. Roman PetscFunctionBegin; 114*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 115*f1769f9dSJose E. Roman PetscCall(MatSolveTransposeAdd(A, b, y, x)); 116*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 117*f1769f9dSJose E. Roman } 118*f1769f9dSJose E. Roman 119*f1769f9dSJose E. Roman static PetscErrorCode MatSolveTranspose_Transpose_Cholesky(Mat N, Vec b, Vec x) 120*f1769f9dSJose E. Roman { 121*f1769f9dSJose E. Roman Mat A; 122*f1769f9dSJose E. Roman 123*f1769f9dSJose E. Roman PetscFunctionBegin; 124*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 125*f1769f9dSJose E. Roman PetscCall(MatSolve(A, b, x)); 126*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 127*f1769f9dSJose E. Roman } 128*f1769f9dSJose E. Roman 129*f1769f9dSJose E. Roman static PetscErrorCode MatSolveTransposeAdd_Transpose_Cholesky(Mat N, Vec b, Vec y, Vec x) 130*f1769f9dSJose E. Roman { 131*f1769f9dSJose E. Roman Mat A; 132*f1769f9dSJose E. Roman 133*f1769f9dSJose E. Roman PetscFunctionBegin; 134*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 135*f1769f9dSJose E. Roman PetscCall(MatSolveAdd(A, b, y, x)); 136*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 137*f1769f9dSJose E. Roman } 138*f1769f9dSJose E. Roman 139*f1769f9dSJose E. Roman static PetscErrorCode MatMatSolve_Transpose_Cholesky(Mat N, Mat B, Mat X) 140*f1769f9dSJose E. Roman { 141*f1769f9dSJose E. Roman Mat A; 142*f1769f9dSJose E. Roman 143*f1769f9dSJose E. Roman PetscFunctionBegin; 144*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 145*f1769f9dSJose E. Roman PetscCall(MatMatSolveTranspose(A, B, X)); 146*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 147*f1769f9dSJose E. Roman } 148*f1769f9dSJose E. Roman 149*f1769f9dSJose E. Roman static PetscErrorCode MatMatSolveTranspose_Transpose_Cholesky(Mat N, Mat B, Mat X) 150*f1769f9dSJose E. Roman { 151*f1769f9dSJose E. Roman Mat A; 152*f1769f9dSJose E. Roman 153*f1769f9dSJose E. Roman PetscFunctionBegin; 154*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 155*f1769f9dSJose E. Roman PetscCall(MatMatSolve(A, B, X)); 156*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 157*f1769f9dSJose E. Roman } 158*f1769f9dSJose E. Roman 159*f1769f9dSJose E. Roman static PetscErrorCode MatCholeskyFactor_Transpose(Mat N, IS perm, const MatFactorInfo *minfo) 160*f1769f9dSJose E. Roman { 161*f1769f9dSJose E. Roman Mat A; 162*f1769f9dSJose E. Roman 163*f1769f9dSJose E. Roman PetscFunctionBegin; 164*f1769f9dSJose E. Roman PetscCall(MatShellGetContext(N, &A)); 165*f1769f9dSJose E. Roman PetscCall(MatCholeskyFactor(A, perm, minfo)); 166*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_Cholesky)); 167*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_Cholesky)); 168*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_Cholesky)); 169*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_Cholesky)); 170*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_Cholesky)); 171*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_Cholesky)); 172*f1769f9dSJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 173*f1769f9dSJose E. Roman } 174*f1769f9dSJose E. Roman 17566976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_Transpose(Mat N) 176d71ae5a4SJacob Faibussowitsch { 177bf477422SJose E. Roman Mat A; 17885e3dda7SBarry Smith 17985e3dda7SBarry Smith PetscFunctionBegin; 180bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 181bf477422SJose E. Roman PetscCall(MatDestroy(&A)); 1829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatTransposeGetMat_C", NULL)); 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatProductSetFromOptions_anytype_C", NULL)); 184543844c4SJose E. Roman PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatShellSetContext_C", NULL)); 1853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18685e3dda7SBarry Smith } 18785e3dda7SBarry Smith 18866976f2fSJacob Faibussowitsch static PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat *m) 189d71ae5a4SJacob Faibussowitsch { 190a1f56445SPierre Jolivet Mat A, C; 191d0de2241SAndrew Spott 192d0de2241SAndrew Spott PetscFunctionBegin; 193bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 194a1f56445SPierre Jolivet PetscCall(MatDuplicate(A, op, &C)); 195a1f56445SPierre Jolivet PetscCall(MatCreateTranspose(C, m)); 196*f1769f9dSJose E. Roman if (op == MAT_COPY_VALUES) { 197*f1769f9dSJose E. Roman PetscCall(MatCopy(N, *m, SAME_NONZERO_PATTERN)); 198*f1769f9dSJose E. Roman PetscCall(MatPropagateSymmetryOptions(A, C)); 199*f1769f9dSJose E. Roman } 200a1f56445SPierre Jolivet PetscCall(MatDestroy(&C)); 2013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 202d0de2241SAndrew Spott } 203d0de2241SAndrew Spott 20466976f2fSJacob Faibussowitsch static PetscErrorCode MatHasOperation_Transpose(Mat mat, MatOperation op, PetscBool *has) 205d71ae5a4SJacob Faibussowitsch { 206bf477422SJose E. Roman Mat A; 20752c5f739Sprj- 208bf477422SJose E. Roman PetscFunctionBegin; 209bf477422SJose E. Roman PetscCall(MatShellGetContext(mat, &A)); 21052c5f739Sprj- *has = PETSC_FALSE; 211bf477422SJose E. Roman if (op == MATOP_MULT || op == MATOP_MULT_ADD) { 212bf477422SJose E. Roman PetscCall(MatHasOperation(A, MATOP_MULT_TRANSPOSE, has)); 213bf477422SJose E. Roman } else if (op == MATOP_MULT_TRANSPOSE || op == MATOP_MULT_TRANSPOSE_ADD) { 214bf477422SJose E. Roman PetscCall(MatHasOperation(A, MATOP_MULT, has)); 2153c6db4c4SPierre Jolivet } else if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 2163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21752c5f739Sprj- } 21852c5f739Sprj- 219d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D) 220d71ae5a4SJacob Faibussowitsch { 2216718818eSStefano Zampini Mat A, B, C, Ain, Bin, Cin; 2226718818eSStefano Zampini PetscBool Aistrans, Bistrans, Cistrans; 2236718818eSStefano Zampini PetscInt Atrans, Btrans, Ctrans; 2246718818eSStefano Zampini MatProductType ptype; 2256718818eSStefano Zampini 2266718818eSStefano Zampini PetscFunctionBegin; 2276718818eSStefano Zampini MatCheckProduct(D, 1); 2286718818eSStefano Zampini A = D->product->A; 2296718818eSStefano Zampini B = D->product->B; 2306718818eSStefano Zampini C = D->product->C; 231013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)A, MATTRANSPOSEVIRTUAL, &Aistrans)); 232013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)B, MATTRANSPOSEVIRTUAL, &Bistrans)); 233013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)C, MATTRANSPOSEVIRTUAL, &Cistrans)); 234aed4548fSBarry Smith PetscCheck(Aistrans || Bistrans || Cistrans, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "This should not happen"); 2356718818eSStefano Zampini Atrans = 0; 2366718818eSStefano Zampini Ain = A; 2376718818eSStefano Zampini while (Aistrans) { 2386718818eSStefano Zampini Atrans++; 2399566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Ain, &Ain)); 240013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Ain, MATTRANSPOSEVIRTUAL, &Aistrans)); 2416718818eSStefano Zampini } 2426718818eSStefano Zampini Btrans = 0; 2436718818eSStefano Zampini Bin = B; 2446718818eSStefano Zampini while (Bistrans) { 2456718818eSStefano Zampini Btrans++; 2469566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Bin, &Bin)); 247013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Bin, MATTRANSPOSEVIRTUAL, &Bistrans)); 2486718818eSStefano Zampini } 2496718818eSStefano Zampini Ctrans = 0; 2506718818eSStefano Zampini Cin = C; 2516718818eSStefano Zampini while (Cistrans) { 2526718818eSStefano Zampini Ctrans++; 2539566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Cin, &Cin)); 254013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Cin, MATTRANSPOSEVIRTUAL, &Cistrans)); 2556718818eSStefano Zampini } 2566718818eSStefano Zampini Atrans = Atrans % 2; 2576718818eSStefano Zampini Btrans = Btrans % 2; 2586718818eSStefano Zampini Ctrans = Ctrans % 2; 2596718818eSStefano Zampini ptype = D->product->type; /* same product type by default */ 260b94d7dedSBarry Smith if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0; 261b94d7dedSBarry Smith if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0; 262b94d7dedSBarry Smith if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0; 2636718818eSStefano Zampini 2646718818eSStefano Zampini if (Atrans || Btrans || Ctrans) { 2656718818eSStefano Zampini ptype = MATPRODUCT_UNSPECIFIED; 2666718818eSStefano Zampini switch (D->product->type) { 2676718818eSStefano Zampini case MATPRODUCT_AB: 2686718818eSStefano Zampini if (Atrans && Btrans) { /* At * Bt we do not have support for this */ 2696718818eSStefano Zampini /* TODO custom implementation ? */ 2706718818eSStefano Zampini } else if (Atrans) { /* At * B */ 2716718818eSStefano Zampini ptype = MATPRODUCT_AtB; 2726718818eSStefano Zampini } else { /* A * Bt */ 2736718818eSStefano Zampini ptype = MATPRODUCT_ABt; 2746718818eSStefano Zampini } 2756718818eSStefano Zampini break; 2766718818eSStefano Zampini case MATPRODUCT_AtB: 2776718818eSStefano Zampini if (Atrans && Btrans) { /* A * Bt */ 2786718818eSStefano Zampini ptype = MATPRODUCT_ABt; 2796718818eSStefano Zampini } else if (Atrans) { /* A * B */ 2806718818eSStefano Zampini ptype = MATPRODUCT_AB; 2816718818eSStefano Zampini } else { /* At * Bt we do not have support for this */ 2826718818eSStefano Zampini /* TODO custom implementation ? */ 2836718818eSStefano Zampini } 2846718818eSStefano Zampini break; 2856718818eSStefano Zampini case MATPRODUCT_ABt: 2866718818eSStefano Zampini if (Atrans && Btrans) { /* At * B */ 2876718818eSStefano Zampini ptype = MATPRODUCT_AtB; 2886718818eSStefano Zampini } else if (Atrans) { /* At * Bt we do not have support for this */ 2896718818eSStefano Zampini /* TODO custom implementation ? */ 2906718818eSStefano Zampini } else { /* A * B */ 2916718818eSStefano Zampini ptype = MATPRODUCT_AB; 2926718818eSStefano Zampini } 2936718818eSStefano Zampini break; 2946718818eSStefano Zampini case MATPRODUCT_PtAP: 2956718818eSStefano Zampini if (Atrans) { /* PtAtP */ 2966718818eSStefano Zampini /* TODO custom implementation ? */ 2976718818eSStefano Zampini } else { /* RARt */ 2986718818eSStefano Zampini ptype = MATPRODUCT_RARt; 2996718818eSStefano Zampini } 3006718818eSStefano Zampini break; 3016718818eSStefano Zampini case MATPRODUCT_RARt: 3026718818eSStefano Zampini if (Atrans) { /* RAtRt */ 3036718818eSStefano Zampini /* TODO custom implementation ? */ 3046718818eSStefano Zampini } else { /* PtAP */ 3056718818eSStefano Zampini ptype = MATPRODUCT_PtAP; 3066718818eSStefano Zampini } 3076718818eSStefano Zampini break; 3086718818eSStefano Zampini case MATPRODUCT_ABC: 3096718818eSStefano Zampini /* TODO custom implementation ? */ 3106718818eSStefano Zampini break; 311d71ae5a4SJacob Faibussowitsch default: 312d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)D), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[D->product->type]); 3136718818eSStefano Zampini } 3146718818eSStefano Zampini } 3159566063dSJacob Faibussowitsch PetscCall(MatProductReplaceMats(Ain, Bin, Cin, D)); 3169566063dSJacob Faibussowitsch PetscCall(MatProductSetType(D, ptype)); 3179566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(D)); 3183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3196718818eSStefano Zampini } 3206718818eSStefano Zampini 321bf477422SJose E. Roman static PetscErrorCode MatGetDiagonal_Transpose(Mat N, Vec v) 322d71ae5a4SJacob Faibussowitsch { 323bf477422SJose E. Roman Mat A; 324a0eea678SPierre Jolivet 325a0eea678SPierre Jolivet PetscFunctionBegin; 326bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 327bf477422SJose E. Roman PetscCall(MatGetDiagonal(A, v)); 3283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 329a0eea678SPierre Jolivet } 330a0eea678SPierre Jolivet 331a1f56445SPierre Jolivet static PetscErrorCode MatCopy_Transpose(Mat A, Mat B, MatStructure str) 332a1f56445SPierre Jolivet { 333a1f56445SPierre Jolivet Mat a, b; 334a1f56445SPierre Jolivet 335a1f56445SPierre Jolivet PetscFunctionBegin; 336a1f56445SPierre Jolivet PetscCall(MatShellGetContext(A, &a)); 337a1f56445SPierre Jolivet PetscCall(MatShellGetContext(B, &b)); 338a1f56445SPierre Jolivet PetscCall(MatCopy(a, b, str)); 339a1f56445SPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 340a1f56445SPierre Jolivet } 341a1f56445SPierre Jolivet 342bf477422SJose E. Roman static PetscErrorCode MatConvert_Transpose(Mat N, MatType newtype, MatReuse reuse, Mat *newmat) 343d71ae5a4SJacob Faibussowitsch { 344bf477422SJose E. Roman Mat A; 345b22c5e46SPierre Jolivet PetscScalar vscale = 1.0, vshift = 0.0; 3466a4403aaSStefano Zampini PetscBool flg; 347a0eea678SPierre Jolivet 348a0eea678SPierre Jolivet PetscFunctionBegin; 349bf477422SJose E. Roman PetscCall(MatShellGetContext(N, &A)); 350bf477422SJose E. Roman PetscCall(MatHasOperation(A, MATOP_TRANSPOSE, &flg)); 351b22c5e46SPierre Jolivet if (flg || N->ops->getrow) { /* if this condition is false, MatConvert_Shell() will be called in MatConvert_Basic(), so the following checks are not needed */ 352b22c5e46SPierre Jolivet PetscCheck(!((Mat_Shell *)N->data)->zrows && !((Mat_Shell *)N->data)->zcols, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatZeroRows() or MatZeroRowsColumns() has been called on the input Mat"); 353b22c5e46SPierre Jolivet PetscCheck(!((Mat_Shell *)N->data)->axpy, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatAXPY() has been called on the input Mat"); 354b22c5e46SPierre Jolivet PetscCheck(!((Mat_Shell *)N->data)->left && !((Mat_Shell *)N->data)->right, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatDiagonalScale() has been called on the input Mat"); 355b22c5e46SPierre Jolivet PetscCheck(!((Mat_Shell *)N->data)->dshift, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatDiagonalSet() has been called on the input Mat"); 356b22c5e46SPierre Jolivet vscale = ((Mat_Shell *)N->data)->vscale; 357b22c5e46SPierre Jolivet vshift = ((Mat_Shell *)N->data)->vshift; 358b22c5e46SPierre Jolivet } 3596a4403aaSStefano Zampini if (flg) { 3606a4403aaSStefano Zampini Mat B; 3616a4403aaSStefano Zampini 362bf477422SJose E. Roman PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B)); 363ff83db7bSPierre Jolivet if (reuse != MAT_INPLACE_MATRIX) { 3649566063dSJacob Faibussowitsch PetscCall(MatConvert(B, newtype, reuse, newmat)); 3659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 366ff83db7bSPierre Jolivet } else { 3679566063dSJacob Faibussowitsch PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B)); 368bf477422SJose E. Roman PetscCall(MatHeaderReplace(N, &B)); 369ff83db7bSPierre Jolivet } 3706a4403aaSStefano Zampini } else { /* use basic converter as fallback */ 371b22c5e46SPierre Jolivet flg = (PetscBool)(N->ops->getrow != NULL); 372bf477422SJose E. Roman PetscCall(MatConvert_Basic(N, newtype, reuse, newmat)); 3736a4403aaSStefano Zampini } 374b22c5e46SPierre Jolivet if (flg) { 375b22c5e46SPierre Jolivet PetscCall(MatScale(*newmat, vscale)); 376b22c5e46SPierre Jolivet PetscCall(MatShift(*newmat, vshift)); 377b22c5e46SPierre Jolivet } 3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 379a0eea678SPierre Jolivet } 380a0eea678SPierre Jolivet 381bf477422SJose E. Roman static PetscErrorCode MatTransposeGetMat_Transpose(Mat N, Mat *M) 382d71ae5a4SJacob Faibussowitsch { 3838060fb66Sstefano_zampini PetscFunctionBegin; 384bf477422SJose E. Roman PetscCall(MatShellGetContext(N, M)); 3853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3868060fb66Sstefano_zampini } 3878060fb66Sstefano_zampini 3888060fb66Sstefano_zampini /*@ 389013e2dc7SBarry Smith MatTransposeGetMat - Gets the `Mat` object stored inside a `MATTRANSPOSEVIRTUAL` 3908060fb66Sstefano_zampini 39120f4b53cSBarry Smith Logically Collective 3928060fb66Sstefano_zampini 3938060fb66Sstefano_zampini Input Parameter: 394013e2dc7SBarry Smith . A - the `MATTRANSPOSEVIRTUAL` matrix 3958060fb66Sstefano_zampini 3968060fb66Sstefano_zampini Output Parameter: 3972ef1f0ffSBarry Smith . M - the matrix object stored inside `A` 3988060fb66Sstefano_zampini 3998060fb66Sstefano_zampini Level: intermediate 4008060fb66Sstefano_zampini 4011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateTranspose()` 4028060fb66Sstefano_zampini @*/ 403d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeGetMat(Mat A, Mat *M) 404d71ae5a4SJacob Faibussowitsch { 4058060fb66Sstefano_zampini PetscFunctionBegin; 4068060fb66Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4078060fb66Sstefano_zampini PetscValidType(A, 1); 4084f572ea9SToby Isaac PetscAssertPointer(M, 2); 409cac4c232SBarry Smith PetscUseMethod(A, "MatTransposeGetMat_C", (Mat, Mat *), (A, M)); 4103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4118060fb66Sstefano_zampini } 412d0de2241SAndrew Spott 41311a5261eSBarry Smith /*MC 414013e2dc7SBarry Smith MATTRANSPOSEVIRTUAL - "transpose" - A matrix type that represents a virtual transpose of a matrix 41585e3dda7SBarry Smith 41611a5261eSBarry Smith Level: advanced 41711a5261eSBarry Smith 418a1f56445SPierre Jolivet Developer Notes: 419543844c4SJose E. Roman This is implemented on top of `MATSHELL` to get support for scaling and shifting without requiring duplicate code 420543844c4SJose E. Roman 421543844c4SJose E. Roman Users can not call `MatShellSetOperation()` operations on this class, there is some error checking for that incorrect usage 422543844c4SJose E. Roman 4231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATHERMITIANTRANSPOSEVIRTUAL`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`, 4242ef1f0ffSBarry Smith `MATNORMALHERMITIAN`, `MATNORMAL` 42511a5261eSBarry Smith M*/ 42611a5261eSBarry Smith 42711a5261eSBarry Smith /*@ 428013e2dc7SBarry Smith MatCreateTranspose - Creates a new matrix `MATTRANSPOSEVIRTUAL` object that behaves like A' 42911a5261eSBarry Smith 430c3339decSBarry Smith Collective 43185e3dda7SBarry Smith 43285e3dda7SBarry Smith Input Parameter: 43385e3dda7SBarry Smith . A - the (possibly rectangular) matrix 43485e3dda7SBarry Smith 43585e3dda7SBarry Smith Output Parameter: 43685e3dda7SBarry Smith . N - the matrix that represents A' 43785e3dda7SBarry Smith 43885e3dda7SBarry Smith Level: intermediate 43985e3dda7SBarry Smith 44011a5261eSBarry Smith Note: 44195452b02SPatrick Sanan The transpose A' is NOT actually formed! Rather the new matrix 44211a5261eSBarry Smith object performs the matrix-vector product by using the `MatMultTranspose()` on 44385e3dda7SBarry Smith the original matrix 44485e3dda7SBarry Smith 4451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateNormal()`, `MatMult()`, `MatMultTranspose()`, `MatCreate()`, 4462ef1f0ffSBarry Smith `MATNORMALHERMITIAN` 44785e3dda7SBarry Smith @*/ 448d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateTranspose(Mat A, Mat *N) 449d71ae5a4SJacob Faibussowitsch { 450487d878eSStefano Zampini VecType vtype; 45185e3dda7SBarry Smith 45285e3dda7SBarry Smith PetscFunctionBegin; 4539566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N)); 45487971105SStefano Zampini PetscCall(PetscLayoutReference(A->rmap, &((*N)->cmap))); 45587971105SStefano Zampini PetscCall(PetscLayoutReference(A->cmap, &((*N)->rmap))); 456bf477422SJose E. Roman PetscCall(MatSetType(*N, MATSHELL)); 457bf477422SJose E. Roman PetscCall(MatShellSetContext(*N, A)); 4589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 45985e3dda7SBarry Smith 4609566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs))); 4619566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A, &vtype)); 4629566063dSJacob Faibussowitsch PetscCall(MatSetVecType(*N, vtype)); 4632487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 4649566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*N, A->boundtocpu)); 4652487f3f2SStefano Zampini #endif 4669566063dSJacob Faibussowitsch PetscCall(MatSetUp(*N)); 467bf477422SJose E. Roman 468bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_DESTROY, (void (*)(void))MatDestroy_Transpose)); 469bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_MULT, (void (*)(void))MatMult_Transpose)); 470bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Transpose)); 471*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_LUFACTOR, (void (*)(void))MatLUFactor_Transpose)); 472*f1769f9dSJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_CHOLESKYFACTOR, (void (*)(void))MatCholeskyFactor_Transpose)); 473bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_DUPLICATE, (void (*)(void))MatDuplicate_Transpose)); 474bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_HAS_OPERATION, (void (*)(void))MatHasOperation_Transpose)); 475bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Transpose)); 476a1f56445SPierre Jolivet PetscCall(MatShellSetOperation(*N, MATOP_COPY, (void (*)(void))MatCopy_Transpose)); 477bf477422SJose E. Roman PetscCall(MatShellSetOperation(*N, MATOP_CONVERT, (void (*)(void))MatConvert_Transpose)); 478bf477422SJose E. Roman 479543844c4SJose E. Roman PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatTransposeGetMat_C", MatTransposeGetMat_Transpose)); 480543844c4SJose E. Roman PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose)); 481a1f56445SPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetContext_C", MatShellSetContext_Immutable)); 482a1f56445SPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetContextDestroy_C", MatShellSetContextDestroy_Immutable)); 483a1f56445SPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetManageScalingShifts_C", MatShellSetManageScalingShifts_Immutable)); 484bf477422SJose E. Roman PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATTRANSPOSEVIRTUAL)); 4853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48685e3dda7SBarry Smith } 487