Actual source code: ex38.c

slepc-3.11.2 2019-07-30
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2019, Universitat Politecnica de Valencia, Spain

  6:    This file is part of SLEPc.
  7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
  8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  9: */

 11: static char help[] = "Spectrum slicing on quadratic symmetric eigenproblem.\n\n"
 12:   "The command line options are:\n"
 13:   "  -n <n> ... dimension of the matrices.\n\n";

 15: #include <slepcpep.h>

 17: int main(int argc,char **argv)
 18: {
 19:   Mat            M,C,K,A[3]; /* problem matrices */
 20:   PEP            pep;        /* polynomial eigenproblem solver context */
 21:   ST             st;         /* spectral transformation context */
 22:   KSP            ksp;
 23:   PC             pc;
 24:   PEPType        type;
 25:   PetscBool      show=PETSC_FALSE,terse;
 26:   PetscInt       n=100,Istart,Iend,nev,i,*inertias,ns;
 27:   PetscReal      mu=1,tau=10,kappa=5,inta,intb,*shifts;

 30:   SlepcInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;

 32:   PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL);
 33:   PetscOptionsGetBool(NULL,NULL,"-show_inertias",&show,NULL);
 34:   PetscOptionsHasName(NULL,NULL,"-terse",&terse);
 35:   PetscPrintf(PETSC_COMM_WORLD,"\nSpectrum slicing on PEP, n=%D\n\n",n);

 37:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 38:      Compute the matrices that define the eigensystem, (k^2*M+k*C+K)x=0
 39:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

 41:   /* K is a tridiagonal */
 42:   MatCreate(PETSC_COMM_WORLD,&K);
 43:   MatSetSizes(K,PETSC_DECIDE,PETSC_DECIDE,n,n);
 44:   MatSetFromOptions(K);
 45:   MatSetUp(K);

 47:   MatGetOwnershipRange(K,&Istart,&Iend);
 48:   for (i=Istart;i<Iend;i++) {
 49:     if (i>0) {
 50:       MatSetValue(K,i,i-1,-kappa,INSERT_VALUES);
 51:     }
 52:     MatSetValue(K,i,i,kappa*3.0,INSERT_VALUES);
 53:     if (i<n-1) {
 54:       MatSetValue(K,i,i+1,-kappa,INSERT_VALUES);
 55:     }
 56:   }

 58:   MatAssemblyBegin(K,MAT_FINAL_ASSEMBLY);
 59:   MatAssemblyEnd(K,MAT_FINAL_ASSEMBLY);

 61:   /* C is a tridiagonal */
 62:   MatCreate(PETSC_COMM_WORLD,&C);
 63:   MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,n,n);
 64:   MatSetFromOptions(C);
 65:   MatSetUp(C);

 67:   MatGetOwnershipRange(C,&Istart,&Iend);
 68:   for (i=Istart;i<Iend;i++) {
 69:     if (i>0) {
 70:       MatSetValue(C,i,i-1,-tau,INSERT_VALUES);
 71:     }
 72:     MatSetValue(C,i,i,tau*3.0,INSERT_VALUES);
 73:     if (i<n-1) {
 74:       MatSetValue(C,i,i+1,-tau,INSERT_VALUES);
 75:     }
 76:   }

 78:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
 79:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);

 81:   /* M is a diagonal matrix */
 82:   MatCreate(PETSC_COMM_WORLD,&M);
 83:   MatSetSizes(M,PETSC_DECIDE,PETSC_DECIDE,n,n);
 84:   MatSetFromOptions(M);
 85:   MatSetUp(M);
 86:   MatGetOwnershipRange(M,&Istart,&Iend);
 87:   for (i=Istart;i<Iend;i++) {
 88:     MatSetValue(M,i,i,mu,INSERT_VALUES);
 89:   }
 90:   MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);
 91:   MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);

 93:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 94:                 Create the eigensolver and solve the problem
 95:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

 97:   /*
 98:      Create eigensolver context
 99:   */
100:   PEPCreate(PETSC_COMM_WORLD,&pep);

102:   /*
103:      Set operators and set problem type
104:   */
105:   A[0] = K; A[1] = C; A[2] = M;
106:   PEPSetOperators(pep,3,A);
107:   PEPSetProblemType(pep,PEP_HYPERBOLIC);

109:    /*
110:      Set interval for spectrum slicing
111:   */
112:   inta = -11.3;
113:   intb = -9.5;
114:   PEPSetInterval(pep,inta,intb);
115:   PEPSetWhichEigenpairs(pep,PEP_ALL);

