xref: /petsc/src/mat/tests/ex178.c (revision 327415f76d85372a4417cf1aaa14db707d4d6c04)
18a9c020eSBarry Smith 
28a9c020eSBarry Smith static char help[] = "Tests MatInvertVariableBlockEnvelope()\n\n";
38a9c020eSBarry Smith 
48a9c020eSBarry Smith #include <petscmat.h>
58a9c020eSBarry Smith extern PetscErrorCode MatIsDiagonal(Mat);
68a9c020eSBarry Smith extern PetscErrorCode BuildMatrix(const PetscInt*, PetscInt,const PetscInt *,Mat*);
78a9c020eSBarry Smith 
88a9c020eSBarry Smith int main(int argc,char **argv)
98a9c020eSBarry Smith {
108a9c020eSBarry Smith   Mat            A,C,D,F;
118a9c020eSBarry Smith   PetscInt       i,j,rows[2],*parts,cnt, N = 21,nblocks,*blocksizes;
128a9c020eSBarry Smith   PetscScalar    values[2][2];
138a9c020eSBarry Smith   PetscReal      rand;
148a9c020eSBarry Smith   PetscRandom    rctx;
158a9c020eSBarry Smith   PetscMPIInt    size;
168a9c020eSBarry Smith 
17*327415f7SBarry Smith   PetscFunctionBeginUser;
188a9c020eSBarry Smith   PetscCall(PetscInitialize(&argc,&argv,(char*) 0,help));
198a9c020eSBarry Smith   PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_DENSE));
208a9c020eSBarry Smith 
218a9c020eSBarry Smith   PetscCall(MatCreate(PETSC_COMM_WORLD,&C));
228a9c020eSBarry Smith   PetscCall(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,6,18));
238a9c020eSBarry Smith   PetscCall(MatSetFromOptions(C));
248a9c020eSBarry Smith   PetscCall(MatSetUp(C));
258a9c020eSBarry Smith   values[0][0] = 2; values[0][1] = 1;
268a9c020eSBarry Smith   values[1][0] = 1; values[1][1] = 2;
278a9c020eSBarry Smith   for (i=0;i<3;i++){
288a9c020eSBarry Smith     rows[0] = 2*i; rows[1] = 2*i + 1;
298a9c020eSBarry Smith     PetscCall(MatSetValues(C,2,rows,2,rows,(PetscScalar*)values,INSERT_VALUES));
308a9c020eSBarry Smith   }
318a9c020eSBarry Smith   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
328a9c020eSBarry Smith   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
338a9c020eSBarry Smith   PetscCall(MatView(C,PETSC_VIEWER_STDOUT_WORLD));
348a9c020eSBarry Smith 
358a9c020eSBarry Smith   PetscCall(MatMatTransposeMult(C,C,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&A));
368a9c020eSBarry Smith   PetscCall(MatView(A,PETSC_VIEWER_STDOUT_WORLD));
378a9c020eSBarry Smith 
388a9c020eSBarry Smith   PetscCall(MatInvertVariableBlockEnvelope(A,MAT_INITIAL_MATRIX,&D));
398a9c020eSBarry Smith   PetscCall(MatView(D,PETSC_VIEWER_STDOUT_WORLD));
408a9c020eSBarry Smith 
418a9c020eSBarry Smith   PetscCall(MatMatMult(A,D,MAT_INITIAL_MATRIX,1.0,&F));
428a9c020eSBarry Smith   PetscCall(MatView(F,PETSC_VIEWER_STDOUT_WORLD));
438a9c020eSBarry Smith   PetscCall(MatIsDiagonal(F));
448a9c020eSBarry Smith 
458a9c020eSBarry Smith   PetscCall(MatDestroy(&A));
468a9c020eSBarry Smith   PetscCall(MatDestroy(&D));
478a9c020eSBarry Smith   PetscCall(MatDestroy(&C));
488a9c020eSBarry Smith   PetscCall(MatDestroy(&F));
498a9c020eSBarry Smith 
508a9c020eSBarry Smith   PetscCall(PetscRandomCreate(PETSC_COMM_SELF,&rctx));
518a9c020eSBarry Smith   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
528a9c020eSBarry Smith   PetscCall(PetscMalloc1(size,&parts));
538a9c020eSBarry Smith 
548a9c020eSBarry Smith   for (j=0; j<128; j++) {
558a9c020eSBarry Smith     cnt = 0;
568a9c020eSBarry Smith     for (i=0; i<size-1; i++) {
578a9c020eSBarry Smith       PetscCall(PetscRandomGetValueReal(rctx,&rand));
588a9c020eSBarry Smith       parts[i] = (PetscInt) N*rand;
598a9c020eSBarry Smith       parts[i] = PetscMin(parts[i],N-cnt);
608a9c020eSBarry Smith       cnt      += parts[i];
618a9c020eSBarry Smith     }
628a9c020eSBarry Smith     parts[size-1] = N - cnt;
638a9c020eSBarry Smith 
648a9c020eSBarry Smith     PetscCall(PetscRandomGetValueReal(rctx,&rand));
658a9c020eSBarry Smith     nblocks = rand*10;
668a9c020eSBarry Smith     nblocks = PetscMax(nblocks,2);
678a9c020eSBarry Smith     cnt = 0;
688a9c020eSBarry Smith     PetscCall(PetscMalloc1(nblocks,&blocksizes));
698a9c020eSBarry Smith     for (i=0; i<nblocks-1; i++) {
708a9c020eSBarry Smith       PetscCall(PetscRandomGetValueReal(rctx,&rand));
718a9c020eSBarry Smith       blocksizes[i] = PetscMax(1,(PetscInt) N*rand);
728a9c020eSBarry Smith       blocksizes[i] = PetscMin(blocksizes[i],N-cnt);
738a9c020eSBarry Smith       cnt      += blocksizes[i];
748a9c020eSBarry Smith       if (cnt == N) {
758a9c020eSBarry Smith         nblocks = i + 1;
768a9c020eSBarry Smith         break;
778a9c020eSBarry Smith       }
788a9c020eSBarry Smith     }
798a9c020eSBarry Smith     if (cnt < N) {
808a9c020eSBarry Smith       blocksizes[nblocks-1] = N - cnt;
818a9c020eSBarry Smith     }
828a9c020eSBarry Smith 
838a9c020eSBarry Smith     PetscCall(BuildMatrix(parts,nblocks,blocksizes,&A));
848a9c020eSBarry Smith     PetscCall(PetscFree(blocksizes));
858a9c020eSBarry Smith 
868a9c020eSBarry Smith     PetscCall(MatInvertVariableBlockEnvelope(A,MAT_INITIAL_MATRIX,&D));
878a9c020eSBarry Smith 
888a9c020eSBarry Smith     PetscCall(MatMatMult(A,D,MAT_INITIAL_MATRIX,1.0,&F));
898a9c020eSBarry Smith     PetscCall(MatIsDiagonal(F));
908a9c020eSBarry Smith 
918a9c020eSBarry Smith     PetscCall(MatDestroy(&A));
928a9c020eSBarry Smith     PetscCall(MatDestroy(&D));
938a9c020eSBarry Smith     PetscCall(MatDestroy(&F));
948a9c020eSBarry Smith   }
958a9c020eSBarry Smith   PetscCall(PetscFree(parts));
968a9c020eSBarry Smith   PetscCall(PetscRandomDestroy(&rctx));
978a9c020eSBarry Smith 
988a9c020eSBarry Smith   PetscCall(PetscFinalize());
998a9c020eSBarry Smith   return 0;
1008a9c020eSBarry Smith }
1018a9c020eSBarry Smith 
1028a9c020eSBarry Smith PetscErrorCode MatIsDiagonal(Mat A)
1038a9c020eSBarry Smith {
1048a9c020eSBarry Smith   PetscInt          ncols,i,j,rstart,rend;
1058a9c020eSBarry Smith   const PetscInt    *cols;
1068a9c020eSBarry Smith   const PetscScalar *vals;
1078a9c020eSBarry Smith   PetscBool         founddiag;
1088a9c020eSBarry Smith 
1098a9c020eSBarry Smith   PetscFunctionBeginUser;
1108a9c020eSBarry Smith   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
1118a9c020eSBarry Smith   for (i=rstart; i<rend; i++) {
1128a9c020eSBarry Smith     founddiag = PETSC_FALSE;
1138a9c020eSBarry Smith     PetscCall(MatGetRow(A,i,&ncols,&cols,&vals));
1148a9c020eSBarry Smith     for (j=0; j<ncols; j++) {
1158a9c020eSBarry Smith       if (cols[j] == i) {
1168a9c020eSBarry Smith         PetscCheck(PetscAbsScalar(vals[j] - 1) < PETSC_SMALL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row %" PetscInt_FMT " does not have 1 on the diagonal, it has %g",i,(double)PetscAbsScalar(vals[j]));
1178a9c020eSBarry Smith         founddiag = PETSC_TRUE;
1188a9c020eSBarry Smith       } else {
1198a9c020eSBarry Smith         PetscCheck(PetscAbsScalar(vals[j]) < PETSC_SMALL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row %" PetscInt_FMT " has off-diagonal value %g at %" PetscInt_FMT "",i,(double)PetscAbsScalar(vals[j]),cols[j]);
1208a9c020eSBarry Smith       }
1218a9c020eSBarry Smith     }
1228a9c020eSBarry Smith     PetscCall(MatRestoreRow(A,i,&ncols,&cols,&vals));
1238a9c020eSBarry Smith     PetscCheck(founddiag,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row %" PetscInt_FMT " does not have diagonal entrie",i);
1248a9c020eSBarry Smith   }
1258a9c020eSBarry Smith   PetscFunctionReturn(0);
1268a9c020eSBarry Smith }
1278a9c020eSBarry Smith 
1288a9c020eSBarry Smith /*
1298a9c020eSBarry Smith     All processes receive all the block information
1308a9c020eSBarry Smith */
1318a9c020eSBarry Smith PetscErrorCode BuildMatrix(const PetscInt *parts, PetscInt nblocks, const PetscInt *blocksizes,Mat *A)
1328a9c020eSBarry Smith {
1338a9c020eSBarry Smith   PetscInt          i,cnt = 0;
1348a9c020eSBarry Smith   PetscMPIInt       rank;
1358a9c020eSBarry Smith 
1368a9c020eSBarry Smith   PetscFunctionBeginUser;
1378a9c020eSBarry Smith   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1388a9c020eSBarry Smith   PetscCall(MatCreateAIJ(PETSC_COMM_WORLD,parts[rank],parts[rank],PETSC_DETERMINE,PETSC_DETERMINE,0,NULL,0,NULL,A));
1398a9c020eSBarry Smith   PetscCall(MatSetOption(*A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
140c5853193SPierre Jolivet   if (rank == 0) {
1418a9c020eSBarry Smith     for (i=0; i<nblocks; i++) {
1428a9c020eSBarry Smith       PetscCall(MatSetValue(*A,cnt,cnt+blocksizes[i]-1,1.0,INSERT_VALUES));
1438a9c020eSBarry Smith       PetscCall(MatSetValue(*A,cnt+blocksizes[i]-1,cnt,1.0,INSERT_VALUES));
1448a9c020eSBarry Smith       cnt += blocksizes[i];
1458a9c020eSBarry Smith     }
1468a9c020eSBarry Smith   }
1478a9c020eSBarry Smith   PetscCall(MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY));
1488a9c020eSBarry Smith   PetscCall(MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY));
1498a9c020eSBarry Smith   PetscCall(MatShift(*A,10));
1508a9c020eSBarry Smith   PetscFunctionReturn(0);
1518a9c020eSBarry Smith }
1528a9c020eSBarry Smith 
1538a9c020eSBarry Smith /*TEST
1548a9c020eSBarry Smith 
1558a9c020eSBarry Smith    test:
1568a9c020eSBarry Smith 
1578a9c020eSBarry Smith    test:
1588a9c020eSBarry Smith      suffix: 2
1598a9c020eSBarry Smith      nsize: 2
1608a9c020eSBarry Smith 
1618a9c020eSBarry Smith    test:
1628a9c020eSBarry Smith      suffix: 5
1638a9c020eSBarry Smith      nsize: 5
1648a9c020eSBarry Smith 
1658a9c020eSBarry Smith TEST*/
166