xref: /petsc/src/mat/impls/transpose/transm.c (revision ff83db7b6187e6e76e718e6806a94af28628dfd2)
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   PetscErrorCode ierr;
1285e3dda7SBarry Smith 
1385e3dda7SBarry Smith   PetscFunctionBegin;
1485e3dda7SBarry Smith   ierr = MatMultTranspose(Na->A,x,y);CHKERRQ(ierr);
1585e3dda7SBarry Smith   PetscFunctionReturn(0);
1685e3dda7SBarry Smith }
1785e3dda7SBarry Smith 
1885e3dda7SBarry Smith PetscErrorCode MatMultAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3)
1985e3dda7SBarry Smith {
2085e3dda7SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
2185e3dda7SBarry Smith   PetscErrorCode ierr;
2285e3dda7SBarry Smith 
2385e3dda7SBarry Smith   PetscFunctionBegin;
2485e3dda7SBarry Smith   ierr = MatMultTransposeAdd(Na->A,v1,v2,v3);CHKERRQ(ierr);
2585e3dda7SBarry Smith   PetscFunctionReturn(0);
2685e3dda7SBarry Smith }
2785e3dda7SBarry Smith 
2847a9afc9SBarry Smith PetscErrorCode MatMultTranspose_Transpose(Mat N,Vec x,Vec y)
2947a9afc9SBarry Smith {
3047a9afc9SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
3147a9afc9SBarry Smith   PetscErrorCode ierr;
3247a9afc9SBarry Smith 
3347a9afc9SBarry Smith   PetscFunctionBegin;
3447a9afc9SBarry Smith   ierr = MatMult(Na->A,x,y);CHKERRQ(ierr);
3547a9afc9SBarry Smith   PetscFunctionReturn(0);
3647a9afc9SBarry Smith }
3747a9afc9SBarry Smith 
3847a9afc9SBarry Smith PetscErrorCode MatMultTransposeAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3)
3947a9afc9SBarry Smith {
4047a9afc9SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
4147a9afc9SBarry Smith   PetscErrorCode ierr;
4247a9afc9SBarry Smith 
4347a9afc9SBarry Smith   PetscFunctionBegin;
4447a9afc9SBarry Smith   ierr = MatMultAdd(Na->A,v1,v2,v3);CHKERRQ(ierr);
4547a9afc9SBarry Smith   PetscFunctionReturn(0);
4647a9afc9SBarry Smith }
4747a9afc9SBarry Smith 
4885e3dda7SBarry Smith PetscErrorCode MatDestroy_Transpose(Mat N)
4985e3dda7SBarry Smith {
5085e3dda7SBarry Smith   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
5185e3dda7SBarry Smith   PetscErrorCode ierr;
5285e3dda7SBarry Smith 
5385e3dda7SBarry Smith   PetscFunctionBegin;
546bf464f9SBarry Smith   ierr = MatDestroy(&Na->A);CHKERRQ(ierr);
558060fb66Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)N,"MatTransposeGetMat_C",NULL);CHKERRQ(ierr);
566718818eSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_anytype_C",NULL);CHKERRQ(ierr);
57bf0cc555SLisandro Dalcin   ierr = PetscFree(N->data);CHKERRQ(ierr);
5885e3dda7SBarry Smith   PetscFunctionReturn(0);
5985e3dda7SBarry Smith }
6085e3dda7SBarry Smith 
61d0de2241SAndrew Spott PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat* m)
62d0de2241SAndrew Spott {
63d0de2241SAndrew Spott   Mat_Transpose  *Na = (Mat_Transpose*)N->data;
64d0de2241SAndrew Spott   PetscErrorCode ierr;
65d0de2241SAndrew Spott 
66d0de2241SAndrew Spott   PetscFunctionBegin;
67d0de2241SAndrew Spott   if (op == MAT_COPY_VALUES) {
68d0de2241SAndrew Spott     ierr = MatTranspose(Na->A,MAT_INITIAL_MATRIX,m);CHKERRQ(ierr);
69d0de2241SAndrew Spott   } else if (op == MAT_DO_NOT_COPY_VALUES) {
70d0de2241SAndrew Spott     ierr = MatDuplicate(Na->A,MAT_DO_NOT_COPY_VALUES,m);CHKERRQ(ierr);
71c837ededSStefano Zampini     ierr = MatTranspose(*m,MAT_INPLACE_MATRIX,m);CHKERRQ(ierr);
72fb41c00aSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)N),PETSC_ERR_SUP,"MAT_SHARE_NONZERO_PATTERN not supported for this matrix type");
73d0de2241SAndrew Spott   PetscFunctionReturn(0);
74d0de2241SAndrew Spott }
75d0de2241SAndrew Spott 
76d9b48344SStefano Zampini PetscErrorCode MatCreateVecs_Transpose(Mat A,Vec *r, Vec *l)
77d9b48344SStefano Zampini {
78d9b48344SStefano Zampini   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
79d9b48344SStefano Zampini   PetscErrorCode ierr;
80d9b48344SStefano Zampini 
81d9b48344SStefano Zampini   PetscFunctionBegin;
82d9b48344SStefano Zampini   ierr = MatCreateVecs(Aa->A,l,r);CHKERRQ(ierr);
83d9b48344SStefano Zampini   PetscFunctionReturn(0);
84d9b48344SStefano Zampini }
85d9b48344SStefano Zampini 
866171f1c8SPierre Jolivet PetscErrorCode MatAXPY_Transpose(Mat Y,PetscScalar a,Mat X,MatStructure str)
876171f1c8SPierre Jolivet {
886171f1c8SPierre Jolivet   Mat_Transpose  *Ya = (Mat_Transpose*)Y->data;
896171f1c8SPierre Jolivet   Mat_Transpose  *Xa = (Mat_Transpose*)X->data;
906171f1c8SPierre Jolivet   Mat              M = Ya->A;
916171f1c8SPierre Jolivet   Mat              N = Xa->A;
926171f1c8SPierre Jolivet   PetscErrorCode ierr;
936171f1c8SPierre Jolivet 
946171f1c8SPierre Jolivet   PetscFunctionBegin;
956171f1c8SPierre Jolivet   ierr = MatAXPY(M,a,N,str);CHKERRQ(ierr);
966171f1c8SPierre Jolivet   PetscFunctionReturn(0);
976171f1c8SPierre Jolivet }
986171f1c8SPierre Jolivet 
9952c5f739Sprj- PetscErrorCode MatHasOperation_Transpose(Mat mat,MatOperation op,PetscBool *has)
10052c5f739Sprj- {
10152c5f739Sprj-   Mat_Transpose  *X = (Mat_Transpose*)mat->data;
10252c5f739Sprj-   PetscErrorCode ierr;
10352c5f739Sprj-   PetscFunctionBegin;
10452c5f739Sprj- 
10552c5f739Sprj-   *has = PETSC_FALSE;
1063c6db4c4SPierre Jolivet   if (op == MATOP_MULT) {
1073c6db4c4SPierre Jolivet     ierr = MatHasOperation(X->A,MATOP_MULT_TRANSPOSE,has);CHKERRQ(ierr);
1083c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_TRANSPOSE) {
1093c6db4c4SPierre Jolivet     ierr = MatHasOperation(X->A,MATOP_MULT,has);CHKERRQ(ierr);
1103c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_ADD) {
1113c6db4c4SPierre Jolivet     ierr = MatHasOperation(X->A,MATOP_MULT_TRANSPOSE_ADD,has);CHKERRQ(ierr);
1123c6db4c4SPierre Jolivet   } else if (op == MATOP_MULT_TRANSPOSE_ADD) {
1133c6db4c4SPierre Jolivet     ierr = MatHasOperation(X->A,MATOP_MULT_ADD,has);CHKERRQ(ierr);
1143c6db4c4SPierre Jolivet   } else if (((void**)mat->ops)[op]) *has = PETSC_TRUE;
11552c5f739Sprj-   PetscFunctionReturn(0);
11652c5f739Sprj- }
11752c5f739Sprj- 
1186718818eSStefano Zampini /* used by hermitian transpose */
1196718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D)
1206718818eSStefano Zampini {
1216718818eSStefano Zampini   Mat            A,B,C,Ain,Bin,Cin;
1226718818eSStefano Zampini   PetscBool      Aistrans,Bistrans,Cistrans;
1236718818eSStefano Zampini   PetscInt       Atrans,Btrans,Ctrans;
1246718818eSStefano Zampini   MatProductType ptype;
1256718818eSStefano Zampini   PetscErrorCode ierr;
1266718818eSStefano Zampini 
1276718818eSStefano Zampini   PetscFunctionBegin;
1286718818eSStefano Zampini   MatCheckProduct(D,1);
1296718818eSStefano Zampini   A = D->product->A;
1306718818eSStefano Zampini   B = D->product->B;
1316718818eSStefano Zampini   C = D->product->C;
1326718818eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&Aistrans);CHKERRQ(ierr);
1336718818eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&Bistrans);CHKERRQ(ierr);
1346718818eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)C,MATTRANSPOSEMAT,&Cistrans);CHKERRQ(ierr);
1356718818eSStefano Zampini   if (!Aistrans && !Bistrans && !Cistrans) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"This should not happen");
1366718818eSStefano Zampini   Atrans = 0;
1376718818eSStefano Zampini   Ain    = A;
1386718818eSStefano Zampini   while (Aistrans) {
1396718818eSStefano Zampini     Atrans++;
1406718818eSStefano Zampini     ierr = MatTransposeGetMat(Ain,&Ain);CHKERRQ(ierr);
1416718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)Ain,MATTRANSPOSEMAT,&Aistrans);CHKERRQ(ierr);
1426718818eSStefano Zampini   }
1436718818eSStefano Zampini   Btrans = 0;
1446718818eSStefano Zampini   Bin    = B;
1456718818eSStefano Zampini   while (Bistrans) {
1466718818eSStefano Zampini     Btrans++;
1476718818eSStefano Zampini     ierr = MatTransposeGetMat(Bin,&Bin);CHKERRQ(ierr);
1486718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)Bin,MATTRANSPOSEMAT,&Bistrans);CHKERRQ(ierr);
1496718818eSStefano Zampini   }
1506718818eSStefano Zampini   Ctrans = 0;
1516718818eSStefano Zampini   Cin    = C;
1526718818eSStefano Zampini   while (Cistrans) {
1536718818eSStefano Zampini     Ctrans++;
1546718818eSStefano Zampini     ierr = MatTransposeGetMat(Cin,&Cin);CHKERRQ(ierr);
1556718818eSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)Cin,MATTRANSPOSEMAT,&Cistrans);CHKERRQ(ierr);
1566718818eSStefano Zampini   }
1576718818eSStefano Zampini   Atrans = Atrans%2;
1586718818eSStefano Zampini   Btrans = Btrans%2;
1596718818eSStefano Zampini   Ctrans = Ctrans%2;
1606718818eSStefano Zampini   ptype = D->product->type; /* same product type by default */
1616718818eSStefano Zampini   if (Ain->symmetric) Atrans = 0;
1626718818eSStefano Zampini   if (Bin->symmetric) Btrans = 0;
1636718818eSStefano Zampini   if (Cin && Cin->symmetric) Ctrans = 0;
1646718818eSStefano Zampini 
1656718818eSStefano Zampini   if (Atrans || Btrans || Ctrans) {
1666718818eSStefano Zampini     ptype = MATPRODUCT_UNSPECIFIED;
1676718818eSStefano Zampini     switch (D->product->type) {
1686718818eSStefano Zampini     case MATPRODUCT_AB:
1696718818eSStefano Zampini       if (Atrans && Btrans) { /* At * Bt we do not have support for this */
1706718818eSStefano Zampini         /* TODO custom implementation ? */
1716718818eSStefano Zampini       } else if (Atrans) { /* At * B */
1726718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1736718818eSStefano Zampini       } else { /* A * Bt */
1746718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1756718818eSStefano Zampini       }
1766718818eSStefano Zampini       break;
1776718818eSStefano Zampini     case MATPRODUCT_AtB:
1786718818eSStefano Zampini       if (Atrans && Btrans) { /* A * Bt */
1796718818eSStefano Zampini         ptype = MATPRODUCT_ABt;
1806718818eSStefano Zampini       } else if (Atrans) { /* A * B */
1816718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1826718818eSStefano Zampini       } else { /* At * Bt we do not have support for this */
1836718818eSStefano Zampini         /* TODO custom implementation ? */
1846718818eSStefano Zampini       }
1856718818eSStefano Zampini       break;
1866718818eSStefano Zampini     case MATPRODUCT_ABt:
1876718818eSStefano Zampini       if (Atrans && Btrans) { /* At * B */
1886718818eSStefano Zampini         ptype = MATPRODUCT_AtB;
1896718818eSStefano Zampini       } else if (Atrans) { /* At * Bt we do not have support for this */
1906718818eSStefano Zampini         /* TODO custom implementation ? */
1916718818eSStefano Zampini       } else {  /* A * B */
1926718818eSStefano Zampini         ptype = MATPRODUCT_AB;
1936718818eSStefano Zampini       }
1946718818eSStefano Zampini       break;
1956718818eSStefano Zampini     case MATPRODUCT_PtAP:
1966718818eSStefano Zampini       if (Atrans) { /* PtAtP */
1976718818eSStefano Zampini         /* TODO custom implementation ? */
1986718818eSStefano Zampini       } else { /* RARt */
1996718818eSStefano Zampini         ptype = MATPRODUCT_RARt;
2006718818eSStefano Zampini       }
2016718818eSStefano Zampini       break;
2026718818eSStefano Zampini     case MATPRODUCT_RARt:
2036718818eSStefano Zampini       if (Atrans) { /* RAtRt */
2046718818eSStefano Zampini         /* TODO custom implementation ? */
2056718818eSStefano Zampini       } else { /* PtAP */
2066718818eSStefano Zampini         ptype = MATPRODUCT_PtAP;
2076718818eSStefano Zampini       }
2086718818eSStefano Zampini       break;
2096718818eSStefano Zampini     case MATPRODUCT_ABC:
2106718818eSStefano Zampini       /* TODO custom implementation ? */
2116718818eSStefano Zampini       break;
2126718818eSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[D->product->type]);
2136718818eSStefano Zampini     }
2146718818eSStefano Zampini   }
2156718818eSStefano Zampini   ierr = MatProductReplaceMats(Ain,Bin,Cin,D);CHKERRQ(ierr);
2166718818eSStefano Zampini   ierr = MatProductSetType(D,ptype);CHKERRQ(ierr);
2176718818eSStefano Zampini   ierr = MatProductSetFromOptions(D);CHKERRQ(ierr);
2186718818eSStefano Zampini   PetscFunctionReturn(0);
2196718818eSStefano Zampini }
2206718818eSStefano Zampini 
221a0eea678SPierre Jolivet PetscErrorCode MatGetDiagonal_Transpose(Mat A,Vec v)
222a0eea678SPierre Jolivet {
223a0eea678SPierre Jolivet   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
224a0eea678SPierre Jolivet   PetscErrorCode ierr;
225a0eea678SPierre Jolivet 
226a0eea678SPierre Jolivet   PetscFunctionBegin;
227a0eea678SPierre Jolivet   ierr = MatGetDiagonal(Aa->A,v);CHKERRQ(ierr);
228a0eea678SPierre Jolivet   PetscFunctionReturn(0);
229a0eea678SPierre Jolivet }
230a0eea678SPierre Jolivet 
231a0eea678SPierre Jolivet PetscErrorCode MatConvert_Transpose(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
232a0eea678SPierre Jolivet {
233a0eea678SPierre Jolivet   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
234a0eea678SPierre Jolivet   Mat            B;
235a0eea678SPierre Jolivet   PetscErrorCode ierr;
236a0eea678SPierre Jolivet 
237a0eea678SPierre Jolivet   PetscFunctionBegin;
238a0eea678SPierre Jolivet   ierr = MatTranspose(Aa->A,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
239*ff83db7bSPierre Jolivet   if (reuse != MAT_INPLACE_MATRIX) {
240a0eea678SPierre Jolivet     ierr = MatConvert(B,newtype,reuse,newmat);CHKERRQ(ierr);
241a0eea678SPierre Jolivet     ierr = MatDestroy(&B);CHKERRQ(ierr);
242*ff83db7bSPierre Jolivet   } else {
243*ff83db7bSPierre Jolivet     ierr = MatConvert(B,newtype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
244*ff83db7bSPierre Jolivet     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
245*ff83db7bSPierre Jolivet   }
246a0eea678SPierre Jolivet   PetscFunctionReturn(0);
247a0eea678SPierre Jolivet }
248a0eea678SPierre Jolivet 
2498060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat_Transpose(Mat A,Mat *M)
2508060fb66Sstefano_zampini {
2518060fb66Sstefano_zampini   Mat_Transpose  *Aa = (Mat_Transpose*)A->data;
2528060fb66Sstefano_zampini 
2538060fb66Sstefano_zampini   PetscFunctionBegin;
2548060fb66Sstefano_zampini   *M = Aa->A;
2558060fb66Sstefano_zampini   PetscFunctionReturn(0);
2568060fb66Sstefano_zampini }
2578060fb66Sstefano_zampini 
2588060fb66Sstefano_zampini /*@
25906511a5cSPierre Jolivet       MatTransposeGetMat - Gets the Mat object stored inside a MATTRANSPOSEMAT
2608060fb66Sstefano_zampini 
2618060fb66Sstefano_zampini    Logically collective on Mat
2628060fb66Sstefano_zampini 
2638060fb66Sstefano_zampini    Input Parameter:
2648060fb66Sstefano_zampini .   A  - the MATTRANSPOSE matrix
2658060fb66Sstefano_zampini 
2668060fb66Sstefano_zampini    Output Parameter:
2678060fb66Sstefano_zampini .   M - the matrix object stored inside A
2688060fb66Sstefano_zampini 
2698060fb66Sstefano_zampini    Level: intermediate
2708060fb66Sstefano_zampini 
2718060fb66Sstefano_zampini .seealso: MatCreateTranspose()
2728060fb66Sstefano_zampini 
2738060fb66Sstefano_zampini @*/
2748060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat(Mat A,Mat *M)
2758060fb66Sstefano_zampini {
2768060fb66Sstefano_zampini   PetscErrorCode ierr;
2778060fb66Sstefano_zampini 
2788060fb66Sstefano_zampini   PetscFunctionBegin;
2798060fb66Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2808060fb66Sstefano_zampini   PetscValidType(A,1);
2818060fb66Sstefano_zampini   PetscValidPointer(M,2);
2828060fb66Sstefano_zampini   ierr = PetscUseMethod(A,"MatTransposeGetMat_C",(Mat,Mat*),(A,M));CHKERRQ(ierr);
2838060fb66Sstefano_zampini   PetscFunctionReturn(0);
2848060fb66Sstefano_zampini }
285d0de2241SAndrew Spott 
28685e3dda7SBarry Smith /*@
28785e3dda7SBarry Smith       MatCreateTranspose - Creates a new matrix object that behaves like A'
28885e3dda7SBarry Smith 
28985e3dda7SBarry Smith    Collective on Mat
29085e3dda7SBarry Smith 
29185e3dda7SBarry Smith    Input Parameter:
29285e3dda7SBarry Smith .   A  - the (possibly rectangular) matrix
29385e3dda7SBarry Smith 
29485e3dda7SBarry Smith    Output Parameter:
29585e3dda7SBarry Smith .   N - the matrix that represents A'
29685e3dda7SBarry Smith 
29785e3dda7SBarry Smith    Level: intermediate
29885e3dda7SBarry Smith 
29995452b02SPatrick Sanan    Notes:
30095452b02SPatrick Sanan     The transpose A' is NOT actually formed! Rather the new matrix
30185e3dda7SBarry Smith           object performs the matrix-vector product by using the MatMultTranspose() on
30285e3dda7SBarry Smith           the original matrix
30385e3dda7SBarry Smith 
30485e3dda7SBarry Smith .seealso: MatCreateNormal(), MatMult(), MatMultTranspose(), MatCreate()
30585e3dda7SBarry Smith 
30685e3dda7SBarry Smith @*/
3077087cfbeSBarry Smith PetscErrorCode  MatCreateTranspose(Mat A,Mat *N)
30885e3dda7SBarry Smith {
30985e3dda7SBarry Smith   PetscErrorCode ierr;
31085e3dda7SBarry Smith   PetscInt       m,n;
31185e3dda7SBarry Smith   Mat_Transpose  *Na;
312487d878eSStefano Zampini   VecType        vtype;
31385e3dda7SBarry Smith 
31485e3dda7SBarry Smith   PetscFunctionBegin;
31585e3dda7SBarry Smith   ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
316ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),N);CHKERRQ(ierr);
31785e3dda7SBarry Smith   ierr = MatSetSizes(*N,n,m,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
318d97d01c0SJed Brown   ierr = PetscLayoutSetUp((*N)->rmap);CHKERRQ(ierr);
319d97d01c0SJed Brown   ierr = PetscLayoutSetUp((*N)->cmap);CHKERRQ(ierr);
320557cca28SSatish Balay   ierr = PetscObjectChangeTypeName((PetscObject)*N,MATTRANSPOSEMAT);CHKERRQ(ierr);
32185e3dda7SBarry Smith 
322b00a9115SJed Brown   ierr       = PetscNewLog(*N,&Na);CHKERRQ(ierr);
32385e3dda7SBarry Smith   (*N)->data = (void*) Na;
32485e3dda7SBarry Smith   ierr       = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
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 
3418060fb66Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)(*N),"MatTransposeGetMat_C",MatTransposeGetMat_Transpose);CHKERRQ(ierr);
3426718818eSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_Transpose);CHKERRQ(ierr);
34333d57670SJed Brown   ierr = MatSetBlockSizes(*N,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
344487d878eSStefano Zampini   ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr);
345487d878eSStefano Zampini   ierr = MatSetVecType(*N,vtype);CHKERRQ(ierr);
3462487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3472487f3f2SStefano Zampini   ierr = MatBindToCPU(*N,A->boundtocpu);CHKERRQ(ierr);
3482487f3f2SStefano Zampini #endif
349037c98a2SJed Brown   ierr = MatSetUp(*N);CHKERRQ(ierr);
35085e3dda7SBarry Smith   PetscFunctionReturn(0);
35185e3dda7SBarry Smith }
352