xref: /petsc/src/mat/impls/transpose/htransm.c (revision 11a5261e40035b7c793f2783a2ba6c7cd4f3b077)
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 
89371c9d4SSatish Balay PetscErrorCode MatMult_HT(Mat N, Vec x, Vec y) {
9fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
10d0de2241SAndrew Spott 
11d0de2241SAndrew Spott   PetscFunctionBegin;
129566063dSJacob Faibussowitsch   PetscCall(MatMultHermitianTranspose(Na->A, x, y));
13d0de2241SAndrew Spott   PetscFunctionReturn(0);
14d0de2241SAndrew Spott }
15d0de2241SAndrew Spott 
169371c9d4SSatish Balay PetscErrorCode MatMultAdd_HT(Mat N, Vec v1, Vec v2, Vec v3) {
17fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
18d0de2241SAndrew Spott 
19d0de2241SAndrew Spott   PetscFunctionBegin;
209566063dSJacob Faibussowitsch   PetscCall(MatMultHermitianTransposeAdd(Na->A, v1, v2, v3));
21d0de2241SAndrew Spott   PetscFunctionReturn(0);
22d0de2241SAndrew Spott }
23d0de2241SAndrew Spott 
249371c9d4SSatish Balay PetscErrorCode MatMultHermitianTranspose_HT(Mat N, Vec x, Vec y) {
25fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
26d0de2241SAndrew Spott 
27d0de2241SAndrew Spott   PetscFunctionBegin;
289566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A, x, y));
29d0de2241SAndrew Spott   PetscFunctionReturn(0);
30d0de2241SAndrew Spott }
31d0de2241SAndrew Spott 
329371c9d4SSatish Balay PetscErrorCode MatMultHermitianTransposeAdd_HT(Mat N, Vec v1, Vec v2, Vec v3) {
33fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
34d0de2241SAndrew Spott 
35d0de2241SAndrew Spott   PetscFunctionBegin;
369566063dSJacob Faibussowitsch   PetscCall(MatMultAdd(Na->A, v1, v2, v3));
37d0de2241SAndrew Spott   PetscFunctionReturn(0);
38d0de2241SAndrew Spott }
39d0de2241SAndrew Spott 
409371c9d4SSatish Balay PetscErrorCode MatDestroy_HT(Mat N) {
41fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
42d0de2241SAndrew Spott 
43d0de2241SAndrew Spott   PetscFunctionBegin;
449566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Na->A));
459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatHermitianTransposeGetMat_C", NULL));
46204606b3SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatTransposeGetMat_C", NULL));
489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatProductSetFromOptions_anytype_C", NULL));
49204606b3SStefano Zampini #endif
509566063dSJacob Faibussowitsch   PetscCall(PetscFree(N->data));
51d0de2241SAndrew Spott   PetscFunctionReturn(0);
52d0de2241SAndrew Spott }
53d0de2241SAndrew Spott 
549371c9d4SSatish Balay PetscErrorCode MatDuplicate_HT(Mat N, MatDuplicateOption op, Mat *m) {
55fb41c00aSBarry Smith   Mat_HT *Na = (Mat_HT *)N->data;
56d0de2241SAndrew Spott 
57d0de2241SAndrew Spott   PetscFunctionBegin;
58d0de2241SAndrew Spott   if (op == MAT_COPY_VALUES) {
599566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(Na->A, MAT_INITIAL_MATRIX, m));
60d0de2241SAndrew Spott   } else if (op == MAT_DO_NOT_COPY_VALUES) {
619566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(Na->A, MAT_DO_NOT_COPY_VALUES, m));
629566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(*m, MAT_INPLACE_MATRIX, m));
63fb41c00aSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "MAT_SHARE_NONZERO_PATTERN not supported for this matrix type");
64d0de2241SAndrew Spott   PetscFunctionReturn(0);
65d0de2241SAndrew Spott }
66d0de2241SAndrew Spott 
679371c9d4SSatish Balay PetscErrorCode MatCreateVecs_HT(Mat N, Vec *r, Vec *l) {
6806511a5cSPierre Jolivet   Mat_HT *Na = (Mat_HT *)N->data;
6906511a5cSPierre Jolivet 
7006511a5cSPierre Jolivet   PetscFunctionBegin;
719566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(Na->A, l, r));
7206511a5cSPierre Jolivet   PetscFunctionReturn(0);
7306511a5cSPierre Jolivet }
7406511a5cSPierre Jolivet 
759371c9d4SSatish Balay PetscErrorCode MatAXPY_HT(Mat Y, PetscScalar a, Mat X, MatStructure str) {
766171f1c8SPierre Jolivet   Mat_HT *Ya = (Mat_HT *)Y->data;
776171f1c8SPierre Jolivet   Mat_HT *Xa = (Mat_HT *)X->data;
786171f1c8SPierre Jolivet   Mat     M  = Ya->A;
796171f1c8SPierre Jolivet   Mat     N  = Xa->A;
806171f1c8SPierre Jolivet 
816171f1c8SPierre Jolivet   PetscFunctionBegin;
829566063dSJacob Faibussowitsch   PetscCall(MatAXPY(M, a, N, str));
836171f1c8SPierre Jolivet   PetscFunctionReturn(0);
846171f1c8SPierre Jolivet }
856171f1c8SPierre Jolivet 
869371c9d4SSatish Balay PetscErrorCode MatHermitianTransposeGetMat_HT(Mat N, Mat *M) {
8706511a5cSPierre Jolivet   Mat_HT *Na = (Mat_HT *)N->data;
8806511a5cSPierre Jolivet 
8906511a5cSPierre Jolivet   PetscFunctionBegin;
9006511a5cSPierre Jolivet   *M = Na->A;
9106511a5cSPierre Jolivet   PetscFunctionReturn(0);
9206511a5cSPierre Jolivet }
9306511a5cSPierre Jolivet 
9406511a5cSPierre Jolivet /*@
95*11a5261eSBarry Smith       MatHermitianTransposeGetMat - Gets the `Mat` object stored inside a `MATHERMITIANTRANSPOSE`
9606511a5cSPierre Jolivet 
9706511a5cSPierre Jolivet    Logically collective on Mat
9806511a5cSPierre Jolivet 
9906511a5cSPierre Jolivet    Input Parameter:
100*11a5261eSBarry Smith .   A  - the `MATHERMITIANTRANSPOSE` matrix
10106511a5cSPierre Jolivet 
10206511a5cSPierre Jolivet    Output Parameter:
10306511a5cSPierre Jolivet .   M - the matrix object stored inside A
10406511a5cSPierre Jolivet 
10506511a5cSPierre Jolivet    Level: intermediate
10606511a5cSPierre Jolivet 
107*11a5261eSBarry Smith .seealso: `MATHERMITIANTRANSPOSE`, `MatCreateHermitianTranspose()`
10806511a5cSPierre Jolivet @*/
1099371c9d4SSatish Balay PetscErrorCode MatHermitianTransposeGetMat(Mat A, Mat *M) {
11006511a5cSPierre Jolivet   PetscFunctionBegin;
11106511a5cSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11206511a5cSPierre Jolivet   PetscValidType(A, 1);
11306511a5cSPierre Jolivet   PetscValidPointer(M, 2);
114cac4c232SBarry Smith   PetscUseMethod(A, "MatHermitianTransposeGetMat_C", (Mat, Mat *), (A, M));
11506511a5cSPierre Jolivet   PetscFunctionReturn(0);
11606511a5cSPierre Jolivet }
11706511a5cSPierre Jolivet 
1186718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat);
1196718818eSStefano Zampini 
1209371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_HT(Mat A, Vec v) {
121a0eea678SPierre Jolivet   Mat_HT *Na = (Mat_HT *)A->data;
122a0eea678SPierre Jolivet 
123a0eea678SPierre Jolivet   PetscFunctionBegin;
1249566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(Na->A, v));
1259566063dSJacob Faibussowitsch   PetscCall(VecConjugate(v));
126a0eea678SPierre Jolivet   PetscFunctionReturn(0);
127a0eea678SPierre Jolivet }
128a0eea678SPierre Jolivet 
1299371c9d4SSatish Balay PetscErrorCode MatConvert_HT(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) {
130a0eea678SPierre Jolivet   Mat_HT   *Na = (Mat_HT *)A->data;
1316a4403aaSStefano Zampini   PetscBool flg;
132a0eea678SPierre Jolivet 
133a0eea678SPierre Jolivet   PetscFunctionBegin;
1349566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(Na->A, MATOP_HERMITIAN_TRANSPOSE, &flg));
1356a4403aaSStefano Zampini   if (flg) {
1366a4403aaSStefano Zampini     Mat B;
1376a4403aaSStefano Zampini 
1389566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(Na->A, MAT_INITIAL_MATRIX, &B));
139ff83db7bSPierre Jolivet     if (reuse != MAT_INPLACE_MATRIX) {
1409566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, reuse, newmat));
1419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B));
142ff83db7bSPierre Jolivet     } else {
1439566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B));
1449566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &B));
145ff83db7bSPierre Jolivet     }
1466a4403aaSStefano Zampini   } else { /* use basic converter as fallback */
1479566063dSJacob Faibussowitsch     PetscCall(MatConvert_Basic(A, newtype, reuse, newmat));
1486a4403aaSStefano Zampini   }
149a0eea678SPierre Jolivet   PetscFunctionReturn(0);
150a0eea678SPierre Jolivet }
151a0eea678SPierre Jolivet 
152*11a5261eSBarry Smith /*MC
153*11a5261eSBarry Smith    MATHERMITIANTRANSPOSE - "hermitiantranspose" - A matrix type that represents a virtual transpose of a matrix
154d0de2241SAndrew Spott 
155*11a5261eSBarry Smith   Level: advanced
156*11a5261eSBarry Smith 
157*11a5261eSBarry Smith .seealso: `MATTRANSPOSE`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`
158*11a5261eSBarry Smith M*/
159*11a5261eSBarry Smith 
160*11a5261eSBarry Smith /*@
161*11a5261eSBarry Smith       MatCreateHermitianTranspose - Creates a new matrix object of `MatType` `MATHERMITIANTRANSPOSE` that behaves like A'*
162*11a5261eSBarry Smith 
163*11a5261eSBarry Smith    Collective on A
164d0de2241SAndrew Spott 
165d0de2241SAndrew Spott    Input Parameter:
166d0de2241SAndrew Spott .   A  - the (possibly rectangular) matrix
167d0de2241SAndrew Spott 
168d0de2241SAndrew Spott    Output Parameter:
169d0de2241SAndrew Spott .   N - the matrix that represents A'*
170d0de2241SAndrew Spott 
171d0de2241SAndrew Spott    Level: intermediate
172d0de2241SAndrew Spott 
173*11a5261eSBarry Smith    Note:
174*11a5261eSBarry Smith     The Hermitian transpose A' is NOT actually formed! Rather the new matrix
175*11a5261eSBarry Smith           object performs the matrix-vector product, `MatMult()`, by using the `MatMultHermitianTranspose()` on
176d0de2241SAndrew Spott           the original matrix
177d0de2241SAndrew Spott 
178*11a5261eSBarry Smith .seealso: `MATHERMITIANTRANSPOSE`, `MatCreateNormal()`, `MatMult()`, `MatMultHermitianTranspose()`, `MatCreate()`
179d0de2241SAndrew Spott @*/
1809371c9d4SSatish Balay PetscErrorCode MatCreateHermitianTranspose(Mat A, Mat *N) {
181d0de2241SAndrew Spott   PetscInt m, n;
182fb41c00aSBarry Smith   Mat_HT  *Na;
183487d878eSStefano Zampini   VecType  vtype;
184d0de2241SAndrew Spott 
185d0de2241SAndrew Spott   PetscFunctionBegin;
1869566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
1879566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N));
1889566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N, n, m, PETSC_DECIDE, PETSC_DECIDE));
1899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->rmap));
1909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->cmap));
191*11a5261eSBarry Smith   PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATHERMITIANTRANSPOSE));
192d0de2241SAndrew Spott 
1939566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(*N, &Na));
194d0de2241SAndrew Spott   (*N)->data = (void *)Na;
1959566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
196d0de2241SAndrew Spott   Na->A = A;
197d0de2241SAndrew Spott 
198fb41c00aSBarry Smith   (*N)->ops->destroy                   = MatDestroy_HT;
199fb41c00aSBarry Smith   (*N)->ops->mult                      = MatMult_HT;
200fb41c00aSBarry Smith   (*N)->ops->multadd                   = MatMultAdd_HT;
201fb41c00aSBarry Smith   (*N)->ops->multhermitiantranspose    = MatMultHermitianTranspose_HT;
202fb41c00aSBarry Smith   (*N)->ops->multhermitiantransposeadd = MatMultHermitianTransposeAdd_HT;
2036048efd1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
2046048efd1SBarry Smith   (*N)->ops->multtranspose    = MatMultHermitianTranspose_HT;
2056048efd1SBarry Smith   (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_HT;
2066048efd1SBarry Smith #endif
207fb41c00aSBarry Smith   (*N)->ops->duplicate = MatDuplicate_HT;
20806511a5cSPierre Jolivet   (*N)->ops->getvecs   = MatCreateVecs_HT;
2096171f1c8SPierre Jolivet   (*N)->ops->axpy      = MatAXPY_HT;
2106718818eSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2116718818eSStefano Zampini   (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose;
2126718818eSStefano Zampini #endif
213a0eea678SPierre Jolivet   (*N)->ops->getdiagonal = MatGetDiagonal_HT;
214a0eea678SPierre Jolivet   (*N)->ops->convert     = MatConvert_HT;
215d0de2241SAndrew Spott   (*N)->assembled        = PETSC_TRUE;
216d0de2241SAndrew Spott 
2179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatHermitianTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
218204606b3SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
2209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose));
221204606b3SStefano Zampini #endif
2229566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs)));
2239566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A, &vtype));
2249566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N, vtype));
2252487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
2269566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N, A->boundtocpu));
2272487f3f2SStefano Zampini #endif
2289566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*N));
229d0de2241SAndrew Spott   PetscFunctionReturn(0);
230d0de2241SAndrew Spott }
231