Actual source code: planar_waveguide.c
slepc-3.7.1 2016-05-27
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
8: SLEPc is free software: you can redistribute it and/or modify it under the
9: terms of version 3 of the GNU Lesser General Public License as published by
10: the Free Software Foundation.
12: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
13: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15: more details.
17: You should have received a copy of the GNU Lesser General Public License
18: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
19: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20: */
21: /*
22: This example implements one of the problems found at
23: NLEVP: A Collection of Nonlinear Eigenvalue Problems,
24: The University of Manchester.
25: The details of the collection can be found at:
26: [1] T. Betcke et al., "NLEVP: A Collection of Nonlinear Eigenvalue
27: Problems", ACM Trans. Math. Software 39(2), Article 7, 2013.
29: The planar_waveguide problem is a quartic PEP with symmetric matrices,
30: arising from a finite element solution of the propagation constants in a
31: six-layer planar waveguide.
32: */
34: static char help[] = "FEM solution of the propagation constants in a six-layer planar waveguide.\n\n"
35: "The command line options are:\n"
36: " -n <n>, the dimension of the matrices.\n\n";
38: #include <slepcpep.h>
40: #define NMAT 5
41: #define NL 6
45: int main(int argc,char **argv)
46: {
47: Mat A[NMAT]; /* problem matrices */
48: PEP pep; /* polynomial eigenproblem solver context */
49: PetscInt n=128,nlocal,k,Istart,Iend,i,j,start_ct,end_ct;
50: PetscReal w=9.92918,a=0.0,b=2.0,h,deltasq;
51: PetscReal nref[NL],K2[NL],q[NL],*md,*supd,*subd;
52: PetscScalar v,alpha;
53: PetscBool terse;
56: SlepcInitialize(&argc,&argv,(char*)0,help);
58: PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL);
59: n = (n/4)*4;
60: PetscPrintf(PETSC_COMM_WORLD,"\nPlanar waveguide, n=%D\n\n",n+1);
61: h = (b-a)/n;
62: nlocal = (n/4)-1;
64: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
65: Set waveguide parameters used in construction of matrices
66: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
68: /* refractive indices in each layer */
69: nref[0] = 1.5;
70: nref[1] = 1.66;
71: nref[2] = 1.6;
72: nref[3] = 1.53;
73: nref[4] = 1.66;
74: nref[5] = 1.0;
76: for (i=0;i<NL;i++) K2[i] = w*w*nref[i]*nref[i];
77: deltasq = K2[0] - K2[NL-1];
78: for (i=0;i<NL;i++) q[i] = K2[i] - (K2[0] + K2[NL-1])/2;
80: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81: Compute the polynomial matrices
82: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
84: /* initialize matrices */
85: for (i=0;i<NMAT;i++) {
86: MatCreate(PETSC_COMM_WORLD,&A[i]);
87: MatSetSizes(A[i],PETSC_DECIDE,PETSC_DECIDE,n+1,n+1);
88: MatSetFromOptions(A[i]);
89: MatSetUp(A[i]);
90: }
91: MatGetOwnershipRange(A[0],&Istart,&Iend);
93: /* A0 */
94: alpha = (h/6)*(deltasq*deltasq/16);
95: for (i=Istart;i<Iend;i++) {
96: v = 4.0;
97: if (i==0 || i==n) v = 2.0;
98: MatSetValue(A[0],i,i,v*alpha,INSERT_VALUES);
99: if (i>0) { MatSetValue(A[0],i,i-1,alpha,INSERT_VALUES); }
100: if (i<n) { MatSetValue(A[0],i,i+1,alpha,INSERT_VALUES); }
101: }
103: /* A1 */
104: if (Istart==0) { MatSetValue(A[1],0,0,-deltasq/4,INSERT_VALUES); }
105: if (Iend==n+1) { MatSetValue(A[1],n,n,deltasq/4,INSERT_VALUES); }
107: /* A2 */
108: alpha = 1.0/h;
109: for (i=Istart;i<Iend;i++) {
110: v = 2.0;
111: if (i==0 || i==n) v = 1.0;
112: MatSetValue(A[2],i,i,v*alpha,ADD_VALUES);
113: if (i>0) { MatSetValue(A[2],i,i-1,-alpha,ADD_VALUES); }
114: if (i<n) { MatSetValue(A[2],i,i+1,-alpha,ADD_VALUES); }
115: }
116: PetscMalloc3(n+1,&md,n+1,&supd,n+1,&subd);
118: md[0] = 2.0*q[1];
119: supd[1] = q[1];
120: subd[0] = q[1];
122: for (k=1;k<=NL-2;k++) {
124: end_ct = k*(nlocal+1);
125: start_ct = end_ct-nlocal;
127: for (j=start_ct;j<end_ct;j++) {
128: md[j] = 4*q[k];
129: supd[j+1] = q[k];
130: subd[j] = q[k];
131: }
133: if (k < 4) { /* interface points */
134: md[end_ct] = 4*(q[k] + q[k+1])/2.0;
135: supd[end_ct+1] = q[k+1];
136: subd[end_ct] = q[k+1];
137: }
139: }
141: md[n] = 2*q[NL-2];
142: supd[n] = q[NL-2];
143: subd[n] = q[NL-2];
145: alpha = -h/6.0;
146: for (i=Istart;i<Iend;i++) {
147: MatSetValue(A[2],i,i,md[i]*alpha,ADD_VALUES);
148: if (i>0) { MatSetValue(A[2],i,i-1,subd[i-1]*alpha,ADD_VALUES); }
149: if (i<n) { MatSetValue(A[2],i,i+1,supd[i+1]*alpha,ADD_VALUES); }
150: }
151: PetscFree3(md,supd,subd);
153: /* A3 */
154: if (Istart==0) { MatSetValue(A[3],0,0,1.0,INSERT_VALUES); }
155: if (Iend==n+1) { MatSetValue(A[3],n,n,1.0,INSERT_VALUES); }
157: /* A4 */
158: alpha = (h/6);
159: for (i=Istart;i<Iend;i++) {
160: v = 4.0;
161: if (i==0 || i==n) v = 2.0;
162: MatSetValue(A[4],i,i,v*alpha,INSERT_VALUES);
163: if (i>0) { MatSetValue(A[4],i,i-1,alpha,INSERT_VALUES); }
164: if (i<n) { MatSetValue(A[4],i,i+1,alpha,INSERT_VALUES); }
165: }
167: /* assemble matrices */
168: for (i=0;i<NMAT;i++) {
169: MatAssemblyBegin(A[i],MAT_FINAL_ASSEMBLY);
170: }
171: for (i=0;i<NMAT;i++) {
172: MatAssemblyEnd(A[i],MAT_FINAL_ASSEMBLY);
173: }
175: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
176: Create the eigensolver and solve the problem
177: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
179: PEPCreate(PETSC_COMM_WORLD,&pep);
180: PEPSetOperators(pep,NMAT,A);
181: PEPSetFromOptions(pep);
182: PEPSolve(pep);
184: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
185: Display solution and clean up
186: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
187:
188: /* show detailed info unless -terse option is given by user */
189: PetscOptionsHasName(NULL,NULL,"-terse",&terse);
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: }
198: PEPDestroy(&pep);
199: for (i=0;i<NMAT;i++) {
200: MatDestroy(&A[i]);
201: }
202: SlepcFinalize();
203: return ierr;
204: }