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 1285e3dda7SBarry Smith PetscFunctionBegin; 139566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A,x,y)); 1485e3dda7SBarry Smith PetscFunctionReturn(0); 1585e3dda7SBarry Smith } 1685e3dda7SBarry Smith 1785e3dda7SBarry Smith PetscErrorCode MatMultAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3) 1885e3dda7SBarry Smith { 1985e3dda7SBarry Smith Mat_Transpose *Na = (Mat_Transpose*)N->data; 2085e3dda7SBarry Smith 2185e3dda7SBarry Smith PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A,v1,v2,v3)); 2385e3dda7SBarry Smith PetscFunctionReturn(0); 2485e3dda7SBarry Smith } 2585e3dda7SBarry Smith 2647a9afc9SBarry Smith PetscErrorCode MatMultTranspose_Transpose(Mat N,Vec x,Vec y) 2747a9afc9SBarry Smith { 2847a9afc9SBarry Smith Mat_Transpose *Na = (Mat_Transpose*)N->data; 2947a9afc9SBarry Smith 3047a9afc9SBarry Smith PetscFunctionBegin; 319566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A,x,y)); 3247a9afc9SBarry Smith PetscFunctionReturn(0); 3347a9afc9SBarry Smith } 3447a9afc9SBarry Smith 3547a9afc9SBarry Smith PetscErrorCode MatMultTransposeAdd_Transpose(Mat N,Vec v1,Vec v2,Vec v3) 3647a9afc9SBarry Smith { 3747a9afc9SBarry Smith Mat_Transpose *Na = (Mat_Transpose*)N->data; 3847a9afc9SBarry Smith 3947a9afc9SBarry Smith PetscFunctionBegin; 409566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A,v1,v2,v3)); 4147a9afc9SBarry Smith PetscFunctionReturn(0); 4247a9afc9SBarry Smith } 4347a9afc9SBarry Smith 4485e3dda7SBarry Smith PetscErrorCode MatDestroy_Transpose(Mat N) 4585e3dda7SBarry Smith { 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)); 5385e3dda7SBarry Smith PetscFunctionReturn(0); 5485e3dda7SBarry Smith } 5585e3dda7SBarry Smith 56d0de2241SAndrew Spott PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat* m) 57d0de2241SAndrew Spott { 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"); 67d0de2241SAndrew Spott PetscFunctionReturn(0); 68d0de2241SAndrew Spott } 69d0de2241SAndrew Spott 70d9b48344SStefano Zampini PetscErrorCode MatCreateVecs_Transpose(Mat A,Vec *r, Vec *l) 71d9b48344SStefano Zampini { 72d9b48344SStefano Zampini Mat_Transpose *Aa = (Mat_Transpose*)A->data; 73d9b48344SStefano Zampini 74d9b48344SStefano Zampini PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Aa->A,l,r)); 76d9b48344SStefano Zampini PetscFunctionReturn(0); 77d9b48344SStefano Zampini } 78d9b48344SStefano Zampini 796171f1c8SPierre Jolivet PetscErrorCode MatAXPY_Transpose(Mat Y,PetscScalar a,Mat X,MatStructure str) 806171f1c8SPierre Jolivet { 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)); 886171f1c8SPierre Jolivet PetscFunctionReturn(0); 896171f1c8SPierre Jolivet } 906171f1c8SPierre Jolivet 9152c5f739Sprj- PetscErrorCode MatHasOperation_Transpose(Mat mat,MatOperation op,PetscBool *has) 9252c5f739Sprj- { 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; 10652c5f739Sprj- PetscFunctionReturn(0); 10752c5f739Sprj- } 10852c5f739Sprj- 1096718818eSStefano Zampini /* used by hermitian transpose */ 1106718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Transpose(Mat D) 1116718818eSStefano Zampini { 1126718818eSStefano Zampini Mat A,B,C,Ain,Bin,Cin; 1136718818eSStefano Zampini PetscBool Aistrans,Bistrans,Cistrans; 1146718818eSStefano Zampini PetscInt Atrans,Btrans,Ctrans; 1156718818eSStefano Zampini MatProductType ptype; 1166718818eSStefano Zampini 1176718818eSStefano Zampini PetscFunctionBegin; 1186718818eSStefano Zampini MatCheckProduct(D,1); 1196718818eSStefano Zampini A = D->product->A; 1206718818eSStefano Zampini B = D->product->B; 1216718818eSStefano Zampini C = D->product->C; 1229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&Aistrans)); 1239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&Bistrans)); 1249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)C,MATTRANSPOSEMAT,&Cistrans)); 125aed4548fSBarry Smith PetscCheck(Aistrans || Bistrans || Cistrans,PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"This should not happen"); 1266718818eSStefano Zampini Atrans = 0; 1276718818eSStefano Zampini Ain = A; 1286718818eSStefano Zampini while (Aistrans) { 1296718818eSStefano Zampini Atrans++; 1309566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Ain,&Ain)); 1319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)Ain,MATTRANSPOSEMAT,&Aistrans)); 1326718818eSStefano Zampini } 1336718818eSStefano Zampini Btrans = 0; 1346718818eSStefano Zampini Bin = B; 1356718818eSStefano Zampini while (Bistrans) { 1366718818eSStefano Zampini Btrans++; 1379566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Bin,&Bin)); 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)Bin,MATTRANSPOSEMAT,&Bistrans)); 1396718818eSStefano Zampini } 1406718818eSStefano Zampini Ctrans = 0; 1416718818eSStefano Zampini Cin = C; 1426718818eSStefano Zampini while (Cistrans) { 1436718818eSStefano Zampini Ctrans++; 1449566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(Cin,&Cin)); 1459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)Cin,MATTRANSPOSEMAT,&Cistrans)); 1466718818eSStefano Zampini } 1476718818eSStefano Zampini Atrans = Atrans%2; 1486718818eSStefano Zampini Btrans = Btrans%2; 1496718818eSStefano Zampini Ctrans = Ctrans%2; 1506718818eSStefano Zampini ptype = D->product->type; /* same product type by default */ 151*b94d7dedSBarry Smith if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0; 152*b94d7dedSBarry Smith if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0; 153*b94d7dedSBarry Smith if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0; 1546718818eSStefano Zampini 1556718818eSStefano Zampini if (Atrans || Btrans || Ctrans) { 1566718818eSStefano Zampini ptype = MATPRODUCT_UNSPECIFIED; 1576718818eSStefano Zampini switch (D->product->type) { 1586718818eSStefano Zampini case MATPRODUCT_AB: 1596718818eSStefano Zampini if (Atrans && Btrans) { /* At * Bt we do not have support for this */ 1606718818eSStefano Zampini /* TODO custom implementation ? */ 1616718818eSStefano Zampini } else if (Atrans) { /* At * B */ 1626718818eSStefano Zampini ptype = MATPRODUCT_AtB; 1636718818eSStefano Zampini } else { /* A * Bt */ 1646718818eSStefano Zampini ptype = MATPRODUCT_ABt; 1656718818eSStefano Zampini } 1666718818eSStefano Zampini break; 1676718818eSStefano Zampini case MATPRODUCT_AtB: 1686718818eSStefano Zampini if (Atrans && Btrans) { /* A * Bt */ 1696718818eSStefano Zampini ptype = MATPRODUCT_ABt; 1706718818eSStefano Zampini } else if (Atrans) { /* A * B */ 1716718818eSStefano Zampini ptype = MATPRODUCT_AB; 1726718818eSStefano Zampini } else { /* At * Bt we do not have support for this */ 1736718818eSStefano Zampini /* TODO custom implementation ? */ 1746718818eSStefano Zampini } 1756718818eSStefano Zampini break; 1766718818eSStefano Zampini case MATPRODUCT_ABt: 1776718818eSStefano Zampini if (Atrans && Btrans) { /* At * B */ 1786718818eSStefano Zampini ptype = MATPRODUCT_AtB; 1796718818eSStefano Zampini } else if (Atrans) { /* At * Bt we do not have support for this */ 1806718818eSStefano Zampini /* TODO custom implementation ? */ 1816718818eSStefano Zampini } else { /* A * B */ 1826718818eSStefano Zampini ptype = MATPRODUCT_AB; 1836718818eSStefano Zampini } 1846718818eSStefano Zampini break; 1856718818eSStefano Zampini case MATPRODUCT_PtAP: 1866718818eSStefano Zampini if (Atrans) { /* PtAtP */ 1876718818eSStefano Zampini /* TODO custom implementation ? */ 1886718818eSStefano Zampini } else { /* RARt */ 1896718818eSStefano Zampini ptype = MATPRODUCT_RARt; 1906718818eSStefano Zampini } 1916718818eSStefano Zampini break; 1926718818eSStefano Zampini case MATPRODUCT_RARt: 1936718818eSStefano Zampini if (Atrans) { /* RAtRt */ 1946718818eSStefano Zampini /* TODO custom implementation ? */ 1956718818eSStefano Zampini } else { /* PtAP */ 1966718818eSStefano Zampini ptype = MATPRODUCT_PtAP; 1976718818eSStefano Zampini } 1986718818eSStefano Zampini break; 1996718818eSStefano Zampini case MATPRODUCT_ABC: 2006718818eSStefano Zampini /* TODO custom implementation ? */ 2016718818eSStefano Zampini break; 20298921bdaSJacob Faibussowitsch default: 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)); 2086718818eSStefano Zampini PetscFunctionReturn(0); 2096718818eSStefano Zampini } 2106718818eSStefano Zampini 211a0eea678SPierre Jolivet PetscErrorCode MatGetDiagonal_Transpose(Mat A,Vec v) 212a0eea678SPierre Jolivet { 213a0eea678SPierre Jolivet Mat_Transpose *Aa = (Mat_Transpose*)A->data; 214a0eea678SPierre Jolivet 215a0eea678SPierre Jolivet PetscFunctionBegin; 2169566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Aa->A,v)); 217a0eea678SPierre Jolivet PetscFunctionReturn(0); 218a0eea678SPierre Jolivet } 219a0eea678SPierre Jolivet 220a0eea678SPierre Jolivet PetscErrorCode MatConvert_Transpose(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 221a0eea678SPierre Jolivet { 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 } 241a0eea678SPierre Jolivet PetscFunctionReturn(0); 242a0eea678SPierre Jolivet } 243a0eea678SPierre Jolivet 2448060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat_Transpose(Mat A,Mat *M) 2458060fb66Sstefano_zampini { 2468060fb66Sstefano_zampini Mat_Transpose *Aa = (Mat_Transpose*)A->data; 2478060fb66Sstefano_zampini 2488060fb66Sstefano_zampini PetscFunctionBegin; 2498060fb66Sstefano_zampini *M = Aa->A; 2508060fb66Sstefano_zampini PetscFunctionReturn(0); 2518060fb66Sstefano_zampini } 2528060fb66Sstefano_zampini 2538060fb66Sstefano_zampini /*@ 25406511a5cSPierre Jolivet MatTransposeGetMat - Gets the Mat object stored inside a MATTRANSPOSEMAT 2558060fb66Sstefano_zampini 2568060fb66Sstefano_zampini Logically collective on Mat 2578060fb66Sstefano_zampini 2588060fb66Sstefano_zampini Input Parameter: 2598060fb66Sstefano_zampini . A - the MATTRANSPOSE matrix 2608060fb66Sstefano_zampini 2618060fb66Sstefano_zampini Output Parameter: 2628060fb66Sstefano_zampini . M - the matrix object stored inside A 2638060fb66Sstefano_zampini 2648060fb66Sstefano_zampini Level: intermediate 2658060fb66Sstefano_zampini 266db781477SPatrick Sanan .seealso: `MatCreateTranspose()` 2678060fb66Sstefano_zampini 2688060fb66Sstefano_zampini @*/ 2698060fb66Sstefano_zampini PetscErrorCode MatTransposeGetMat(Mat A,Mat *M) 2708060fb66Sstefano_zampini { 2718060fb66Sstefano_zampini PetscFunctionBegin; 2728060fb66Sstefano_zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 2738060fb66Sstefano_zampini PetscValidType(A,1); 2748060fb66Sstefano_zampini PetscValidPointer(M,2); 275cac4c232SBarry Smith PetscUseMethod(A,"MatTransposeGetMat_C",(Mat,Mat*),(A,M)); 2768060fb66Sstefano_zampini PetscFunctionReturn(0); 2778060fb66Sstefano_zampini } 278d0de2241SAndrew Spott 27985e3dda7SBarry Smith /*@ 28085e3dda7SBarry Smith MatCreateTranspose - Creates a new matrix object that behaves like A' 28185e3dda7SBarry Smith 28285e3dda7SBarry Smith Collective on Mat 28385e3dda7SBarry Smith 28485e3dda7SBarry Smith Input Parameter: 28585e3dda7SBarry Smith . A - the (possibly rectangular) matrix 28685e3dda7SBarry Smith 28785e3dda7SBarry Smith Output Parameter: 28885e3dda7SBarry Smith . N - the matrix that represents A' 28985e3dda7SBarry Smith 29085e3dda7SBarry Smith Level: intermediate 29185e3dda7SBarry Smith 29295452b02SPatrick Sanan Notes: 29395452b02SPatrick Sanan The transpose A' is NOT actually formed! Rather the new matrix 29485e3dda7SBarry Smith object performs the matrix-vector product by using the MatMultTranspose() on 29585e3dda7SBarry Smith the original matrix 29685e3dda7SBarry Smith 297db781477SPatrick Sanan .seealso: `MatCreateNormal()`, `MatMult()`, `MatMultTranspose()`, `MatCreate()` 29885e3dda7SBarry Smith 29985e3dda7SBarry Smith @*/ 3007087cfbeSBarry Smith PetscErrorCode MatCreateTranspose(Mat A,Mat *N) 30185e3dda7SBarry Smith { 30285e3dda7SBarry Smith PetscInt m,n; 30385e3dda7SBarry Smith Mat_Transpose *Na; 304487d878eSStefano Zampini VecType vtype; 30585e3dda7SBarry Smith 30685e3dda7SBarry Smith PetscFunctionBegin; 3079566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 3089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),N)); 3099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*N,n,m,PETSC_DECIDE,PETSC_DECIDE)); 3109566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*N)->rmap)); 3119566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*N)->cmap)); 3129566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*N,MATTRANSPOSEMAT)); 31385e3dda7SBarry Smith 3149566063dSJacob Faibussowitsch PetscCall(PetscNewLog(*N,&Na)); 31585e3dda7SBarry Smith (*N)->data = (void*) Na; 3169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 31785e3dda7SBarry Smith Na->A = A; 31885e3dda7SBarry Smith 31985e3dda7SBarry Smith (*N)->ops->destroy = MatDestroy_Transpose; 32085e3dda7SBarry Smith (*N)->ops->mult = MatMult_Transpose; 3216d12b599SJed Brown (*N)->ops->multadd = MatMultAdd_Transpose; 32247a9afc9SBarry Smith (*N)->ops->multtranspose = MatMultTranspose_Transpose; 32347a9afc9SBarry Smith (*N)->ops->multtransposeadd = MatMultTransposeAdd_Transpose; 324d0de2241SAndrew Spott (*N)->ops->duplicate = MatDuplicate_Transpose; 325d9b48344SStefano Zampini (*N)->ops->getvecs = MatCreateVecs_Transpose; 3266171f1c8SPierre Jolivet (*N)->ops->axpy = MatAXPY_Transpose; 32752c5f739Sprj- (*N)->ops->hasoperation = MatHasOperation_Transpose; 3286718818eSStefano Zampini (*N)->ops->productsetfromoptions = MatProductSetFromOptions_Transpose; 329a0eea678SPierre Jolivet (*N)->ops->getdiagonal = MatGetDiagonal_Transpose; 330a0eea678SPierre Jolivet (*N)->ops->convert = MatConvert_Transpose; 33185e3dda7SBarry Smith (*N)->assembled = PETSC_TRUE; 33285e3dda7SBarry Smith 3339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatTransposeGetMat_C",MatTransposeGetMat_Transpose)); 3349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_anytype_C",MatProductSetFromOptions_Transpose)); 3359566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*N,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs))); 3369566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A,&vtype)); 3379566063dSJacob Faibussowitsch PetscCall(MatSetVecType(*N,vtype)); 3382487f3f2SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 3399566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*N,A->boundtocpu)); 3402487f3f2SStefano Zampini #endif 3419566063dSJacob Faibussowitsch PetscCall(MatSetUp(*N)); 34285e3dda7SBarry Smith PetscFunctionReturn(0); 34385e3dda7SBarry Smith } 344