117:   /*
118:      Spectrum slicing requires STOAR 
119:   */
120:   PEPSetType(pep,PEPSTOAR);

122:   /*
123:      Set shift-and-invert with Cholesky; select MUMPS if available
124:   */
125:   PEPGetST(pep,&st);
126:   STSetType(st,STSINVERT);

128:   STGetKSP(st,&ksp);
129:   KSPSetType(ksp,KSPPREONLY);
130:   KSPGetPC(ksp,&pc);
131:   PCSetType(pc,PCCHOLESKY);

133: #if defined(PETSC_HAVE_MUMPS)
134: #if defined(PETSC_USE_COMPLEX)
135:   SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Spectrum slicing with MUMPS is not available for complex scalars");
136: #endif
137:   PEPSTOARSetDetectZeros(pep,PETSC_TRUE);  /* enforce zero detection */
138:   PCFactorSetMatSolverType(pc,MATSOLVERMUMPS);
139:   /*
140:      Add several MUMPS options (currently there is no better way of setting this in program):
141:      '-mat_mumps_icntl_13 1': turn off ScaLAPACK for matrix inertia
142:      '-mat_mumps_icntl_24 1': detect null pivots in factorization (for the case that a shift is equal to an eigenvalue)
143:      '-mat_mumps_cntl_3 <tol>': a tolerance used for null pivot detection (must be larger than machine epsilon)

145:      Note: depending on the interval, it may be necessary also to increase the workspace:
146:      '-mat_mumps_icntl_14 <percentage>': increase workspace with a percentage (50, 100 or more)
147:   */
148:   PetscOptionsInsertString(NULL,"-mat_mumps_icntl_13 1 -mat_mumps_icntl_24 1 -mat_mumps_cntl_3 1e-12");
149: #endif

151:   /*
152:      Set solver parameters at runtime
153:   */
154:   PEPSetFromOptions(pep);

156:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
157:                       Solve the eigensystem
158:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
159:   PEPSetUp(pep);
160:   if (show) {
161:     PEPSTOARGetInertias(pep,&ns,&shifts,&inertias);
162:     PetscPrintf(PETSC_COMM_WORLD,"Subintervals (after setup):\n");
163:     for (i=0;i<ns;i++) { PetscPrintf(PETSC_COMM_WORLD,"Shift %g  Inertia %D \n",(double)shifts[i],inertias[i]); }
164:     PetscPrintf(PETSC_COMM_WORLD,"\n");
165:     PetscFree(shifts);
166:     PetscFree(inertias);
167:   }
168:   PEPSolve(pep);
169:   if (show && !terse) {
170:     PEPSTOARGetInertias(pep,&ns,&shifts,&inertias);
171:     PetscPrintf(PETSC_COMM_WORLD,"All shifts (after solve):\n");
172:     for (i=0;i<ns;i++) { PetscPrintf(PETSC_COMM_WORLD,"Shift %g  Inertia %D \n",(double)shifts[i],inertias[i]); }
173:     PetscPrintf(PETSC_COMM_WORLD,"\n");
174:     PetscFree(shifts);
175:     PetscFree(inertias);
176:   }

178:   /*
179:      Show eigenvalues in interval and print solution
180:   */
181:   PEPGetType(pep,&type);
182:   PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);
183:   PEPGetDimensions(pep,&nev,NULL,NULL);
184:   PEPGetInterval(pep,&inta,&intb);
185:   PetscPrintf(PETSC_COMM_WORLD," %D eigenvalues found in [%g, %g]\n",nev,(double)inta,(double)intb);

187:   /*
188:      Show detailed info unless -terse option is given by user
189:    */
190:   if (terse) {
191:     PEPErrorView(pep,PEP_ERROR_BACKWARD,NULL);
192:   } else {
193:     PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL);
194:     PEPReasonView(pep,PETSC_VIEWER_STDOUT_WORLD);
195:     PEPErrorView(pep,PEP_ERROR_BACKWARD,PETSC_VIEWER_STDOUT_WORLD);
196:     PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);
197:   }

199:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
200:                     Clean up
201:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
202:   PEPDestroy(&pep);
203:   MatDestroy(&M);
204:   MatDestroy(&C);
205:   MatDestroy(&K);
206:   SlepcFinalize();
207:   return ierr;
208: }

210: /*TEST

212:    test:
213:       suffix: 1
214:       requires: !single
215:       args: -show_inertias -terse

217: TEST*/