static char help[] = "Tests MatMatSolve() and MatMatTransposeSolve() for computing inv(A) with MUMPS.\n\ Example: mpiexec -n ./ex214 -displ \n\n"; #include int main(int argc,char **args) { PetscMPIInt size,rank; #if defined(PETSC_HAVE_MUMPS) Mat A,RHS,C,F,X,AX,spRHST; PetscInt m,n,nrhs,M,N,i,Istart,Iend,Ii,j,J,test; PetscScalar v; PetscReal norm,tol=PETSC_SQRT_MACHINE_EPSILON; PetscRandom rand; PetscBool displ=PETSC_FALSE; char solver[256]; #endif PetscCall(PetscInitialize(&argc,&args,(char*)0,help)); PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); #if !defined(PETSC_HAVE_MUMPS) if (rank == 0) PetscCall(PetscPrintf(PETSC_COMM_SELF,"This example requires MUMPS, exit...\n")); PetscCall(PetscFinalize()); return 0; #else PetscCall(PetscOptionsGetBool(NULL,NULL,"-displ",&displ,NULL)); /* Create matrix A */ m = 4; n = 4; PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL)); PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL)); PetscCall(MatCreate(PETSC_COMM_WORLD,&A)); PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n)); PetscCall(MatSetFromOptions(A)); PetscCall(MatMPIAIJSetPreallocation(A,5,NULL,5,NULL)); PetscCall(MatSeqAIJSetPreallocation(A,5,NULL)); PetscCall(MatGetOwnershipRange(A,&Istart,&Iend)); for (Ii=Istart; Ii0) {J = Ii - n; PetscCall(MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES));} if (i0) {J = Ii - 1; PetscCall(MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES));} if (j tol) { PetscCall(PetscPrintf(PETSC_COMM_SELF,"(1) MatMatSolve: Norm of error %g\n",norm)); } /* Test X=RHS */ PetscCall(MatMatSolve(F,RHS,RHS)); /* Check the error */ PetscCall(MatAXPY(RHS,-1.0,C,SAME_NONZERO_PATTERN)); PetscCall(MatNorm(RHS,NORM_FROBENIUS,&norm)); if (norm > tol) { PetscCall(PetscPrintf(PETSC_COMM_SELF,"(1.1) MatMatSolve: Norm of error %g\n",norm)); } /* (2) Test MatMatSolve() for inv(A) with dense RHS: RHS = [e[0],...,e[nrhs-1]], dense X holds first nrhs columns of inv(A) */ /* -------------------------------------------------------------------- */ PetscCall(MatZeroEntries(RHS)); for (i=0; i tol) { PetscCall(PetscPrintf(PETSC_COMM_SELF,"(2) MatMatSolve: Norm of residual %g\n",norm)); } PetscCall(MatZeroEntries(X)); /* (3) Test MatMatTransposeSolve() for inv(A) with sparse RHS stored in the host: spRHST = [e[0],...,e[nrhs-1]]^T, dense X holds first nrhs columns of inv(A) */ /* --------------------------------------------------------------------------- */ /* Create spRHST: PETSc does not support compressed column format which is required by MUMPS for sparse RHS matrix, thus user must create spRHST=spRHS^T and call MatMatTransposeSolve() */ PetscCall(MatCreate(PETSC_COMM_WORLD,&spRHST)); if (rank == 0) { /* MUMPS requirs RHS be centralized on the host! */ PetscCall(MatSetSizes(spRHST,nrhs,M,PETSC_DECIDE,PETSC_DECIDE)); } else { PetscCall(MatSetSizes(spRHST,0,0,PETSC_DECIDE,PETSC_DECIDE)); } PetscCall(MatSetType(spRHST,MATAIJ)); PetscCall(MatSetFromOptions(spRHST)); PetscCall(MatSetUp(spRHST)); if (rank == 0) { v = 1.0; for (i=0; i tol) { PetscCall(PetscPrintf(PETSC_COMM_SELF,"(3) MatMatSolve: Norm of residual %g\n",norm)); } /* (4) Test MatMatSolve() for inv(A) with selected entries: input: spRHS gives selected indices; output: spRHS holds selected entries of inv(A) */ /* --------------------------------------------------------------------------------- */ if (nrhs == N) { /* mumps requires nrhs = n */ /* Create spRHS on proc[0] */ Mat spRHS = NULL; /* Create spRHS = spRHST^T. Two matrices share internal matrix data structure */ PetscCall(MatCreateTranspose(spRHST,&spRHS)); PetscCall(MatMumpsGetInverse(F,spRHS)); PetscCall(MatDestroy(&spRHS)); PetscCall(MatMumpsGetInverseTranspose(F,spRHST)); if (displ) { PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nSelected entries of inv(A^T):\n")); PetscCall(MatView(spRHST,PETSC_VIEWER_STDOUT_WORLD)); } PetscCall(MatDestroy(&spRHS)); } PetscCall(MatDestroy(&AX)); PetscCall(MatDestroy(&F)); PetscCall(MatDestroy(&RHS)); PetscCall(MatDestroy(&spRHST)); } /* Free data structures */ PetscCall(MatDestroy(&A)); PetscCall(MatDestroy(&C)); PetscCall(MatDestroy(&X)); PetscCall(PetscRandomDestroy(&rand)); PetscCall(PetscFinalize()); return 0; #endif } /*TEST test: requires: mumps double !complex test: suffix: 2 requires: mumps double !complex nsize: 2 TEST*/