1c4762a1bSJed Brown static char help[] = "Tests the use of MatTranspose_Nest and MatMatMult_Nest_Dense\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscmat.h> 4c4762a1bSJed Brown 5c4762a1bSJed Brown PetscErrorCode TestInitialMatrix(void) 6c4762a1bSJed Brown { 7c4762a1bSJed Brown const PetscInt nr = 2,nc = 3,nk = 10; 8c4762a1bSJed Brown PetscInt n,N,m,M; 9c4762a1bSJed Brown const PetscInt arow[2*3] = { 2,2,2,3,3,3 }; 10c4762a1bSJed Brown const PetscInt acol[2*3] = { 3,2,4,3,2,4 }; 11c4762a1bSJed Brown Mat A,Atranspose,B,C; 12c4762a1bSJed Brown Mat subs[2*3],**block; 13c4762a1bSJed Brown Vec x,y,Ax,ATy; 14c4762a1bSJed Brown PetscInt i,j; 15c20d7725SJed Brown PetscScalar dot1,dot2,zero = 0.0,one = 1.0,*valsB,*valsC; 16c4762a1bSJed Brown PetscReal norm; 17c4762a1bSJed Brown PetscRandom rctx; 18c20d7725SJed Brown PetscBool equal; 19c4762a1bSJed Brown 20c4762a1bSJed Brown PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,&rctx)); 22c4762a1bSJed Brown /* Force the random numbers to have imaginary part 0 so printed results are the same for --with-scalar-type=real or --with-scalar-type=complex */ 239566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rctx,zero,one)); 249566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rctx)); 25c4762a1bSJed Brown for (i=0; i<(nr * nc); i++) { 269566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,arow[i],acol[i],NULL,&subs[i])); 27c4762a1bSJed Brown } 289566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_WORLD,nr,NULL,nc,NULL,subs,&A)); 299566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &x, NULL)); 309566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &y)); 319566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &ATy)); 329566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &Ax)); 339566063dSJacob Faibussowitsch PetscCall(MatSetRandom(A,rctx)); 349566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &Atranspose)); 35c4762a1bSJed Brown 369566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 379566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 38c4762a1bSJed Brown for (i=0; i<nr; i++) { 39c4762a1bSJed Brown for (j=0; j<nc; j++) { 409566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 41c4762a1bSJed Brown } 42c4762a1bSJed Brown } 43c4762a1bSJed Brown 449566063dSJacob Faibussowitsch PetscCall(MatView(Atranspose, PETSC_VIEWER_STDOUT_WORLD)); 459566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(Atranspose, NULL, NULL, &block)); 46c4762a1bSJed Brown for (i=0; i<nc; i++) { 47c4762a1bSJed Brown for (j=0; j<nr; j++) { 489566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 49c4762a1bSJed Brown } 50c4762a1bSJed Brown } 51c4762a1bSJed Brown 52c4762a1bSJed Brown /* Check <Ax, y> = <x, A^Ty> */ 53c4762a1bSJed Brown for (i=0; i<10; i++) { 549566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x,rctx)); 559566063dSJacob Faibussowitsch PetscCall(VecSetRandom(y,rctx)); 56c4762a1bSJed Brown 579566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, Ax)); 589566063dSJacob Faibussowitsch PetscCall(VecDot(Ax, y, &dot1)); 599566063dSJacob Faibussowitsch PetscCall(MatMult(Atranspose, y, ATy)); 609566063dSJacob Faibussowitsch PetscCall(VecDot(ATy, x, &dot2)); 61c4762a1bSJed Brown 629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "<Ax, y> = %g\n", (double)PetscRealPart(dot1))); 639566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "<x, A^Ty> = %g\n",(double)PetscRealPart(dot2))); 64c4762a1bSJed Brown } 659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Ax)); 68c4762a1bSJed Brown 699566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,acol[0]+acol[nr]+acol[2*nr],nk,NULL,&B)); 709566063dSJacob Faibussowitsch PetscCall(MatSetRandom(B,rctx)); 719566063dSJacob Faibussowitsch PetscCall(MatMatMult(A,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&C)); 729566063dSJacob Faibussowitsch PetscCall(MatMatMult(A,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&C)); 739566063dSJacob Faibussowitsch PetscCall(MatMatMultEqual(A,B,C,10,&equal)); 7428b400f6SJacob Faibussowitsch PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Error in C != A*B"); 75c20d7725SJed Brown 769566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 779566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 78c4762a1bSJed Brown for (i=0; i<nk; i++) { 799566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(B,i,&valsB)); 809566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,n,N,valsB,&x)); 819566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,NULL,&Ax)); 829566063dSJacob Faibussowitsch PetscCall(MatMult(A,x,Ax)); 839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 849566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(C,i,&valsC)); 859566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,m,M,valsC,&y)); 869566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,-1.0,Ax)); 879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Ax)); 889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 899566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(C,&valsC)); 909566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(B,&valsB)); 91c4762a1bSJed Brown } 929566063dSJacob Faibussowitsch PetscCall(MatNorm(C,NORM_INFINITY,&norm)); 93*08401ef6SPierre Jolivet PetscCheck(norm <= PETSC_SMALL,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Error in MatMatMult(): %g",(double)norm); 949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 96c4762a1bSJed Brown 97c4762a1bSJed Brown for (i=0; i<(nr * nc); i++) { 989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subs[i])); 99c4762a1bSJed Brown } 1009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 1019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Atranspose)); 1029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ATy)); 1039566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rctx)); 104c4762a1bSJed Brown PetscFunctionReturn(0); 105c4762a1bSJed Brown } 106c4762a1bSJed Brown 107c4762a1bSJed Brown PetscErrorCode TestReuseMatrix(void) 108c4762a1bSJed Brown { 109c4762a1bSJed Brown const PetscInt n = 2; 110c4762a1bSJed Brown Mat A; 111c4762a1bSJed Brown Mat subs[2*2],**block; 112c4762a1bSJed Brown PetscInt i,j; 113c4762a1bSJed Brown PetscRandom rctx; 114c4762a1bSJed Brown PetscScalar zero = 0.0, one = 1.0; 115c4762a1bSJed Brown 116c4762a1bSJed Brown PetscFunctionBegin; 1179566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,&rctx)); 1189566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rctx,zero,one)); 1199566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rctx)); 120c4762a1bSJed Brown for (i=0; i<(n * n); i++) { 1219566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,n,n,NULL,&subs[i])); 122c4762a1bSJed Brown } 1239566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_WORLD,n,NULL,n,NULL,subs,&A)); 1249566063dSJacob Faibussowitsch PetscCall(MatSetRandom(A,rctx)); 125c4762a1bSJed Brown 1269566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 1279566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 128c4762a1bSJed Brown for (i=0; i<n; i++) { 129c4762a1bSJed Brown for (j=0; j<n; j++) { 1309566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 131c4762a1bSJed Brown } 132c4762a1bSJed Brown } 1339566063dSJacob Faibussowitsch PetscCall(MatTranspose(A,MAT_INPLACE_MATRIX,&A)); 1349566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 1359566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 136c4762a1bSJed Brown for (i=0; i<n; i++) { 137c4762a1bSJed Brown for (j=0; j<n; j++) { 1389566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 139c4762a1bSJed Brown } 140c4762a1bSJed Brown } 141c4762a1bSJed Brown 142c4762a1bSJed Brown for (i=0; i<(n * n); i++) { 1439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subs[i])); 144c4762a1bSJed Brown } 1459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 1469566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rctx)); 147c4762a1bSJed Brown PetscFunctionReturn(0); 148c4762a1bSJed Brown } 149c4762a1bSJed Brown 150c4762a1bSJed Brown int main(int argc,char **args) 151c4762a1bSJed Brown { 152c4762a1bSJed Brown 1539566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&args,(char*)0,help)); 1549566063dSJacob Faibussowitsch PetscCall(TestInitialMatrix()); 1559566063dSJacob Faibussowitsch PetscCall(TestReuseMatrix()); 1569566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 157b122ec5aSJacob Faibussowitsch return 0; 158c4762a1bSJed Brown } 159c4762a1bSJed Brown 160c4762a1bSJed Brown /*TEST 161c4762a1bSJed Brown 162c4762a1bSJed Brown test: 163c4762a1bSJed Brown args: -malloc_dump 164c4762a1bSJed Brown 165c4762a1bSJed Brown TEST*/ 166