xref: /petsc/src/mat/impls/transpose/htransm.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
8*9371c9d4SSatish 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 
16*9371c9d4SSatish 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 
24*9371c9d4SSatish 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 
32*9371c9d4SSatish 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 
40*9371c9d4SSatish 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 
54*9371c9d4SSatish 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 
67*9371c9d4SSatish 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 
75*9371c9d4SSatish 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 
86*9371c9d4SSatish 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 /*@
9506511a5cSPierre Jolivet       MatHermitianTransposeGetMat - Gets the Mat object stored inside a MATTRANSPOSEMAT
9606511a5cSPierre Jolivet 
9706511a5cSPierre Jolivet    Logically collective on Mat
9806511a5cSPierre Jolivet 
9906511a5cSPierre Jolivet    Input Parameter:
10006511a5cSPierre Jolivet .   A  - the MATTRANSPOSE matrix
10106511a5cSPierre Jolivet 
10206511a5cSPierre Jolivet    Output Parameter:
10306511a5cSPierre Jolivet .   M - the matrix object stored inside A
10406511a5cSPierre Jolivet 
10506511a5cSPierre Jolivet    Level: intermediate
10606511a5cSPierre Jolivet 
107db781477SPatrick Sanan .seealso: `MatCreateHermitianTranspose()`
10806511a5cSPierre Jolivet 
10906511a5cSPierre Jolivet @*/
110*9371c9d4SSatish Balay PetscErrorCode MatHermitianTransposeGetMat(Mat A, Mat *M) {
11106511a5cSPierre Jolivet   PetscFunctionBegin;
11206511a5cSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11306511a5cSPierre Jolivet   PetscValidType(A, 1);
11406511a5cSPierre Jolivet   PetscValidPointer(M, 2);
115cac4c232SBarry Smith   PetscUseMethod(A, "MatHermitianTransposeGetMat_C", (Mat, Mat *), (A, M));
11606511a5cSPierre Jolivet   PetscFunctionReturn(0);
11706511a5cSPierre Jolivet }
11806511a5cSPierre Jolivet 
1196718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat);
1206718818eSStefano Zampini 
121*9371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_HT(Mat A, Vec v) {
122a0eea678SPierre Jolivet   Mat_HT *Na = (Mat_HT *)A->data;
123a0eea678SPierre Jolivet 
124a0eea678SPierre Jolivet   PetscFunctionBegin;
1259566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(Na->A, v));
1269566063dSJacob Faibussowitsch   PetscCall(VecConjugate(v));
127a0eea678SPierre Jolivet   PetscFunctionReturn(0);
128a0eea678SPierre Jolivet }
129a0eea678SPierre Jolivet 
130*9371c9d4SSatish Balay PetscErrorCode MatConvert_HT(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) {
131a0eea678SPierre Jolivet   Mat_HT   *Na = (Mat_HT *)A->data;
1326a4403aaSStefano Zampini   PetscBool flg;
133a0eea678SPierre Jolivet 
134a0eea678SPierre Jolivet   PetscFunctionBegin;
1359566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(Na->A, MATOP_HERMITIAN_TRANSPOSE, &flg));
1366a4403aaSStefano Zampini   if (flg) {
1376a4403aaSStefano Zampini     Mat B;
1386a4403aaSStefano Zampini 
1399566063dSJacob Faibussowitsch     PetscCall(MatHermitianTranspose(Na->A, MAT_INITIAL_MATRIX, &B));
140ff83db7bSPierre Jolivet     if (reuse != MAT_INPLACE_MATRIX) {
1419566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, reuse, newmat));
1429566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B));
143ff83db7bSPierre Jolivet     } else {
1449566063dSJacob Faibussowitsch       PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B));
1459566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &B));
146ff83db7bSPierre Jolivet     }
1476a4403aaSStefano Zampini   } else { /* use basic converter as fallback */
1489566063dSJacob Faibussowitsch     PetscCall(MatConvert_Basic(A, newtype, reuse, newmat));
1496a4403aaSStefano Zampini   }
150a0eea678SPierre Jolivet   PetscFunctionReturn(0);
151a0eea678SPierre Jolivet }
152a0eea678SPierre Jolivet 
153d0de2241SAndrew Spott /*@
154d0de2241SAndrew Spott       MatCreateHermitianTranspose - Creates a new matrix object that behaves like A'*
155d0de2241SAndrew Spott 
156d0de2241SAndrew Spott    Collective on Mat
157d0de2241SAndrew Spott 
158d0de2241SAndrew Spott    Input Parameter:
159d0de2241SAndrew Spott .   A  - the (possibly rectangular) matrix
160d0de2241SAndrew Spott 
161d0de2241SAndrew Spott    Output Parameter:
162d0de2241SAndrew Spott .   N - the matrix that represents A'*
163d0de2241SAndrew Spott 
164d0de2241SAndrew Spott    Level: intermediate
165d0de2241SAndrew Spott 
16695452b02SPatrick Sanan    Notes:
16795452b02SPatrick Sanan     The hermitian transpose A' is NOT actually formed! Rather the new matrix
168d0de2241SAndrew Spott           object performs the matrix-vector product by using the MatMultHermitianTranspose() on
169d0de2241SAndrew Spott           the original matrix
170d0de2241SAndrew Spott 
171db781477SPatrick Sanan .seealso: `MatCreateNormal()`, `MatMult()`, `MatMultHermitianTranspose()`, `MatCreate()`
172d0de2241SAndrew Spott @*/
173*9371c9d4SSatish Balay PetscErrorCode MatCreateHermitianTranspose(Mat A, Mat *N) {
174d0de2241SAndrew Spott   PetscInt m, n;
175fb41c00aSBarry Smith   Mat_HT  *Na;
176487d878eSStefano Zampini   VecType  vtype;
177d0de2241SAndrew Spott 
178d0de2241SAndrew Spott   PetscFunctionBegin;
1799566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
1809566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N));
1819566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N, n, m, PETSC_DECIDE, PETSC_DECIDE));
1829566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->rmap));
1839566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp((*N)->cmap));
1849566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATTRANSPOSEMAT));
185d0de2241SAndrew Spott 
1869566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(*N, &Na));
187d0de2241SAndrew Spott   (*N)->data = (void *)Na;
1889566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
189d0de2241SAndrew Spott   Na->A = A;
190d0de2241SAndrew Spott 
191fb41c00aSBarry Smith   (*N)->ops->destroy                   = MatDestroy_HT;
192fb41c00aSBarry Smith   (*N)->ops->mult                      = MatMult_HT;
193fb41c00aSBarry Smith   (*N)->ops->multadd                   = MatMultAdd_HT;
194fb41c00aSBarry Smith   (*N)->ops->multhermitiantranspose    = MatMultHermitianTranspose_HT;
195fb41c00aSBarry Smith   (*N)->ops->multhermitiantransposeadd = MatMultHermitianTransposeAdd_HT;
1966048efd1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
1976048efd1SBarry Smith   (*N)->ops->multtranspose    = MatMultHermitianTranspose_HT;
1986048efd1SBarry Smith   (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_HT;
1996048efd1SBarry Smith #endif
200fb41c00aSBarry Smith   (*N)->ops->duplicate = MatDuplicate_HT;
20106511a5cSPierre Jolivet   (*N)->ops->getvecs   = MatCreateVecs_HT;
2026171f1c8SPierre Jolivet   (*N)->ops->axpy      = MatAXPY_HT;
2036718818eSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2046718818eSStefano Zampini   (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose;
2056718818eSStefano Zampini #endif
206a0eea678SPierre Jolivet   (*N)->ops->getdiagonal = MatGetDiagonal_HT;
207a0eea678SPierre Jolivet   (*N)->ops->convert     = MatConvert_HT;
208d0de2241SAndrew Spott   (*N)->assembled        = PETSC_TRUE;
209d0de2241SAndrew Spott 
2109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatHermitianTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
211204606b3SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatTransposeGetMat_C", MatHermitianTransposeGetMat_HT));
2139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose));
214204606b3SStefano Zampini #endif
2159566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs)));
2169566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A, &vtype));
2179566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N, vtype));
2182487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
2199566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N, A->boundtocpu));
2202487f3f2SStefano Zampini #endif
2219566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*N));
222d0de2241SAndrew Spott   PetscFunctionReturn(0);
223d0de2241SAndrew Spott }
224