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; 21*9566063dSJacob 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 */ 23*9566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rctx,zero,one)); 24*9566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rctx)); 25c4762a1bSJed Brown for (i=0; i<(nr * nc); i++) { 26*9566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,arow[i],acol[i],NULL,&subs[i])); 27c4762a1bSJed Brown } 28*9566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_WORLD,nr,NULL,nc,NULL,subs,&A)); 29*9566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &x, NULL)); 30*9566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &y)); 31*9566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &ATy)); 32*9566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &Ax)); 33*9566063dSJacob Faibussowitsch PetscCall(MatSetRandom(A,rctx)); 34*9566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &Atranspose)); 35c4762a1bSJed Brown 36*9566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 37*9566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 38c4762a1bSJed Brown for (i=0; i<nr; i++) { 39c4762a1bSJed Brown for (j=0; j<nc; j++) { 40*9566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 41c4762a1bSJed Brown } 42c4762a1bSJed Brown } 43c4762a1bSJed Brown 44*9566063dSJacob Faibussowitsch PetscCall(MatView(Atranspose, PETSC_VIEWER_STDOUT_WORLD)); 45*9566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(Atranspose, NULL, NULL, &block)); 46c4762a1bSJed Brown for (i=0; i<nc; i++) { 47c4762a1bSJed Brown for (j=0; j<nr; j++) { 48*9566063dSJacob 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++) { 54*9566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x,rctx)); 55*9566063dSJacob Faibussowitsch PetscCall(VecSetRandom(y,rctx)); 56c4762a1bSJed Brown 57*9566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, Ax)); 58*9566063dSJacob Faibussowitsch PetscCall(VecDot(Ax, y, &dot1)); 59*9566063dSJacob Faibussowitsch PetscCall(MatMult(Atranspose, y, ATy)); 60*9566063dSJacob Faibussowitsch PetscCall(VecDot(ATy, x, &dot2)); 61c4762a1bSJed Brown 62*9566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "<Ax, y> = %g\n", (double)PetscRealPart(dot1))); 63*9566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "<x, A^Ty> = %g\n",(double)PetscRealPart(dot2))); 64c4762a1bSJed Brown } 65*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 66*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 67*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Ax)); 68c4762a1bSJed Brown 69*9566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,acol[0]+acol[nr]+acol[2*nr],nk,NULL,&B)); 70*9566063dSJacob Faibussowitsch PetscCall(MatSetRandom(B,rctx)); 71*9566063dSJacob Faibussowitsch PetscCall(MatMatMult(A,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&C)); 72*9566063dSJacob Faibussowitsch PetscCall(MatMatMult(A,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&C)); 73*9566063dSJacob 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 76*9566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 77*9566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 78c4762a1bSJed Brown for (i=0; i<nk; i++) { 79*9566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(B,i,&valsB)); 80*9566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,n,N,valsB,&x)); 81*9566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,NULL,&Ax)); 82*9566063dSJacob Faibussowitsch PetscCall(MatMult(A,x,Ax)); 83*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 84*9566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(C,i,&valsC)); 85*9566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,m,M,valsC,&y)); 86*9566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,-1.0,Ax)); 87*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Ax)); 88*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 89*9566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(C,&valsC)); 90*9566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(B,&valsB)); 91c4762a1bSJed Brown } 92*9566063dSJacob Faibussowitsch PetscCall(MatNorm(C,NORM_INFINITY,&norm)); 932c71b3e2SJacob Faibussowitsch PetscCheckFalse(norm > PETSC_SMALL,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Error in MatMatMult(): %g",(double)norm); 94*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 95*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 96c4762a1bSJed Brown 97c4762a1bSJed Brown for (i=0; i<(nr * nc); i++) { 98*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subs[i])); 99c4762a1bSJed Brown } 100*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 101*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Atranspose)); 102*9566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ATy)); 103*9566063dSJacob 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; 117*9566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,&rctx)); 118*9566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rctx,zero,one)); 119*9566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rctx)); 120c4762a1bSJed Brown for (i=0; i<(n * n); i++) { 121*9566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_WORLD,n,n,NULL,&subs[i])); 122c4762a1bSJed Brown } 123*9566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_WORLD,n,NULL,n,NULL,subs,&A)); 124*9566063dSJacob Faibussowitsch PetscCall(MatSetRandom(A,rctx)); 125c4762a1bSJed Brown 126*9566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 127*9566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 128c4762a1bSJed Brown for (i=0; i<n; i++) { 129c4762a1bSJed Brown for (j=0; j<n; j++) { 130*9566063dSJacob Faibussowitsch PetscCall(MatView(block[i][j], PETSC_VIEWER_STDOUT_WORLD)); 131c4762a1bSJed Brown } 132c4762a1bSJed Brown } 133*9566063dSJacob Faibussowitsch PetscCall(MatTranspose(A,MAT_INPLACE_MATRIX,&A)); 134*9566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD)); 135*9566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, NULL, NULL, &block)); 136c4762a1bSJed Brown for (i=0; i<n; i++) { 137c4762a1bSJed Brown for (j=0; j<n; j++) { 138*9566063dSJacob 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++) { 143*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subs[i])); 144c4762a1bSJed Brown } 145*9566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 146*9566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rctx)); 147c4762a1bSJed Brown PetscFunctionReturn(0); 148c4762a1bSJed Brown } 149c4762a1bSJed Brown 150c4762a1bSJed Brown int main(int argc,char **args) 151c4762a1bSJed Brown { 152c4762a1bSJed Brown 153*9566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&args,(char*)0,help)); 154*9566063dSJacob Faibussowitsch PetscCall(TestInitialMatrix()); 155*9566063dSJacob Faibussowitsch PetscCall(TestReuseMatrix()); 156*9566063dSJacob 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