xref: /petsc/src/mat/impls/transpose/transm.c (revision cac4c232dc4f93991e342196e27ef7b0655dac7b)
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 
885e3dda7SBarry Smith PetscErrorCode MatMult_Transpose(Mat N,Vec x,Vec y)
985e3dda7SBarry Smith {
1085e3dda7SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
1185e3dda7SBarry Smith 
1285e3dda7SBarry Smith   PetscFunctionBegin;
139566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(Na->A,x,y));
1485e3dda7SBarry Smith   PetscFunctionReturn(0);
1585e3dda7SBarry Smith }
1685e3dda7SBarry Smith 
1785e3dda7SBarry Smith PetscErrorCode MatMultAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3)
1885e3dda7SBarry Smith {
1985e3dda7SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
2085e3dda7SBarry Smith 
2185e3dda7SBarry Smith   PetscFunctionBegin;
229566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd(Na->A,v1,v2,v3));
2385e3dda7SBarry Smith   PetscFunctionReturn(0);
2485e3dda7SBarry Smith }
2585e3dda7SBarry Smith 
2647a9afc9SBarry Smith PetscErrorCode MatMultTranspose_Transpose(Mat N,Vec x,Vec y)
2747a9afc9SBarry Smith {
2847a9afc9SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
2947a9afc9SBarry Smith 
3047a9afc9SBarry Smith   PetscFunctionBegin;
319566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A,x,y));
3247a9afc9SBarry Smith   PetscFunctionReturn(0);
3347a9afc9SBarry Smith }
3447a9afc9SBarry Smith 
3547a9afc9SBarry Smith PetscErrorCode MatMultTransposeAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3)
3647a9afc9SBarry Smith {
3747a9afc9SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
3847a9afc9SBarry Smith 
3947a9afc9SBarry Smith   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(MatMultAdd(Na->A,v1,v2,v3));
4147a9afc9SBarry Smith   PetscFunctionReturn(0);
4247a9afc9SBarry Smith }
4347a9afc9SBarry Smith 
4485e3dda7SBarry Smith PetscErrorCode MatDestroy_Transpose(Mat N)
4585e3dda7SBarry Smith {
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));
5385e3dda7SBarry Smith   PetscFunctionReturn(0);
5485e3dda7SBarry Smith }
5585e3dda7SBarry Smith 
56d0de2241SAndrew Spott PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat* m)
57d0de2241SAndrew Spott {
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");
67d0de2241SAndrew Spott   PetscFunctionReturn(0);
68d0de2241SAndrew Spott }
69d0de2241SAndrew Spott 
70d9b48344SStefano Zampini PetscErrorCode MatCreateVecs_Transpose(Mat A,Vec *r, Vec *l)
71d9b48344SStefano Zampini {
72d9b48344SStefano Zampini   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
73d9b48344SStefano Zampini 
74d9b48344SStefano Zampini   PetscFunctionBegin;
759566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(Aa->A,l,r));
76d9b48344SStefano Zampini   PetscFunctionReturn(0);
77d9b48344SStefano Zampini }
78d9b48344SStefano Zampini 
796171f1c8SPierre Jolivet PetscErrorCode MatAXPY_Transpose(Mat Y,PetscScalar a,Mat X,MatStructure str)
806171f1c8SPierre Jolivet {
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));
886171f1c8SPierre Jolivet   PetscFunctionReturn(0);
896171f1c8SPierre Jolivet }
906171f1c8SPierre Jolivet 
9152c5f739Sprj- PetscErrorCode MatHasOperation_Transpose(Mat mat,MatOperation op,PetscBool *has)
9252c5f739Sprj- {
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;
10652c5f739Sprj-   PetscFunctionReturn(0);
10752c5f739Sprj- }
10852c5f739Sprj- 
1096718818eSStefano Zampini /* used by hermitian transpose */
1106718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D)
1116718818eSStefano Zampini {
1126718818eSStefano Zampini   Mat            A,B,C,Ain,Bin,Cin;
1136718818eSStefano Zampini   PetscBool      Aistrans,Bistrans,Cistrans;
1146718818eSStefano Zampini   PetscInt       Atrans,Btrans,Ctrans;
1156718818eSStefano Zampini   MatProductType ptype;
1166718818eSStefano Zampini 
1176718818eSStefano Zampini   PetscFunctionBegin;
1186718818eSStefano Zampini   MatCheckProduct(D,1);
1196718818eSStefano Zampini   A = D->product->A;
1206718818eSStefano Zampini   B = D->product->B;
1216718818eSStefano Zampini   C = D->product->C;
1229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&Aistrans));
1239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&Bistrans));
1249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C,MATTRANSPOSEMAT,&Cistrans));
1252c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!Aistrans && !Bistrans && !Cistrans,PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"This should not happen");
1266718818eSStefano Zampini   Atrans = 0;
1276718818eSStefano Zampini   Ain    = A;
1286718818eSStefano Zampini   while (Aistrans) {
1296718818eSStefano Zampini     Atrans++;
1309566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Ain,&Ain));
1319566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)Ain,MATTRANSPOSEMAT,&Aistrans));
1326718818eSStefano Zampini   }
1336718818eSStefano Zampini   Btrans = 0;
1346718818eSStefano Zampini   Bin    = B;
1356718818eSStefano Zampini   while (Bistrans) {
1366718818eSStefano Zampini     Btrans++;
1379566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Bin,&Bin));
1389566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)Bin,MATTRANSPOSEMAT,&Bistrans));
1396718818eSStefano Zampini   }
1406718818eSStefano Zampini   Ctrans = 0;
1416718818eSStefano Zampini   Cin    = C;
1426718818eSStefano Zampini   while (Cistrans) {
1436718818eSStefano Zampini     Ctrans++;
1449566063dSJacob Faibussowitsch     PetscCall(MatTransposeGetMat(Cin,&Cin));
1459566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)Cin,MATTRANSPOSEMAT,&Cistrans));
1466718818eSStefano Zampini   }
1476718818eSStefano Zampini   Atrans = Atrans%2;
1486718818eSStefano Zampini   Btrans = Btrans%2;
1496718818eSStefano Zampini   Ctrans = Ctrans%2;
1506718818eSStefano Zampini   ptype = D->product->type; /* same product type by default */
1516718818eSStefano Zampini   if (Ain->symmetric) Atrans = 0;
1526718818eSStefano Zampini   if (Bin->symmetric) Btrans = 0;
1536718818eSStefano Zampini   if (Cin && Cin->symmetric) Ctrans = 0;
1546718818eSStefano Zampini 
1556718818eSStefano Zampini   if (Atrans || Btrans || Ctrans) {
1566718818eSStefano Zampini     ptype = MATPRODUCT_UNSPECIFIED;
1576718818eSStefano Zampini     switch (D->product->type) {
1586718818eSStefano Zampini     case MATPRODUCT_AB:
1596718818eSStefano Zampini       if (Atrans && Btrans) { /* At * Bt we do not have support for this */
1606718818eSStefano Zampini         /* TODO custom implementation ? */
1616718818eSStefano Zampini       } else if (Atrans) { /* At * B */
1626718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1636718818eSStefano Zampini       } else { /* A * Bt */
1646718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1656718818eSStefano Zampini       }
1666718818eSStefano Zampini       break;
1676718818eSStefano Zampini     case MATPRODUCT_AtB:
1686718818eSStefano Zampini       if (Atrans && Btrans) { /* A * Bt */
1696718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1706718818eSStefano Zampini       } else if (Atrans) { /* A * B */
1716718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1726718818eSStefano Zampini       } else { /* At * Bt we do not have support for this */
1736718818eSStefano Zampini         /* TODO custom implementation ? */
1746718818eSStefano Zampini       }
1756718818eSStefano Zampini       break;
1766718818eSStefano Zampini     case MATPRODUCT_ABt:
1776718818eSStefano Zampini       if (Atrans && Btrans) { /* At * B */
1786718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1796718818eSStefano Zampini       } else if (Atrans) { /* At * Bt we do not have support for this */
1806718818eSStefano Zampini         /* TODO custom implementation ? */
1816718818eSStefano Zampini       } else {  /* A * B */
1826718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1836718818eSStefano Zampini       }
1846718818eSStefano Zampini       break;
1856718818eSStefano Zampini     case MATPRODUCT_PtAP:
1866718818eSStefano Zampini       if (Atrans) { /* PtAtP */
1876718818eSStefano Zampini         /* TODO custom implementation ? */
1886718818eSStefano Zampini       } else { /* RARt */
1896718818eSStefano Zampini         ptype = MATPRODUCT_RARt;
1906718818eSStefano Zampini       }
1916718818eSStefano Zampini       break;
1926718818eSStefano Zampini     case MATPRODUCT_RARt:
1936718818eSStefano Zampini       if (Atrans) { /* RAtRt */
1946718818eSStefano Zampini         /* TODO custom implementation ? */
1956718818eSStefano Zampini       } else { /* PtAP */
1966718818eSStefano Zampini         ptype = MATPRODUCT_PtAP;
1976718818eSStefano Zampini       }
1986718818eSStefano Zampini       break;
1996718818eSStefano Zampini     case MATPRODUCT_ABC:
2006718818eSStefano Zampini       /* TODO custom implementation ? */
2016718818eSStefano Zampini       break;
20298921bdaSJacob Faibussowitsch     default: 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));
2086718818eSStefano Zampini   PetscFunctionReturn(0);
2096718818eSStefano Zampini }
2106718818eSStefano Zampini 
211a0eea678SPierre Jolivet PetscErrorCode MatGetDiagonal_Transpose(Mat A,Vec v)
212a0eea678SPierre Jolivet {
213a0eea678SPierre Jolivet   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
214a0eea678SPierre Jolivet 
215a0eea678SPierre Jolivet   PetscFunctionBegin;
2169566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(Aa->A,v));
217a0eea678SPierre Jolivet   PetscFunctionReturn(0);
218a0eea678SPierre Jolivet }
219a0eea678SPierre Jolivet 
220a0eea678SPierre Jolivet PetscErrorCode MatConvert_Transpose(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
221a0eea678SPierre Jolivet {
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   }
241a0eea678SPierre Jolivet   PetscFunctionReturn(0);
242a0eea678SPierre Jolivet }
243a0eea678SPierre Jolivet 
2448060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat_Transpose(Mat A,Mat *M)
2458060fb66Sstefano_zampini {
2468060fb66Sstefano_zampini   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
2478060fb66Sstefano_zampini 
2488060fb66Sstefano_zampini   PetscFunctionBegin;
2498060fb66Sstefano_zampini   *M = Aa->A;
2508060fb66Sstefano_zampini   PetscFunctionReturn(0);
2518060fb66Sstefano_zampini }
2528060fb66Sstefano_zampini 
2538060fb66Sstefano_zampini /*@
25406511a5cSPierre Jolivet       MatTransposeGetMat - Gets the Mat object stored inside a MATTRANSPOSEMAT
2558060fb66Sstefano_zampini 
2568060fb66Sstefano_zampini    Logically collective on Mat
2578060fb66Sstefano_zampini 
2588060fb66Sstefano_zampini    Input Parameter:
2598060fb66Sstefano_zampini .   A  - the MATTRANSPOSE matrix
2608060fb66Sstefano_zampini 
2618060fb66Sstefano_zampini    Output Parameter:
2628060fb66Sstefano_zampini .   M - the matrix object stored inside A
2638060fb66Sstefano_zampini 
2648060fb66Sstefano_zampini    Level: intermediate
2658060fb66Sstefano_zampini 
2668060fb66Sstefano_zampini .seealso: MatCreateTranspose()
2678060fb66Sstefano_zampini 
2688060fb66Sstefano_zampini @*/
2698060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat(Mat A,Mat *M)
2708060fb66Sstefano_zampini {
2718060fb66Sstefano_zampini   PetscFunctionBegin;
2728060fb66Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2738060fb66Sstefano_zampini   PetscValidType(A,1);
2748060fb66Sstefano_zampini   PetscValidPointer(M,2);
275*cac4c232SBarry Smith   PetscUseMethod(A,"MatTransposeGetMat_C",(Mat,Mat*),(A,M));
2768060fb66Sstefano_zampini   PetscFunctionReturn(0);
2778060fb66Sstefano_zampini }
278d0de2241SAndrew Spott 
27985e3dda7SBarry Smith /*@
28085e3dda7SBarry Smith       MatCreateTranspose - Creates a new matrix object that behaves like A'
28185e3dda7SBarry Smith 
28285e3dda7SBarry Smith    Collective on Mat
28385e3dda7SBarry Smith 
28485e3dda7SBarry Smith    Input Parameter:
28585e3dda7SBarry Smith .   A  - the (possibly rectangular) matrix
28685e3dda7SBarry Smith 
28785e3dda7SBarry Smith    Output Parameter:
28885e3dda7SBarry Smith .   N - the matrix that represents A'
28985e3dda7SBarry Smith 
29085e3dda7SBarry Smith    Level: intermediate
29185e3dda7SBarry Smith 
29295452b02SPatrick Sanan    Notes:
29395452b02SPatrick Sanan     The transpose A' is NOT actually formed! Rather the new matrix
29485e3dda7SBarry Smith           object performs the matrix-vector product by using the MatMultTranspose() on
29585e3dda7SBarry Smith           the original matrix
29685e3dda7SBarry Smith 
29785e3dda7SBarry Smith .seealso: MatCreateNormal(), MatMult(), MatMultTranspose(), MatCreate()
29885e3dda7SBarry Smith 
29985e3dda7SBarry Smith @*/
3007087cfbeSBarry Smith PetscErrorCode  MatCreateTranspose(Mat A,Mat *N)
30185e3dda7SBarry Smith {
30285e3dda7SBarry Smith   PetscInt       m,n;
30385e3dda7SBarry Smith   Mat_Transpose  *Na;
304487d878eSStefano Zampini   VecType        vtype;
30585e3dda7SBarry Smith 
30685e3dda7SBarry Smith   PetscFunctionBegin;
3079566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,&n));
3089566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),N));
3099566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N,n,m,PETSC_DECIDE,PETSC_DECIDE));
3109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->rmap));
3119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->cmap));
3129566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*N,MATTRANSPOSEMAT));
31385e3dda7SBarry Smith 
3149566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(*N,&Na));
31585e3dda7SBarry Smith   (*N)->data = (void*) Na;
3169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
31785e3dda7SBarry Smith   Na->A      = A;
31885e3dda7SBarry Smith 
31985e3dda7SBarry Smith   (*N)->ops->destroy               = MatDestroy_Transpose;
32085e3dda7SBarry Smith   (*N)->ops->mult                  = MatMult_Transpose;
3216d12b599SJed Brown   (*N)->ops->multadd               = MatMultAdd_Transpose;
32247a9afc9SBarry Smith   (*N)->ops->multtranspose         = MatMultTranspose_Transpose;
32347a9afc9SBarry Smith   (*N)->ops->multtransposeadd      = MatMultTransposeAdd_Transpose;
324d0de2241SAndrew Spott   (*N)->ops->duplicate             = MatDuplicate_Transpose;
325d9b48344SStefano Zampini   (*N)->ops->getvecs               = MatCreateVecs_Transpose;
3266171f1c8SPierre Jolivet   (*N)->ops->axpy                  = MatAXPY_Transpose;
32752c5f739Sprj-   (*N)->ops->hasoperation          = MatHasOperation_Transpose;
3286718818eSStefano Zampini   (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose;
329a0eea678SPierre Jolivet   (*N)->ops->getdiagonal           = MatGetDiagonal_Transpose;
330a0eea678SPierre Jolivet   (*N)->ops->convert               = MatConvert_Transpose;
33185e3dda7SBarry Smith   (*N)->assembled                  = PETSC_TRUE;
33285e3dda7SBarry Smith 
3339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatTransposeGetMat_C",MatTransposeGetMat_Transpose));
3349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_Transpose));
3359566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*N,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
3369566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A,&vtype));
3379566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N,vtype));
3382487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3399566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N,A->boundtocpu));
3402487f3f2SStefano Zampini #endif
3419566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*N));
34285e3dda7SBarry Smith   PetscFunctionReturn(0);
34385e3dda7SBarry Smith }
344