static char help[] = "Solves a linear system in parallel with KSP.\n\n"; /*T Concepts: KSP^solving a Helmholtz equation Concepts: complex numbers; Concepts: Helmholtz equation Processors: n T*/ /* Description: Solves a complex linear system in parallel with KSP. The model problem: Solve Helmholtz equation on the unit square: (0,1) x (0,1) -delta u - sigma1*u + i*sigma2*u = f, where delta = Laplace operator Dirichlet b.c.'s on all sides Use the 2-D, five-point finite difference stencil. Compiling the code: This code uses the complex numbers version of PETSc, so configure must be run to enable this */ /* Include "petscksp.h" so that we can use KSP solvers. Note that this file automatically includes: petscsys.h - base PETSc routines petscvec.h - vectors petscmat.h - matrices petscis.h - index sets petscksp.h - Krylov subspace methods petscviewer.h - viewers petscpc.h - preconditioners */ #include #undef __FUNCT__ #define __FUNCT__ "ModifySubMatrices" PetscErrorCode ModifySubMatrices(PC pc,PetscInt nsub,const IS *row,const IS *col,Mat *submat,void *ctx) { return 0; } #undef __FUNCT__ #define __FUNCT__ "main" int main(int argc,char **args) { Vec u, x, xdd, b; /* exact solution, approx solutions, RHS */ Mat A; /* linear system matrix */ KSP ksp, kspdd; /* linear solver context */ PetscReal norm; /* norm of solution error */ PetscInt dim,i,j,Ii,J,Istart,Iend,n = 6,its, nsub; PetscErrorCode ierr; PetscScalar v,none = -1.0,sigma2,pfive = 0.5,*xa; PetscReal h2,sigma1 = 100.0; PetscBool dd_gasm = PETSC_FALSE, dd_asm = PETSC_FALSE, flg = PETSC_FALSE, printx; char dd_type[11]; PetscScalar a=1.0+PETSC_i; PC pcdd; IS is_local[2], is[2]; PetscMPIInt rank, size; PetscInitialize(&argc,&args,(char *)0,help); #if !defined(PETSC_USE_COMPLEX) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This example requires complex scalars."); #endif a=1.0+PETSC_i; printf("%G+%Gi\n",PetscRealPart(a),PetscImaginaryPart(a)); ierr = PetscOptionsGetReal(PETSC_NULL,"-sigma1",&sigma1,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);CHKERRQ(ierr); dim = n*n; MPI_Comm_size(PETSC_COMM_WORLD,&size); if (size>2) { PetscPrintf(PETSC_COMM_WORLD,"Please use 1 or 2 processes! Quit\n"); return 0; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Compute the matrix and right-hand-side vector that define the linear system, Ax = b. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create parallel matrix, specifying only its global dimensions. When using MatCreate(), the matrix format can be specified at runtime. Also, the parallel partitioning of the matrix is determined by PETSc at runtime. */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,dim,dim);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A); CHKERRQ(ierr); /* Currently, all PETSc parallel matrix formats are partitioned by contiguous chunks of rows across the processors. Determine which rows of the matrix are locally owned. */ ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr); /* Set matrix elements in parallel. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Always specify global rows and columns of matrix entries. */ sigma2 = 10.0*PETSC_i; h2 = 1.0/((n+1)*(n+1)); for (Ii=Istart; Ii0) { J = Ii-n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i0) { J = Ii-1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j -dd_sub_ksp_type -dd_sub_ksp_rtol 1.e-4 */ ierr = KSPCreate(PETSC_COMM_WORLD,&kspdd);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)kspdd, "dd_"); CHKERRQ(ierr); ierr = KSPSetOperators(kspdd,A,A,SAME_PRECONDITIONER);CHKERRQ(ierr); ierr = KSPGetPC(kspdd,&pcdd);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)pcdd, "dd_"); CHKERRQ(ierr); dd_type[0] = 0; ierr = PetscOptionsGetString(PETSC_NULL, "-dd_type", dd_type, 10, &flg); CHKERRQ(ierr); ierr = PetscStrcmp(dd_type, "gasm", &dd_gasm); CHKERRQ(ierr); if(dd_gasm) { ierr = PCSetType(pcdd,PCGASM);CHKERRQ(ierr); } else { ierr = PetscStrcmp(dd_type, "asm", &dd_asm); CHKERRQ(ierr); if(dd_asm) { ierr = PCSetType(pcdd,PCASM);CHKERRQ(ierr); } else { SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Unsupported -dd_type: %s", dd_type); } } /* Set the two subdomains for PC(G)ASM */ /* non-overlapping subdomains */ MPI_Comm_rank(PETSC_COMM_WORLD,&rank); if (size==2) { nsub= 1; ISCreateStride(PETSC_COMM_SELF,n*n/2,rank*n*n/2,1,&(is_local[0])); } else{ nsub= 2; ISCreateStride(PETSC_COMM_SELF,n*n/2,0,1,&(is_local[0])); ISCreateStride(PETSC_COMM_SELF,n*n/2,n*n/2,1,&(is_local[1])); } /* printf("[%i]: ",rank); */ /* ISView(is_local[i],PETSC_VIEWER_STDOUT_SELF); */ /* overlapping subdomains */ PetscInt expand= 1; if (size==2) { if (rank==0) { ISCreateStride(PETSC_COMM_SELF,n*(n/2+expand),0,1,&(is[0])); } else ISCreateStride(PETSC_COMM_SELF,n*(n/2+expand),n*(n/2-expand),1,&(is[0])); } else{ /* size==1 */ ISCreateStride(PETSC_COMM_SELF,n*(n/2+expand),0,1,&(is[0])); ISCreateStride(PETSC_COMM_SELF,n*(n/2+expand),n*(n/2-expand),1,&(is[1])); } /* printf("[%i]: ",rank); */ /* ISView(is[i],PETSC_VIEWER_STDOUT_SELF); */ /* set PC(G)ASM with the subdomains */ if(dd_gasm) { ierr= PCGASMSetSubdomains(pcdd,nsub,is_local, is);CHKERRQ(ierr); } else { ierr= PCASMSetLocalSubdomains(pcdd,nsub,is, is_local);CHKERRQ(ierr); } /* ierr= PCView(pcdd, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); */ /* Modify submatrices */ ierr= PCSetModifySubMatrices(pcdd,ModifySubMatrices,PETSC_NULL);CHKERRQ(ierr); /* Set the DD solver options; use the -dd_ prefix: -dd_ksp_type, etc. */ ierr= KSPSetFromOptions(kspdd);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create the benchmark linear solver. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create linear solver context */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); /* Set operators. Here the matrix that defines the linear system also serves as the preconditioning matrix. */ ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); /* Use command-line options to set the benchmark KSP and PC options. */ #if 0 /* Set type of KSP. */ ierr= KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); { PC pc; ierr= KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr= PCSetType(pc,PCLU);CHKERRQ(ierr); if (size==1) { ierr= PCFactorSetMatSolverPackage(pc,MATSOLVERSUPERLU);CHKERRQ(ierr); } else { ierr= PCFactorSetMatSolverPackage(pc,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr); } } #endif /* Set runtime options, e.g., -ksp_type -pc_type -ksp_monitor -ksp_rtol */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system with two different solvers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); ierr = KSPSolve(kspdd,b,xdd);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Check solution x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Print the first 3 entries of x; this demonstrates extraction of the real and imaginary components of the complex vector, x. */ printx = PETSC_FALSE; ierr = PetscOptionsGetBool(PETSC_NULL,"-print_x",&printx,PETSC_NULL);CHKERRQ(ierr); if (printx) { PetscInt nentries = 3, xlsize; ierr = PetscOptionsGetInt(PETSC_NULL, "-print_x_entries", &nentries,PETSC_NULL); CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"The first %D entries of x on each processor are:\n", nentries);CHKERRQ(ierr); ierr = VecGetLocalSize(x,&xlsize); CHKERRQ(ierr); nentries = PetscMin(xlsize, nentries); ierr = VecGetArray(x,&xa);CHKERRQ(ierr); for (i=0; i