xref: /petsc/src/mat/impls/transpose/htransm.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
1d0de2241SAndrew Spott 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
3d0de2241SAndrew Spott 
4d0de2241SAndrew Spott typedef struct {
5d0de2241SAndrew Spott   Mat A;
6fb41c00aSBarry Smith } Mat_HT;
7d0de2241SAndrew Spott 
8d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_HermitianTranspose(Mat D)
9d71ae5a4SJacob Faibussowitsch {
10013e2dc7SBarry Smith   Mat            A, B, C, Ain, Bin, Cin;
11013e2dc7SBarry Smith   PetscBool      Aistrans, Bistrans, Cistrans;
12013e2dc7SBarry Smith   PetscInt       Atrans, Btrans, Ctrans;
13013e2dc7SBarry Smith   MatProductType ptype;
14013e2dc7SBarry Smith 
15013e2dc7SBarry Smith   PetscFunctionBegin;
16013e2dc7SBarry Smith   MatCheckProduct(D, 1);
17013e2dc7SBarry Smith   A = D->product->A;
18013e2dc7SBarry Smith   B = D->product->B;
19013e2dc7SBarry Smith   C = D->product->C;
20013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHERMITIANTRANSPOSEVIRTUAL, &Aistrans));
21013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHERMITIANTRANSPOSEVIRTUAL, &Bistrans));
22013e2dc7SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHERMITIANTRANSPOSEVIRTUAL, &Cistrans));
23013e2dc7SBarry Smith   PetscCheck(Aistrans || Bistrans || Cistrans, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "This should not happen");
24013e2dc7SBarry Smith   Atrans = 0;
25013e2dc7SBarry Smith   Ain    = A;
26013e2dc7SBarry Smith   while (Aistrans) {
27013e2dc7SBarry Smith     Atrans++;
28013e2dc7SBarry Smith     PetscCall(MatHermitianTransposeGetMat(Ain, &Ain));
29013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Ain, MATHERMITIANTRANSPOSEVIRTUAL, &Aistrans));
30013e2dc7SBarry Smith   }
31013e2dc7SBarry Smith   Btrans = 0;
32013e2dc7SBarry Smith   Bin    = B;
33013e2dc7SBarry Smith   while (Bistrans) {
34013e2dc7SBarry Smith     Btrans++;
35013e2dc7SBarry Smith     PetscCall(MatHermitianTransposeGetMat(Bin, &Bin));
36013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Bin, MATHERMITIANTRANSPOSEVIRTUAL, &Bistrans));
37013e2dc7SBarry Smith   }
38013e2dc7SBarry Smith   Ctrans = 0;
39013e2dc7SBarry Smith   Cin    = C;
40013e2dc7SBarry Smith   while (Cistrans) {
41013e2dc7SBarry Smith     Ctrans++;
42013e2dc7SBarry Smith     PetscCall(MatHermitianTransposeGetMat(Cin, &Cin));
43013e2dc7SBarry Smith     PetscCall(PetscObjectTypeCompare((PetscObject)Cin, MATHERMITIANTRANSPOSEVIRTUAL, &Cistrans));
44013e2dc7SBarry Smith   }
45013e2dc7SBarry Smith   Atrans = Atrans % 2;
46013e2dc7SBarry Smith   Btrans = Btrans % 2;
47013e2dc7SBarry Smith   Ctrans = Ctrans % 2;
48013e2dc7SBarry Smith   ptype  = D->product->type; /* same product type by default */
49013e2dc7SBarry Smith   if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0;
50013e2dc7SBarry Smith   if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0;
51013e2dc7SBarry Smith   if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0;
52013e2dc7SBarry Smith 
53013e2dc7SBarry Smith   if (Atrans || Btrans || Ctrans) {
545afd5614SVaclav Hapla     PetscCheck(!PetscDefined(USE_COMPLEX), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for complex Hermitian transpose matrices");
55013e2dc7SBarry Smith     ptype = MATPRODUCT_UNSPECIFIED;
56013e2dc7SBarry Smith     switch (D->product->type) {
57013e2dc7SBarry Smith     case MATPRODUCT_AB:
58013e2dc7SBarry Smith       if (Atrans && Btrans) { /* At * Bt we do not have support for this */
59013e2dc7SBarry Smith         /* TODO custom implementation ? */
60013e2dc7SBarry Smith       } else if (Atrans) { /* At * B */
61013e2dc7SBarry Smith         ptype = MATPRODUCT_AtB;
62013e2dc7SBarry Smith       } else { /* A * Bt */
63013e2dc7SBarry Smith         ptype = MATPRODUCT_ABt;
64013e2dc7SBarry Smith       }
65013e2dc7SBarry Smith       break;
66013e2dc7SBarry Smith     case MATPRODUCT_AtB:
67013e2dc7SBarry Smith       if (Atrans && Btrans) { /* A * Bt */
68013e2dc7SBarry Smith         ptype = MATPRODUCT_ABt;
69013e2dc7SBarry Smith       } else if (Atrans) { /* A * B */
70013e2dc7SBarry Smith         ptype = MATPRODUCT_AB;
71013e2dc7SBarry Smith       } else { /* At * Bt we do not have support for this */
72013e2dc7SBarry Smith         /* TODO custom implementation ? */
73013e2dc7SBarry Smith       }
74013e2dc7SBarry Smith       break;
75013e2dc7SBarry Smith     case MATPRODUCT_ABt:
76013e2dc7SBarry Smith       if (Atrans && Btrans) { /* At * B */
77013e2dc7SBarry Smith         ptype = MATPRODUCT_AtB;
78013e2dc7SBarry Smith       } else if (Atrans) { /* At * Bt we do not have support for this */
79013e2dc7SBarry Smith         /* TODO custom implementation ? */
80013e2dc7SBarry Smith       } else { /* A * B */
81013e2dc7SBarry Smith         ptype = MATPRODUCT_AB;
82013e2dc7SBarry Smith       }
83013e2dc7SBarry Smith       break;
84013e2dc7SBarry Smith     case MATPRODUCT_PtAP:
85013e2dc7SBarry Smith       if (Atrans) { /* PtAtP */
86013e2dc7SBarry Smith         /* TODO custom implementation ? */
87013e2dc7SBarry Smith       } else { /* RARt */
88013e2dc7SBarry Smith         ptype = MATPRODUCT_RARt;
89013e2dc7SBarry Smith       }
90013e2dc7SBarry Smith       break;
91013e2dc7SBarry Smith     case MATPRODUCT_RARt:
92013e2dc7SBarry Smith       if (Atrans) { /* RAtRt */
93013e2dc7SBarry Smith         /* TODO custom implementation ? */
94013e2dc7SBarry Smith       } else { /* PtAP */
95013e2dc7SBarry Smith         ptype = MATPRODUCT_PtAP;
96013e2dc7SBarry Smith       }
97013e2dc7SBarry Smith       break;
98013e2dc7SBarry Smith     case MATPRODUCT_ABC:
99013e2dc7SBarry Smith       /* TODO custom implementation ? */
100013e2dc7SBarry Smith       break;
101d71ae5a4SJacob Faibussowitsch     default:
102d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)D), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[D->product->type]);
103013e2dc7SBarry Smith     }
104013e2dc7SBarry Smith   }
105013e2dc7SBarry Smith   PetscCall(MatProductReplaceMats(Ain, Bin, Cin, D));
106013e2dc7SBarry Smith   PetscCall(MatProductSetType(D, ptype));
107013e2dc7SBarry Smith   PetscCall(MatProductSetFromOptions(D));
1083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109013e2dc7SBarry Smith }
110d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_HT(Mat N, Vec x, Vec y)
111d71ae5a4SJacob Faibussowitsch {
112fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
113d0de2241SAndrew Spott 
114d0de2241SAndrew Spott   PetscFunctionBegin;
1159566063dSJacob Faibussowitsch   PetscCall(MatMultHermitianTranspose(Na->A, x, y));
1163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
117d0de2241SAndrew Spott }
118d0de2241SAndrew Spott 
119d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_HT(Mat N, Vec v1, Vec v2, Vec v3)
120d71ae5a4SJacob Faibussowitsch {
121fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
122d0de2241SAndrew Spott 
123d0de2241SAndrew Spott   PetscFunctionBegin;
1249566063dSJacob Faibussowitsch   PetscCall(MatMultHermitianTransposeAdd(Na->A, v1, v2, v3));
1253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
126d0de2241SAndrew Spott }
127d0de2241SAndrew Spott 
128d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultHermitianTranspose_HT(Mat N, Vec x, Vec y)
129d71ae5a4SJacob Faibussowitsch {
130fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
131d0de2241SAndrew Spott 
132d0de2241SAndrew Spott   PetscFunctionBegin;
1339566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A, x, y));
1343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135d0de2241SAndrew Spott }
136d0de2241SAndrew Spott 
137d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultHermitianTransposeAdd_HT(Mat N, Vec v1, Vec v2, Vec v3)
138d71ae5a4SJacob Faibussowitsch {
139fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
140d0de2241SAndrew Spott 
141d0de2241SAndrew Spott   PetscFunctionBegin;
1429566063dSJacob Faibussowitsch   PetscCall(MatMultAdd(Na->A, v1, v2, v3));
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144d0de2241SAndrew Spott }
145d0de2241SAndrew Spott 
146d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_HT(Mat N)
147d71ae5a4SJacob Faibussowitsch {
148fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
149d0de2241SAndrew Spott 
150d0de2241SAndrew Spott   PetscFunctionBegin;
1519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Na->A));
1529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatHermitianTransposeGetMat_C", NULL));
153013e2dc7SBarry Smith   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatProductSetFromOptions_anytype_C", NULL));
154204606b3SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatTransposeGetMat_C", NULL));
156204606b3SStefano Zampini #endif
1579566063dSJacob Faibussowitsch   PetscCall(PetscFree(N->data));
1583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
159d0de2241SAndrew Spott }
160d0de2241SAndrew Spott 
161d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_HT(Mat N, MatDuplicateOption op, Mat *m)
162d71ae5a4SJacob Faibussowitsch {
163fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
164d0de2241SAndrew Spott 
165d0de2241SAndrew Spott   PetscFunctionBegin;
166d0de2241SAndrew Spott   if (op == MAT_COPY_VALUES) {
1679566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(Na->A, MAT_INITIAL_MATRIX, m));
168d0de2241SAndrew Spott   } else if (op == MAT_DO_NOT_COPY_VALUES) {
1699566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(Na->A, MAT_DO_NOT_COPY_VALUES, m));
1709566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(*m, MAT_INPLACE_MATRIX, m));
171fb41c00aSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "MAT_SHARE_NONZERO_PATTERN not supported for this matrix type");
1723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
173d0de2241SAndrew Spott }
174d0de2241SAndrew Spott 
175d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateVecs_HT(Mat N, Vec *r, Vec *l)
176d71ae5a4SJacob Faibussowitsch {
17706511a5cSPierre Jolivet   Mat_HT *Na = (Mat_HT *)N->data;
17806511a5cSPierre Jolivet 
17906511a5cSPierre Jolivet   PetscFunctionBegin;
1809566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(Na->A, l, r));
1813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18206511a5cSPierre Jolivet }
18306511a5cSPierre Jolivet 
184d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_HT(Mat Y, PetscScalar a, Mat X, MatStructure str)
185d71ae5a4SJacob Faibussowitsch {
1866171f1c8SPierre Jolivet   Mat_HT *Ya = (Mat_HT *)Y->data;
1876171f1c8SPierre Jolivet   Mat_HT *Xa = (Mat_HT *)X->data;
1886171f1c8SPierre Jolivet   Mat     M  = Ya->A;
1896171f1c8SPierre Jolivet   Mat     N  = Xa->A;
1906171f1c8SPierre Jolivet 
1916171f1c8SPierre Jolivet   PetscFunctionBegin;
1929566063dSJacob Faibussowitsch   PetscCall(MatAXPY(M, a, N, str));
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1946171f1c8SPierre Jolivet }
1956171f1c8SPierre Jolivet 
196d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHermitianTransposeGetMat_HT(Mat N, Mat *M)
197d71ae5a4SJacob Faibussowitsch {
19806511a5cSPierre Jolivet   Mat_HT *Na = (Mat_HT *)N->data;
19906511a5cSPierre Jolivet 
20006511a5cSPierre Jolivet   PetscFunctionBegin;
20106511a5cSPierre Jolivet   *M = Na->A;
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20306511a5cSPierre Jolivet }
20406511a5cSPierre Jolivet 
20506511a5cSPierre Jolivet /*@
206013e2dc7SBarry Smith       MatHermitianTransposeGetMat - Gets the `Mat` object stored inside a `MATHERMITIANTRANSPOSEVIRTUAL`
20706511a5cSPierre Jolivet 
208*20f4b53cSBarry Smith    Logically Collective
20906511a5cSPierre Jolivet 
21006511a5cSPierre Jolivet    Input Parameter:
211013e2dc7SBarry Smith .   A  - the `MATHERMITIANTRANSPOSEVIRTUAL` matrix
21206511a5cSPierre Jolivet 
21306511a5cSPierre Jolivet    Output Parameter:
21406511a5cSPierre Jolivet .   M - the matrix object stored inside A
21506511a5cSPierre Jolivet 
21606511a5cSPierre Jolivet    Level: intermediate
21706511a5cSPierre Jolivet 
2182ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATHERMITIANTRANSPOSEVIRTUAL`, `MatCreateHermitianTranspose()`
21906511a5cSPierre Jolivet @*/
220d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHermitianTransposeGetMat(Mat A, Mat *M)
221d71ae5a4SJacob Faibussowitsch {
22206511a5cSPierre Jolivet   PetscFunctionBegin;
22306511a5cSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22406511a5cSPierre Jolivet   PetscValidType(A, 1);
22506511a5cSPierre Jolivet   PetscValidPointer(M, 2);
226cac4c232SBarry Smith   PetscUseMethod(A, "MatHermitianTransposeGetMat_C", (Mat, Mat *), (A, M));
2273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22806511a5cSPierre Jolivet }
22906511a5cSPierre Jolivet 
2306718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat);
2316718818eSStefano Zampini 
232d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_HT(Mat A, Vec v)
233d71ae5a4SJacob Faibussowitsch {
234a0eea678SPierre Jolivet   Mat_HT *Na = (Mat_HT *)A->data;
235a0eea678SPierre Jolivet 
236a0eea678SPierre Jolivet   PetscFunctionBegin;
2379566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(Na->A, v));
2389566063dSJacob Faibussowitsch   PetscCall(VecConjugate(v));
2393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
240a0eea678SPierre Jolivet }
241a0eea678SPierre Jolivet 
242d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_HT(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
243d71ae5a4SJacob Faibussowitsch {
244a0eea678SPierre Jolivet   Mat_HT   *Na = (Mat_HT *)A->data;
2456a4403aaSStefano Zampini   PetscBool flg;
246a0eea678SPierre Jolivet 
247a0eea678SPierre Jolivet   PetscFunctionBegin;
2489566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(Na->A, MATOP_HERMITIAN_TRANSPOSE, &flg));
2496a4403aaSStefano Zampini   if (flg) {
2506a4403aaSStefano Zampini     Mat B;
2516a4403aaSStefano Zampini 
2529566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(Na->A, MAT_INITIAL_MATRIX, &B));
253ff83db7bSPierre Jolivet     if (reuse != MAT_INPLACE_MATRIX) {
2549566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, reuse, newmat));
2559566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B));
256ff83db7bSPierre Jolivet     } else {
2579566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B));
2589566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &B));
259ff83db7bSPierre Jolivet     }
2606a4403aaSStefano Zampini   } else { /* use basic converter as fallback */
2619566063dSJacob Faibussowitsch     PetscCall(MatConvert_Basic(A, newtype, reuse, newmat));
2626a4403aaSStefano Zampini   }
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
264a0eea678SPierre Jolivet }
265a0eea678SPierre Jolivet 
26611a5261eSBarry Smith /*MC
267013e2dc7SBarry Smith    MATHERMITIANTRANSPOSEVIRTUAL - "hermitiantranspose" - A matrix type that represents a virtual transpose of a matrix
268d0de2241SAndrew Spott 
26911a5261eSBarry Smith   Level: advanced
27011a5261eSBarry Smith 
2712ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`
27211a5261eSBarry Smith M*/
27311a5261eSBarry Smith 
27411a5261eSBarry Smith /*@
275013e2dc7SBarry Smith       MatCreateHermitianTranspose - Creates a new matrix object of `MatType` `MATHERMITIANTRANSPOSEVIRTUAL` that behaves like A'*
27611a5261eSBarry Smith 
277c3339decSBarry Smith    Collective
278d0de2241SAndrew Spott 
279d0de2241SAndrew Spott    Input Parameter:
280d0de2241SAndrew Spott .   A  - the (possibly rectangular) matrix
281d0de2241SAndrew Spott 
282d0de2241SAndrew Spott    Output Parameter:
283d0de2241SAndrew Spott .   N - the matrix that represents A'*
284d0de2241SAndrew Spott 
285d0de2241SAndrew Spott    Level: intermediate
286d0de2241SAndrew Spott 
28711a5261eSBarry Smith    Note:
28811a5261eSBarry Smith     The Hermitian transpose A' is NOT actually formed! Rather the new matrix
28911a5261eSBarry Smith           object performs the matrix-vector product, `MatMult()`, by using the `MatMultHermitianTranspose()` on
290d0de2241SAndrew Spott           the original matrix
291d0de2241SAndrew Spott 
2922ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateNormal()`, `MatMult()`, `MatMultHermitianTranspose()`, `MatCreate()`,
2932ef1f0ffSBarry Smith           `MATTRANSPOSEVIRTUAL`, `MatCreateTranspose()`, `MatHermitianTransposeGetMat()`, `MATNORMAL`, `MATNORMALHERMITIAN`
294d0de2241SAndrew Spott @*/
295d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateHermitianTranspose(Mat A, Mat *N)
296d71ae5a4SJacob Faibussowitsch {
297d0de2241SAndrew Spott   PetscInt m, n;
298fb41c00aSBarry Smith   Mat_HT  *Na;
299487d878eSStefano Zampini   VecType  vtype;
300d0de2241SAndrew Spott 
301d0de2241SAndrew Spott   PetscFunctionBegin;
3029566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
3039566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N));
3049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N, n, m, PETSC_DECIDE, PETSC_DECIDE));
3059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->rmap));
3069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->cmap));
307013e2dc7SBarry Smith   PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATHERMITIANTRANSPOSEVIRTUAL));
308d0de2241SAndrew Spott 
3094dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&Na));
310d0de2241SAndrew Spott   (*N)->data = (void *)Na;
3119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
312d0de2241SAndrew Spott   Na->A = A;
313d0de2241SAndrew Spott 
314fb41c00aSBarry Smith   (*N)->ops->destroy                   = MatDestroy_HT;
315fb41c00aSBarry Smith   (*N)->ops->mult                      = MatMult_HT;
316fb41c00aSBarry Smith   (*N)->ops->multadd                   = MatMultAdd_HT;
317fb41c00aSBarry Smith   (*N)->ops->multhermitiantranspose    = MatMultHermitianTranspose_HT;
318fb41c00aSBarry Smith   (*N)->ops->multhermitiantransposeadd = MatMultHermitianTransposeAdd_HT;
3196048efd1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
3206048efd1SBarry Smith   (*N)->ops->multtranspose    = MatMultHermitianTranspose_HT;
3216048efd1SBarry Smith   (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_HT;
3226048efd1SBarry Smith #endif
323fb41c00aSBarry Smith   (*N)->ops->duplicate = MatDuplicate_HT;
32406511a5cSPierre Jolivet   (*N)->ops->getvecs   = MatCreateVecs_HT;
3256171f1c8SPierre Jolivet   (*N)->ops->axpy      = MatAXPY_HT;
3266718818eSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3276718818eSStefano Zampini   (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose;
3286718818eSStefano Zampini #endif
329a0eea678SPierre Jolivet   (*N)->ops->getdiagonal = MatGetDiagonal_HT;
330a0eea678SPierre Jolivet   (*N)->ops->convert     = MatConvert_HT;
331d0de2241SAndrew Spott   (*N)->assembled        = PETSC_TRUE;
332d0de2241SAndrew Spott 
3339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatHermitianTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
334013e2dc7SBarry Smith   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_HermitianTranspose));
335204606b3SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
337204606b3SStefano Zampini #endif
3389566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs)));
3399566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A, &vtype));
3409566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N, vtype));
3412487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3429566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N, A->boundtocpu));
3432487f3f2SStefano Zampini #endif
3449566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*N));
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346d0de2241SAndrew Spott }
347