xref: /petsc/src/mat/impls/transpose/transm.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
185e3dda7SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
385e3dda7SBarry Smith 
485e3dda7SBarry Smith typedef struct {
585e3dda7SBarry Smith   Mat A;
685e3dda7SBarry Smith } Mat_Transpose;
785e3dda7SBarry Smith 
8d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_Transpose(Mat N, Vec x, Vec y)
9d71ae5a4SJacob Faibussowitsch {
1085e3dda7SBarry Smith   Mat_Transpose *Na = (Mat_Transpose *)N->data;
1185e3dda7SBarry Smith 
1285e3dda7SBarry Smith   PetscFunctionBegin;
139566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(Na->A, x, y));
143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1585e3dda7SBarry Smith }
1685e3dda7SBarry Smith 
17d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_Transpose(Mat N, Vec v1, Vec v2, Vec v3)
18d71ae5a4SJacob Faibussowitsch {
1985e3dda7SBarry Smith   Mat_Transpose *Na = (Mat_Transpose *)N->data;
2085e3dda7SBarry Smith 
2185e3dda7SBarry Smith   PetscFunctionBegin;
229566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd(Na->A, v1, v2, v3));
233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2485e3dda7SBarry Smith }
2585e3dda7SBarry Smith 
26d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_Transpose(Mat N, Vec x, Vec y)
27d71ae5a4SJacob Faibussowitsch {
2847a9afc9SBarry Smith   Mat_Transpose *Na = (Mat_Transpose *)N->data;
2947a9afc9SBarry Smith 
3047a9afc9SBarry Smith   PetscFunctionBegin;
319566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A, x, y));
323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3347a9afc9SBarry Smith }
3447a9afc9SBarry Smith 
35d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_Transpose(Mat N, Vec v1, Vec v2, Vec v3)
36d71ae5a4SJacob Faibussowitsch {
3747a9afc9SBarry Smith   Mat_Transpose *Na = (Mat_Transpose *)N->data;
3847a9afc9SBarry Smith 
3947a9afc9SBarry Smith   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(MatMultAdd(Na->A, v1, v2, v3));
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4247a9afc9SBarry Smith }
4347a9afc9SBarry Smith 
44d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_Transpose(Mat N)
45d71ae5a4SJacob Faibussowitsch {
4685e3dda7SBarry Smith   Mat_Transpose *Na = (Mat_Transpose *)N->data;
4785e3dda7SBarry Smith 
4885e3dda7SBarry Smith   PetscFunctionBegin;
499566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Na->A));
509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatTransposeGetMat_C", NULL));
519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatProductSetFromOptions_anytype_C", NULL));
529566063dSJacob Faibussowitsch   PetscCall(PetscFree(N->data));
533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5485e3dda7SBarry Smith }
5585e3dda7SBarry Smith 
56d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat *m)
57d71ae5a4SJacob Faibussowitsch {
58d0de2241SAndrew Spott   Mat_Transpose *Na = (Mat_Transpose *)N->data;
59d0de2241SAndrew Spott 
60d0de2241SAndrew Spott   PetscFunctionBegin;
61d0de2241SAndrew Spott   if (op == MAT_COPY_VALUES) {
629566063dSJacob Faibussowitsch     PetscCall(MatTranspose(Na->A, MAT_INITIAL_MATRIX, m));
63d0de2241SAndrew Spott   } else if (op == MAT_DO_NOT_COPY_VALUES) {
649566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(Na->A, MAT_DO_NOT_COPY_VALUES, m));
659566063dSJacob Faibussowitsch     PetscCall(MatTranspose(*m, MAT_INPLACE_MATRIX, m));
66fb41c00aSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "MAT_SHARE_NONZERO_PATTERN not supported for this matrix type");
673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68d0de2241SAndrew Spott }
69d0de2241SAndrew Spott 
70d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateVecs_Transpose(Mat A, Vec *r, Vec *l)
71d71ae5a4SJacob Faibussowitsch {
72d9b48344SStefano Zampini   Mat_Transpose *Aa = (Mat_Transpose *)A->data;
73d9b48344SStefano Zampini 
74d9b48344SStefano Zampini   PetscFunctionBegin;
759566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(Aa->A, l, r));
763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77d9b48344SStefano Zampini }
78d9b48344SStefano Zampini 
79d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_Transpose(Mat Y, PetscScalar a, Mat X, MatStructure str)
80d71ae5a4SJacob Faibussowitsch {
816171f1c8SPierre Jolivet   Mat_Transpose *Ya = (Mat_Transpose *)Y->data;
826171f1c8SPierre Jolivet   Mat_Transpose *Xa = (Mat_Transpose *)X->data;
836171f1c8SPierre Jolivet   Mat            M  = Ya->A;
846171f1c8SPierre Jolivet   Mat            N  = Xa->A;
856171f1c8SPierre Jolivet 
866171f1c8SPierre Jolivet   PetscFunctionBegin;
879566063dSJacob Faibussowitsch   PetscCall(MatAXPY(M, a, N, str));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
896171f1c8SPierre Jolivet }
906171f1c8SPierre Jolivet 
91d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHasOperation_Transpose(Mat mat, MatOperation op, PetscBool *has)
92d71ae5a4SJacob Faibussowitsch {
9352c5f739Sprj-   Mat_Transpose *X = (Mat_Transpose *)mat->data;
9452c5f739Sprj-   PetscFunctionBegin;
9552c5f739Sprj- 
9652c5f739Sprj-   *has = PETSC_FALSE;
973c6db4c4SPierre Jolivet   if (op == MATOP_MULT) {
989566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(X->A, MATOP_MULT_TRANSPOSE, has));
993c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_TRANSPOSE) {
1009566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(X->A, MATOP_MULT, has));
1013c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_ADD) {
1029566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(X->A, MATOP_MULT_TRANSPOSE_ADD, has));
1033c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_TRANSPOSE_ADD) {
1049566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(X->A, MATOP_MULT_ADD, has));
1053c6db4c4SPierre Jolivet   } else if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
1063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10752c5f739Sprj- }
10852c5f739Sprj- 
109d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D)
110d71ae5a4SJacob Faibussowitsch {
1116718818eSStefano Zampini   Mat            A, B, C, Ain, Bin, Cin;
1126718818eSStefano Zampini   PetscBool      Aistrans, Bistrans, Cistrans;
1136718818eSStefano Zampini   PetscInt       Atrans, Btrans, Ctrans;
1146718818eSStefano Zampini   MatProductType ptype;
1156718818eSStefano Zampini 
1166718818eSStefano Zampini   PetscFunctionBegin;
1176718818eSStefano Zampini   MatCheckProduct(D, 1);
1186718818eSStefano Zampini   A = D->product->A;
1196718818eSStefano Zampini   B = D->product->B;
1206718818eSStefano Zampini   C = D->product->C;
121013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATTRANSPOSEVIRTUAL, &Aistrans));
122013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATTRANSPOSEVIRTUAL, &Bistrans));
123013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATTRANSPOSEVIRTUAL, &Cistrans));
124aed4548fSBarry Smith   PetscCheck(Aistrans || Bistrans || Cistrans, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "This should not happen");
1256718818eSStefano Zampini   Atrans = 0;
1266718818eSStefano Zampini   Ain    = A;
1276718818eSStefano Zampini   while (Aistrans) {
1286718818eSStefano Zampini     Atrans++;
1299566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Ain, &Ain));
130013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Ain, MATTRANSPOSEVIRTUAL, &Aistrans));
1316718818eSStefano Zampini   }
1326718818eSStefano Zampini   Btrans = 0;
1336718818eSStefano Zampini   Bin    = B;
1346718818eSStefano Zampini   while (Bistrans) {
1356718818eSStefano Zampini     Btrans++;
1369566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Bin, &Bin));
137013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Bin, MATTRANSPOSEVIRTUAL, &Bistrans));
1386718818eSStefano Zampini   }
1396718818eSStefano Zampini   Ctrans = 0;
1406718818eSStefano Zampini   Cin    = C;
1416718818eSStefano Zampini   while (Cistrans) {
1426718818eSStefano Zampini     Ctrans++;
1439566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Cin, &Cin));
144013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Cin, MATTRANSPOSEVIRTUAL, &Cistrans));
1456718818eSStefano Zampini   }
1466718818eSStefano Zampini   Atrans = Atrans % 2;
1476718818eSStefano Zampini   Btrans = Btrans % 2;
1486718818eSStefano Zampini   Ctrans = Ctrans % 2;
1496718818eSStefano Zampini   ptype  = D->product->type; /* same product type by default */
150b94d7dedSBarry Smith   if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0;
151b94d7dedSBarry Smith   if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0;
152b94d7dedSBarry Smith   if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0;
1536718818eSStefano Zampini 
1546718818eSStefano Zampini   if (Atrans || Btrans || Ctrans) {
1556718818eSStefano Zampini     ptype = MATPRODUCT_UNSPECIFIED;
1566718818eSStefano Zampini     switch (D->product->type) {
1576718818eSStefano Zampini     case MATPRODUCT_AB:
1586718818eSStefano Zampini       if (Atrans && Btrans) { /* At * Bt we do not have support for this */
1596718818eSStefano Zampini         /* TODO custom implementation ? */
1606718818eSStefano Zampini       } else if (Atrans) { /* At * B */
1616718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1626718818eSStefano Zampini       } else { /* A * Bt */
1636718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1646718818eSStefano Zampini       }
1656718818eSStefano Zampini       break;
1666718818eSStefano Zampini     case MATPRODUCT_AtB:
1676718818eSStefano Zampini       if (Atrans && Btrans) { /* A * Bt */
1686718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1696718818eSStefano Zampini       } else if (Atrans) { /* A * B */
1706718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1716718818eSStefano Zampini       } else { /* At * Bt we do not have support for this */
1726718818eSStefano Zampini         /* TODO custom implementation ? */
1736718818eSStefano Zampini       }
1746718818eSStefano Zampini       break;
1756718818eSStefano Zampini     case MATPRODUCT_ABt:
1766718818eSStefano Zampini       if (Atrans && Btrans) { /* At * B */
1776718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1786718818eSStefano Zampini       } else if (Atrans) { /* At * Bt we do not have support for this */
1796718818eSStefano Zampini         /* TODO custom implementation ? */
1806718818eSStefano Zampini       } else { /* A * B */
1816718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1826718818eSStefano Zampini       }
1836718818eSStefano Zampini       break;
1846718818eSStefano Zampini     case MATPRODUCT_PtAP:
1856718818eSStefano Zampini       if (Atrans) { /* PtAtP */
1866718818eSStefano Zampini         /* TODO custom implementation ? */
1876718818eSStefano Zampini       } else { /* RARt */
1886718818eSStefano Zampini         ptype = MATPRODUCT_RARt;
1896718818eSStefano Zampini       }
1906718818eSStefano Zampini       break;
1916718818eSStefano Zampini     case MATPRODUCT_RARt:
1926718818eSStefano Zampini       if (Atrans) { /* RAtRt */
1936718818eSStefano Zampini         /* TODO custom implementation ? */
1946718818eSStefano Zampini       } else { /* PtAP */
1956718818eSStefano Zampini         ptype = MATPRODUCT_PtAP;
1966718818eSStefano Zampini       }
1976718818eSStefano Zampini       break;
1986718818eSStefano Zampini     case MATPRODUCT_ABC:
1996718818eSStefano Zampini       /* TODO custom implementation ? */
2006718818eSStefano Zampini       break;
201d71ae5a4SJacob Faibussowitsch     default:
202d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)D), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[D->product->type]);
2036718818eSStefano Zampini     }
2046718818eSStefano Zampini   }
2059566063dSJacob Faibussowitsch   PetscCall(MatProductReplaceMats(Ain, Bin, Cin, D));
2069566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(D, ptype));
2079566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(D));
2083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2096718818eSStefano Zampini }
2106718818eSStefano Zampini 
211d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_Transpose(Mat A, Vec v)
212d71ae5a4SJacob Faibussowitsch {
213a0eea678SPierre Jolivet   Mat_Transpose *Aa = (Mat_Transpose *)A->data;
214a0eea678SPierre Jolivet 
215a0eea678SPierre Jolivet   PetscFunctionBegin;
2169566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(Aa->A, v));
2173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218a0eea678SPierre Jolivet }
219a0eea678SPierre Jolivet 
220d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_Transpose(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
221d71ae5a4SJacob Faibussowitsch {
222a0eea678SPierre Jolivet   Mat_Transpose *Aa = (Mat_Transpose *)A->data;
2236a4403aaSStefano Zampini   PetscBool      flg;
224a0eea678SPierre Jolivet 
225a0eea678SPierre Jolivet   PetscFunctionBegin;
2269566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(Aa->A, MATOP_TRANSPOSE, &flg));
2276a4403aaSStefano Zampini   if (flg) {
2286a4403aaSStefano Zampini     Mat B;
2296a4403aaSStefano Zampini 
2309566063dSJacob Faibussowitsch     PetscCall(MatTranspose(Aa->A, MAT_INITIAL_MATRIX, &B));
231ff83db7bSPierre Jolivet     if (reuse != MAT_INPLACE_MATRIX) {
2329566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, reuse, newmat));
2339566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B));
234ff83db7bSPierre Jolivet     } else {
2359566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B));
2369566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &B));
237ff83db7bSPierre Jolivet     }
2386a4403aaSStefano Zampini   } else { /* use basic converter as fallback */
2399566063dSJacob Faibussowitsch     PetscCall(MatConvert_Basic(A, newtype, reuse, newmat));
2406a4403aaSStefano Zampini   }
2413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
242a0eea678SPierre Jolivet }
243a0eea678SPierre Jolivet 
244d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeGetMat_Transpose(Mat A, Mat *M)
245d71ae5a4SJacob Faibussowitsch {
2468060fb66Sstefano_zampini   Mat_Transpose *Aa = (Mat_Transpose *)A->data;
2478060fb66Sstefano_zampini 
2488060fb66Sstefano_zampini   PetscFunctionBegin;
2498060fb66Sstefano_zampini   *M = Aa->A;
2503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2518060fb66Sstefano_zampini }
2528060fb66Sstefano_zampini 
2538060fb66Sstefano_zampini /*@
254013e2dc7SBarry Smith       MatTransposeGetMat - Gets the `Mat` object stored inside a `MATTRANSPOSEVIRTUAL`
2558060fb66Sstefano_zampini 
25620f4b53cSBarry Smith    Logically Collective
2578060fb66Sstefano_zampini 
2588060fb66Sstefano_zampini    Input Parameter:
259013e2dc7SBarry Smith .   A  - the `MATTRANSPOSEVIRTUAL` matrix
2608060fb66Sstefano_zampini 
2618060fb66Sstefano_zampini    Output Parameter:
2622ef1f0ffSBarry Smith .   M - the matrix object stored inside `A`
2638060fb66Sstefano_zampini 
2648060fb66Sstefano_zampini    Level: intermediate
2658060fb66Sstefano_zampini 
266*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateTranspose()`
2678060fb66Sstefano_zampini @*/
268d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeGetMat(Mat A, Mat *M)
269d71ae5a4SJacob Faibussowitsch {
2708060fb66Sstefano_zampini   PetscFunctionBegin;
2718060fb66Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2728060fb66Sstefano_zampini   PetscValidType(A, 1);
2738060fb66Sstefano_zampini   PetscValidPointer(M, 2);
274cac4c232SBarry Smith   PetscUseMethod(A, "MatTransposeGetMat_C", (Mat, Mat *), (A, M));
2753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2768060fb66Sstefano_zampini }
277d0de2241SAndrew Spott 
27811a5261eSBarry Smith /*MC
279013e2dc7SBarry Smith    MATTRANSPOSEVIRTUAL - "transpose" - A matrix type that represents a virtual transpose of a matrix
28085e3dda7SBarry Smith 
28111a5261eSBarry Smith   Level: advanced
28211a5261eSBarry Smith 
283*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATHERMITIANTRANSPOSEVIRTUAL`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`,
2842ef1f0ffSBarry Smith           `MATNORMALHERMITIAN`, `MATNORMAL`
28511a5261eSBarry Smith M*/
28611a5261eSBarry Smith 
28711a5261eSBarry Smith /*@
288013e2dc7SBarry Smith       MatCreateTranspose - Creates a new matrix `MATTRANSPOSEVIRTUAL` object that behaves like A'
28911a5261eSBarry Smith 
290c3339decSBarry Smith    Collective
29185e3dda7SBarry Smith 
29285e3dda7SBarry Smith    Input Parameter:
29385e3dda7SBarry Smith .   A  - the (possibly rectangular) matrix
29485e3dda7SBarry Smith 
29585e3dda7SBarry Smith    Output Parameter:
29685e3dda7SBarry Smith .   N - the matrix that represents A'
29785e3dda7SBarry Smith 
29885e3dda7SBarry Smith    Level: intermediate
29985e3dda7SBarry Smith 
30011a5261eSBarry Smith    Note:
30195452b02SPatrick Sanan     The transpose A' is NOT actually formed! Rather the new matrix
30211a5261eSBarry Smith           object performs the matrix-vector product by using the `MatMultTranspose()` on
30385e3dda7SBarry Smith           the original matrix
30485e3dda7SBarry Smith 
305*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateNormal()`, `MatMult()`, `MatMultTranspose()`, `MatCreate()`,
3062ef1f0ffSBarry Smith           `MATNORMALHERMITIAN`
30785e3dda7SBarry Smith @*/
308d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateTranspose(Mat A, Mat *N)
309d71ae5a4SJacob Faibussowitsch {
31085e3dda7SBarry Smith   PetscInt       m, n;
31185e3dda7SBarry Smith   Mat_Transpose *Na;
312487d878eSStefano Zampini   VecType        vtype;
31385e3dda7SBarry Smith 
31485e3dda7SBarry Smith   PetscFunctionBegin;
3159566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
3169566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N));
3179566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N, n, m, PETSC_DECIDE, PETSC_DECIDE));
3189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->rmap));
3199566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->cmap));
320013e2dc7SBarry Smith   PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATTRANSPOSEVIRTUAL));
32185e3dda7SBarry Smith 
3224dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&Na));
32385e3dda7SBarry Smith   (*N)->data = (void *)Na;
3249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
32585e3dda7SBarry Smith   Na->A = A;
32685e3dda7SBarry Smith 
32785e3dda7SBarry Smith   (*N)->ops->destroy               = MatDestroy_Transpose;
32885e3dda7SBarry Smith   (*N)->ops->mult                  = MatMult_Transpose;
3296d12b599SJed Brown   (*N)->ops->multadd               = MatMultAdd_Transpose;
33047a9afc9SBarry Smith   (*N)->ops->multtranspose         = MatMultTranspose_Transpose;
33147a9afc9SBarry Smith   (*N)->ops->multtransposeadd      = MatMultTransposeAdd_Transpose;
332d0de2241SAndrew Spott   (*N)->ops->duplicate             = MatDuplicate_Transpose;
333d9b48344SStefano Zampini   (*N)->ops->getvecs               = MatCreateVecs_Transpose;
3346171f1c8SPierre Jolivet   (*N)->ops->axpy                  = MatAXPY_Transpose;
33552c5f739Sprj-   (*N)->ops->hasoperation          = MatHasOperation_Transpose;
3366718818eSStefano Zampini   (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose;
337a0eea678SPierre Jolivet   (*N)->ops->getdiagonal           = MatGetDiagonal_Transpose;
338a0eea678SPierre Jolivet   (*N)->ops->convert               = MatConvert_Transpose;
33985e3dda7SBarry Smith   (*N)->assembled                  = PETSC_TRUE;
34085e3dda7SBarry Smith 
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatTransposeGetMat_C", MatTransposeGetMat_Transpose));
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose));
3439566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs)));
3449566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A, &vtype));
3459566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N, vtype));
3462487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3479566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N, A->boundtocpu));
3482487f3f2SStefano Zampini #endif
3499566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*N));
3503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35185e3dda7SBarry Smith }
352