Actual source code: ex38.c
slepc-3.11.2 2019-07-30
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*/