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 8d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_Transpose(Mat N, Vec x, Vec y) 9d71ae5a4SJacob Faibussowitsch { 1085e3dda7SBarry Smith Mat_Transpose *Na = (Mat_Transpose *)N->data; 1185e3dda7SBarry Smith 1285e3dda7SBarry Smith PetscFunctionBegin; 139566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A, x, y)); 143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1585e3dda7SBarry Smith } 1685e3dda7SBarry Smith 17d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_Transpose(Mat N, Vec v1, Vec v2, Vec v3) 18d71ae5a4SJacob Faibussowitsch { 1985e3dda7SBarry Smith Mat_Transpose *Na = (Mat_Transpose *)N->data; 2085e3dda7SBarry Smith 2185e3dda7SBarry Smith PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, v1, v2, v3)); 233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2485e3dda7SBarry Smith } 2585e3dda7SBarry Smith 26d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_Transpose(Mat N, Vec x, Vec y) 27d71ae5a4SJacob Faibussowitsch { 2847a9afc9SBarry Smith Mat_Transpose *Na = (Mat_Transpose *)N->data; 2947a9afc9SBarry Smith 3047a9afc9SBarry Smith PetscFunctionBegin; 319566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A, x, y)); 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3347a9afc9SBarry Smith } 3447a9afc9SBarry Smith 35d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_Transpose(Mat N, Vec v1, Vec v2, Vec v3) 36d71ae5a4SJacob Faibussowitsch { 3747a9afc9SBarry Smith Mat_Transpose *Na = (Mat_Transpose *)N->data; 3847a9afc9SBarry Smith 3947a9afc9SBarry Smith PetscFunctionBegin; 409566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, v1, v2, v3)); 413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4247a9afc9SBarry Smith } 4347a9afc9SBarry Smith 44d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_Transpose(Mat N) 45d71ae5a4SJacob Faibussowitsch { 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)); 533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5485e3dda7SBarry Smith } 5585e3dda7SBarry Smith 56d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat *m) 57d71ae5a4SJacob Faibussowitsch { 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"); 673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68d0de2241SAndrew Spott } 69d0de2241SAndrew Spott 70d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateVecs_Transpose(Mat A, Vec *r, Vec *l) 71d71ae5a4SJacob Faibussowitsch { 72d9b48344SStefano Zampini Mat_Transpose *Aa = (Mat_Transpose *)A->data; 73d9b48344SStefano Zampini 74d9b48344SStefano Zampini PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Aa->A, l, r)); 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77d9b48344SStefano Zampini } 78d9b48344SStefano Zampini 79d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_Transpose(Mat Y, PetscScalar a, Mat X, MatStructure str) 80d71ae5a4SJacob Faibussowitsch { 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)); 883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 896171f1c8SPierre Jolivet } 906171f1c8SPierre Jolivet 91d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHasOperation_Transpose(Mat mat, MatOperation op, PetscBool *has) 92d71ae5a4SJacob Faibussowitsch { 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; 1063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10752c5f739Sprj- } 10852c5f739Sprj- 109d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D) 110d71ae5a4SJacob Faibussowitsch { 1116718818eSStefano Zampini Mat A, B, C, Ain, Bin, Cin; 1126718818eSStefano Zampini PetscBool Aistrans, Bistrans, Cistrans; 1136718818eSStefano Zampini PetscInt Atrans, Btrans, Ctrans; 1146718818eSStefano Zampini MatProductType ptype; 1156718818eSStefano Zampini 1166718818eSStefano Zampini PetscFunctionBegin; 1176718818eSStefano Zampini MatCheckProduct(D, 1); 1186718818eSStefano Zampini A = D->product->A; 1196718818eSStefano Zampini B = D->product->B; 1206718818eSStefano Zampini C = D->product->C; 121013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)A, MATTRANSPOSEVIRTUAL, &Aistrans)); 122013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)B, MATTRANSPOSEVIRTUAL, &Bistrans)); 123013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)C, MATTRANSPOSEVIRTUAL, &Cistrans)); 124aed4548fSBarry Smith PetscCheck(Aistrans || Bistrans || Cistrans, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "This should not happen"); 1256718818eSStefano Zampini Atrans = 0; 1266718818eSStefano Zampini Ain = A; 1276718818eSStefano Zampini while (Aistrans) { 1286718818eSStefano Zampini Atrans++; 1299566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Ain, &Ain)); 130013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Ain, MATTRANSPOSEVIRTUAL, &Aistrans)); 1316718818eSStefano Zampini } 1326718818eSStefano Zampini Btrans = 0; 1336718818eSStefano Zampini Bin = B; 1346718818eSStefano Zampini while (Bistrans) { 1356718818eSStefano Zampini Btrans++; 1369566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Bin, &Bin)); 137013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Bin, MATTRANSPOSEVIRTUAL, &Bistrans)); 1386718818eSStefano Zampini } 1396718818eSStefano Zampini Ctrans = 0; 1406718818eSStefano Zampini Cin = C; 1416718818eSStefano Zampini while (Cistrans) { 1426718818eSStefano Zampini Ctrans++; 1439566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Cin, &Cin)); 144013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)Cin, MATTRANSPOSEVIRTUAL, &Cistrans)); 1456718818eSStefano Zampini } 1466718818eSStefano Zampini Atrans = Atrans % 2; 1476718818eSStefano Zampini Btrans = Btrans % 2; 1486718818eSStefano Zampini Ctrans = Ctrans % 2; 1496718818eSStefano Zampini ptype = D->product->type; /* same product type by default */ 150b94d7dedSBarry Smith if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0; 151b94d7dedSBarry Smith if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0; 152b94d7dedSBarry Smith if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0; 1536718818eSStefano Zampini 1546718818eSStefano Zampini if (Atrans || Btrans || Ctrans) { 1556718818eSStefano Zampini ptype = MATPRODUCT_UNSPECIFIED; 1566718818eSStefano Zampini switch (D->product->type) { 1576718818eSStefano Zampini case MATPRODUCT_AB: 1586718818eSStefano Zampini if (Atrans && Btrans) { /* At * Bt we do not have support for this */ 1596718818eSStefano Zampini /* TODO custom implementation ? */ 1606718818eSStefano Zampini } else if (Atrans) { /* At * B */ 1616718818eSStefano Zampini ptype = MATPRODUCT_AtB; 1626718818eSStefano Zampini } else { /* A * Bt */ 1636718818eSStefano Zampini ptype = MATPRODUCT_ABt; 1646718818eSStefano Zampini } 1656718818eSStefano Zampini break; 1666718818eSStefano Zampini case MATPRODUCT_AtB: 1676718818eSStefano Zampini if (Atrans && Btrans) { /* A * Bt */ 1686718818eSStefano Zampini ptype = MATPRODUCT_ABt; 1696718818eSStefano Zampini } else if (Atrans) { /* A * B */ 1706718818eSStefano Zampini ptype = MATPRODUCT_AB; 1716718818eSStefano Zampini } else { /* At * Bt we do not have support for this */ 1726718818eSStefano Zampini /* TODO custom implementation ? */ 1736718818eSStefano Zampini } 1746718818eSStefano Zampini break; 1756718818eSStefano Zampini case MATPRODUCT_ABt: 1766718818eSStefano Zampini if (Atrans && Btrans) { /* At * B */ 1776718818eSStefano Zampini ptype = MATPRODUCT_AtB; 1786718818eSStefano Zampini } else if (Atrans) { /* At * Bt we do not have support for this */ 1796718818eSStefano Zampini /* TODO custom implementation ? */ 1806718818eSStefano Zampini } else { /* A * B */ 1816718818eSStefano Zampini ptype = MATPRODUCT_AB; 1826718818eSStefano Zampini } 1836718818eSStefano Zampini break; 1846718818eSStefano Zampini case MATPRODUCT_PtAP: 1856718818eSStefano Zampini if (Atrans) { /* PtAtP */ 1866718818eSStefano Zampini /* TODO custom implementation ? */ 1876718818eSStefano Zampini } else { /* RARt */ 1886718818eSStefano Zampini ptype = MATPRODUCT_RARt; 1896718818eSStefano Zampini } 1906718818eSStefano Zampini break; 1916718818eSStefano Zampini case MATPRODUCT_RARt: 1926718818eSStefano Zampini if (Atrans) { /* RAtRt */ 1936718818eSStefano Zampini /* TODO custom implementation ? */ 1946718818eSStefano Zampini } else { /* PtAP */ 1956718818eSStefano Zampini ptype = MATPRODUCT_PtAP; 1966718818eSStefano Zampini } 1976718818eSStefano Zampini break; 1986718818eSStefano Zampini case MATPRODUCT_ABC: 1996718818eSStefano Zampini /* TODO custom implementation ? */ 2006718818eSStefano Zampini break; 201d71ae5a4SJacob Faibussowitsch default: 202d71ae5a4SJacob Faibussowitsch 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)); 2083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2096718818eSStefano Zampini } 2106718818eSStefano Zampini 211d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_Transpose(Mat A, Vec v) 212d71ae5a4SJacob Faibussowitsch { 213a0eea678SPierre Jolivet Mat_Transpose *Aa = (Mat_Transpose *)A->data; 214a0eea678SPierre Jolivet 215a0eea678SPierre Jolivet PetscFunctionBegin; 2169566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Aa->A, v)); 2173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218a0eea678SPierre Jolivet } 219a0eea678SPierre Jolivet 220d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_Transpose(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 221d71ae5a4SJacob Faibussowitsch { 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 } 2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 242a0eea678SPierre Jolivet } 243a0eea678SPierre Jolivet 244d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeGetMat_Transpose(Mat A, Mat *M) 245d71ae5a4SJacob Faibussowitsch { 2468060fb66Sstefano_zampini Mat_Transpose *Aa = (Mat_Transpose *)A->data; 2478060fb66Sstefano_zampini 2488060fb66Sstefano_zampini PetscFunctionBegin; 2498060fb66Sstefano_zampini *M = Aa->A; 2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2518060fb66Sstefano_zampini } 2528060fb66Sstefano_zampini 2538060fb66Sstefano_zampini /*@ 254013e2dc7SBarry Smith MatTransposeGetMat - Gets the `Mat` object stored inside a `MATTRANSPOSEVIRTUAL` 2558060fb66Sstefano_zampini 25620f4b53cSBarry Smith Logically Collective 2578060fb66Sstefano_zampini 2588060fb66Sstefano_zampini Input Parameter: 259013e2dc7SBarry Smith . A - the `MATTRANSPOSEVIRTUAL` matrix 2608060fb66Sstefano_zampini 2618060fb66Sstefano_zampini Output Parameter: 2622ef1f0ffSBarry Smith . M - the matrix object stored inside `A` 2638060fb66Sstefano_zampini 2648060fb66Sstefano_zampini Level: intermediate 2658060fb66Sstefano_zampini 266*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateTranspose()` 2678060fb66Sstefano_zampini @*/ 268d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeGetMat(Mat A, Mat *M) 269d71ae5a4SJacob Faibussowitsch { 2708060fb66Sstefano_zampini PetscFunctionBegin; 2718060fb66Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2728060fb66Sstefano_zampini PetscValidType(A, 1); 2738060fb66Sstefano_zampini PetscValidPointer(M, 2); 274cac4c232SBarry Smith PetscUseMethod(A, "MatTransposeGetMat_C", (Mat, Mat *), (A, M)); 2753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2768060fb66Sstefano_zampini } 277d0de2241SAndrew Spott 27811a5261eSBarry Smith /*MC 279013e2dc7SBarry Smith MATTRANSPOSEVIRTUAL - "transpose" - A matrix type that represents a virtual transpose of a matrix 28085e3dda7SBarry Smith 28111a5261eSBarry Smith Level: advanced 28211a5261eSBarry Smith 283*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATHERMITIANTRANSPOSEVIRTUAL`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`, 2842ef1f0ffSBarry Smith `MATNORMALHERMITIAN`, `MATNORMAL` 28511a5261eSBarry Smith M*/ 28611a5261eSBarry Smith 28711a5261eSBarry Smith /*@ 288013e2dc7SBarry Smith MatCreateTranspose - Creates a new matrix `MATTRANSPOSEVIRTUAL` object that behaves like A' 28911a5261eSBarry Smith 290c3339decSBarry Smith Collective 29185e3dda7SBarry Smith 29285e3dda7SBarry Smith Input Parameter: 29385e3dda7SBarry Smith . A - the (possibly rectangular) matrix 29485e3dda7SBarry Smith 29585e3dda7SBarry Smith Output Parameter: 29685e3dda7SBarry Smith . N - the matrix that represents A' 29785e3dda7SBarry Smith 29885e3dda7SBarry Smith Level: intermediate 29985e3dda7SBarry Smith 30011a5261eSBarry Smith Note: 30195452b02SPatrick Sanan The transpose A' is NOT actually formed! Rather the new matrix 30211a5261eSBarry Smith object performs the matrix-vector product by using the `MatMultTranspose()` on 30385e3dda7SBarry Smith the original matrix 30485e3dda7SBarry Smith 305*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateNormal()`, `MatMult()`, `MatMultTranspose()`, `MatCreate()`, 3062ef1f0ffSBarry Smith `MATNORMALHERMITIAN` 30785e3dda7SBarry Smith @*/ 308d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateTranspose(Mat A, Mat *N) 309d71ae5a4SJacob Faibussowitsch { 31085e3dda7SBarry Smith PetscInt m, n; 31185e3dda7SBarry Smith Mat_Transpose *Na; 312487d878eSStefano Zampini VecType vtype; 31385e3dda7SBarry Smith 31485e3dda7SBarry Smith PetscFunctionBegin; 3159566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 3169566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N)); 3179566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*N, n, m, PETSC_DECIDE, PETSC_DECIDE)); 3189566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*N)->rmap)); 3199566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*N)->cmap)); 320013e2dc7SBarry Smith PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATTRANSPOSEVIRTUAL)); 32185e3dda7SBarry Smith 3224dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&Na)); 32385e3dda7SBarry Smith (*N)->data = (void *)Na; 3249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 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 3419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatTransposeGetMat_C", MatTransposeGetMat_Transpose)); 3429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N), "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose)); 3439566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs))); 3449566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A, &vtype)); 3459566063dSJacob Faibussowitsch PetscCall(MatSetVecType(*N, vtype)); 3462487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 3479566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*N, A->boundtocpu)); 3482487f3f2SStefano Zampini #endif 3499566063dSJacob Faibussowitsch PetscCall(MatSetUp(*N)); 3503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35185e3dda7SBarry Smith } 352