Line data Source code
1 : /*
2 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3 : SLEPc - Scalable Library for Eigenvalue Problem Computations
4 : Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
5 :
6 : This file is part of SLEPc.
7 : SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9 : */
10 :
11 : #include <slepc/private/dsimpl.h> /*I "slepcds.h" I*/
12 : #include <slepcblaslapack.h>
13 :
14 : typedef struct {
15 : PetscInt nf; /* number of functions in f[] */
16 : FN f[DS_NUM_EXTRA]; /* functions defining the nonlinear operator */
17 : PetscInt max_mid; /* maximum minimality index */
18 : PetscInt nnod; /* number of nodes for quadrature rules */
19 : PetscInt spls; /* number of sampling columns for quadrature rules */
20 : PetscInt Nit; /* number of refinement iterations */
21 : PetscReal rtol; /* tolerance of Newton refinement */
22 : RG rg; /* region for contour integral */
23 : PetscLayout map; /* used to distribute work among MPI processes */
24 : void *computematrixctx;
25 : PetscErrorCode (*computematrix)(DS,PetscScalar,PetscBool,DSMatType,void*);
26 : } DS_NEP;
27 :
28 : /*
29 : DSNEPComputeMatrix - Build the matrix associated with a nonlinear operator
30 : T(lambda) or its derivative T'(lambda), given the parameter lambda, where
31 : T(lambda) = sum_i E_i*f_i(lambda). The result is written in mat.
32 : */
33 969 : static PetscErrorCode DSNEPComputeMatrix(DS ds,PetscScalar lambda,PetscBool deriv,DSMatType mat)
34 : {
35 969 : DS_NEP *ctx = (DS_NEP*)ds->data;
36 969 : PetscScalar *T,alpha;
37 969 : const PetscScalar *E;
38 969 : PetscInt i,ld,n;
39 969 : PetscBLASInt k,inc=1;
40 :
41 969 : PetscFunctionBegin;
42 969 : PetscCall(PetscLogEventBegin(DS_Other,ds,0,0,0));
43 969 : if (ctx->computematrix) PetscCall((*ctx->computematrix)(ds,lambda,deriv,mat,ctx->computematrixctx));
44 : else {
45 10 : PetscCall(DSGetDimensions(ds,&n,NULL,NULL,NULL));
46 10 : PetscCall(DSGetLeadingDimension(ds,&ld));
47 10 : PetscCall(PetscBLASIntCast(ld*n,&k));
48 10 : PetscCall(MatDenseGetArray(ds->omat[mat],&T));
49 10 : PetscCall(PetscArrayzero(T,k));
50 40 : for (i=0;i<ctx->nf;i++) {
51 30 : if (deriv) PetscCall(FNEvaluateDerivative(ctx->f[i],lambda,&alpha));
52 18 : else PetscCall(FNEvaluateFunction(ctx->f[i],lambda,&alpha));
53 30 : PetscCall(MatDenseGetArrayRead(ds->omat[DSMatExtra[i]],&E));
54 30 : PetscCallBLAS("BLASaxpy",BLASaxpy_(&k,&alpha,E,&inc,T,&inc));
55 30 : PetscCall(MatDenseRestoreArrayRead(ds->omat[DSMatExtra[i]],&E));
56 : }
57 10 : PetscCall(MatDenseRestoreArray(ds->omat[mat],&T));
58 : }
59 969 : PetscCall(PetscLogEventEnd(DS_Other,ds,0,0,0));
60 969 : PetscFunctionReturn(PETSC_SUCCESS);
61 : }
62 :
63 20 : static PetscErrorCode DSAllocate_NEP(DS ds,PetscInt ld)
64 : {
65 20 : DS_NEP *ctx = (DS_NEP*)ds->data;
66 20 : PetscInt i;
67 :
68 20 : PetscFunctionBegin;
69 20 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_X));
70 80 : for (i=0;i<ctx->nf;i++) PetscCall(DSAllocateMat_Private(ds,DSMatExtra[i]));
71 20 : PetscCall(PetscFree(ds->perm));
72 20 : PetscCall(PetscMalloc1(ld*ctx->max_mid,&ds->perm));
73 20 : PetscFunctionReturn(PETSC_SUCCESS);
74 : }
75 :
76 1 : static PetscErrorCode DSView_NEP(DS ds,PetscViewer viewer)
77 : {
78 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
79 1 : PetscViewerFormat format;
80 1 : PetscInt i;
81 1 : const char *methodname[] = {
82 : "Successive Linear Problems",
83 : "Contour Integral"
84 : };
85 1 : const int nmeth=PETSC_STATIC_ARRAY_LENGTH(methodname);
86 :
87 1 : PetscFunctionBegin;
88 1 : PetscCall(PetscViewerGetFormat(viewer,&format));
89 1 : if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
90 1 : if (ds->method<nmeth) PetscCall(PetscViewerASCIIPrintf(viewer,"solving the problem with: %s\n",methodname[ds->method]));
91 : #if defined(PETSC_USE_COMPLEX)
92 : if (ds->method==1) { /* contour integral method */
93 : PetscCall(PetscViewerASCIIPrintf(viewer,"number of integration points: %" PetscInt_FMT "\n",ctx->nnod));
94 : PetscCall(PetscViewerASCIIPrintf(viewer,"maximum minimality index: %" PetscInt_FMT "\n",ctx->max_mid));
95 : if (ctx->spls) PetscCall(PetscViewerASCIIPrintf(viewer,"number of sampling columns for quadrature: %" PetscInt_FMT "\n",ctx->spls));
96 : if (ctx->Nit) PetscCall(PetscViewerASCIIPrintf(viewer,"doing iterative refinement (%" PetscInt_FMT " its, tolerance %g)\n",ctx->Nit,(double)ctx->rtol));
97 : PetscCall(RGView(ctx->rg,viewer));
98 : }
99 : #endif
100 1 : if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPrintf(viewer,"number of functions: %" PetscInt_FMT "\n",ctx->nf));
101 1 : PetscFunctionReturn(PETSC_SUCCESS);
102 : }
103 0 : for (i=0;i<ctx->nf;i++) {
104 0 : PetscCall(FNView(ctx->f[i],viewer));
105 0 : PetscCall(DSViewMat(ds,viewer,DSMatExtra[i]));
106 : }
107 0 : if (ds->state>DS_STATE_INTERMEDIATE) PetscCall(DSViewMat(ds,viewer,DS_MAT_X));
108 0 : PetscFunctionReturn(PETSC_SUCCESS);
109 : }
110 :
111 2 : static PetscErrorCode DSVectors_NEP(DS ds,DSMatType mat,PetscInt *j,PetscReal *rnorm)
112 : {
113 2 : PetscFunctionBegin;
114 2 : PetscCheck(!rnorm,PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Not implemented yet");
115 2 : switch (mat) {
116 : case DS_MAT_X:
117 2 : break;
118 0 : case DS_MAT_Y:
119 0 : SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Not implemented yet");
120 0 : default:
121 0 : SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
122 : }
123 2 : PetscFunctionReturn(PETSC_SUCCESS);
124 : }
125 :
126 2 : static PetscErrorCode DSSort_NEP(DS ds,PetscScalar *wr,PetscScalar *wi,PetscScalar *rr,PetscScalar *ri,PetscInt *dummy)
127 : {
128 2 : DS_NEP *ctx = (DS_NEP*)ds->data;
129 2 : PetscInt n,l,i,*perm,lds;
130 2 : PetscScalar *Q;
131 :
132 2 : PetscFunctionBegin;
133 2 : if (!ds->sc) PetscFunctionReturn(PETSC_SUCCESS);
134 2 : if (!ds->method) PetscFunctionReturn(PETSC_SUCCESS); /* SLP computes just one eigenvalue */
135 0 : n = ds->n*ctx->max_mid;
136 0 : lds = ds->ld*ctx->max_mid;
137 0 : l = ds->l;
138 0 : perm = ds->perm;
139 0 : for (i=0;i<n;i++) perm[i] = i;
140 0 : if (rr) PetscCall(DSSortEigenvalues_Private(ds,rr,ri,perm,PETSC_FALSE));
141 0 : else PetscCall(DSSortEigenvalues_Private(ds,wr,NULL,perm,PETSC_FALSE));
142 0 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_Q],&Q));
143 0 : for (i=l;i<ds->t;i++) Q[i+i*lds] = wr[perm[i]];
144 0 : for (i=l;i<ds->t;i++) wr[i] = Q[i+i*lds];
145 0 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_Q],&Q));
146 : /* n != ds->n */
147 0 : PetscCall(DSPermuteColumns_Private(ds,0,ds->t,ds->n,DS_MAT_X,perm));
148 0 : PetscFunctionReturn(PETSC_SUCCESS);
149 : }
150 :
151 : #if defined(SLEPC_MISSING_LAPACK_GGEV3)
152 : #define LAPGEEV "ggev"
153 : #else
154 : #define LAPGEEV "ggev3"
155 : #endif
156 :
157 185 : static PetscErrorCode DSSolve_NEP_SLP(DS ds,PetscScalar *wr,PetscScalar *wi)
158 : {
159 185 : PetscScalar *A,*B,*W,*X,*work,*alpha,*beta,a;
160 185 : PetscScalar sigma,lambda,mu,re,re2,sone=1.0,szero=0.0;
161 185 : PetscBLASInt info,n,ld,lwork,one=1,zero=0;
162 185 : PetscInt it,pos,j,maxit=100,result;
163 185 : PetscReal norm,tol,done=1.0;
164 : #if !defined(PETSC_USE_COMPLEX)
165 185 : PetscReal *alphai,im,im2;
166 : #endif
167 :
168 185 : PetscFunctionBegin;
169 185 : PetscCall(PetscBLASIntCast(ds->n,&n));
170 185 : PetscCall(PetscBLASIntCast(ds->ld,&ld));
171 185 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_A));
172 185 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_B));
173 185 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_W));
174 185 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_A],&A));
175 185 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_B],&B));
176 185 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_W],&W));
177 185 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_X],&X));
178 :
179 : /* workspace query and memory allocation */
180 185 : lwork = -1;
181 : #if defined(PETSC_USE_COMPLEX)
182 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&n,A,&ld,B,&ld,NULL,NULL,NULL,&ld,W,&ld,&a,&lwork,NULL,&info));
183 : PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(a),&lwork));
184 : PetscCall(DSAllocateWork_Private(ds,lwork+2*ds->n,8*ds->n,0));
185 : alpha = ds->work;
186 : beta = ds->work + ds->n;
187 : work = ds->work + 2*ds->n;
188 : #else
189 185 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&n,A,&ld,B,&ld,NULL,NULL,NULL,NULL,&ld,W,&ld,&a,&lwork,&info));
190 185 : PetscCall(PetscBLASIntCast((PetscInt)a,&lwork));
191 185 : PetscCall(DSAllocateWork_Private(ds,lwork+3*ds->n,0,0));
192 185 : alpha = ds->work;
193 185 : beta = ds->work + ds->n;
194 185 : alphai = ds->work + 2*ds->n;
195 185 : work = ds->work + 3*ds->n;
196 : #endif
197 :
198 185 : sigma = 0.0;
199 185 : if (ds->sc->comparison==SlepcCompareTargetMagnitude || ds->sc->comparison==SlepcCompareTargetReal) sigma = *(PetscScalar*)ds->sc->comparisonctx;
200 185 : lambda = sigma;
201 185 : tol = n*PETSC_MACHINE_EPSILON/PetscSqrtReal(PETSC_SQRT_MACHINE_EPSILON);
202 :
203 577 : for (it=0;it<maxit;it++) {
204 :
205 : /* evaluate T and T' */
206 577 : PetscCall(DSNEPComputeMatrix(ds,lambda,PETSC_FALSE,DS_MAT_A));
207 577 : if (it) {
208 392 : PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,A,&ld,X,&one,&szero,X+ld,&one));
209 392 : norm = BLASnrm2_(&n,X+ld,&one);
210 392 : if (norm/PetscAbsScalar(lambda)<=tol) break;
211 : }
212 392 : PetscCall(DSNEPComputeMatrix(ds,lambda,PETSC_TRUE,DS_MAT_B));
213 :
214 : /* compute eigenvalue correction mu and eigenvector u */
215 : #if defined(PETSC_USE_COMPLEX)
216 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&n,A,&ld,B,&ld,alpha,beta,NULL,&ld,W,&ld,work,&lwork,ds->rwork,&info));
217 : #else
218 392 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&n,A,&ld,B,&ld,alpha,alphai,beta,NULL,&ld,W,&ld,work,&lwork,&info));
219 : #endif
220 392 : SlepcCheckLapackInfo(LAPGEEV,info);
221 :
222 : /* find smallest eigenvalue */
223 392 : j = 0;
224 392 : if (beta[j]==0.0) re = (PetscRealPart(alpha[j])>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
225 392 : else re = alpha[j]/beta[j];
226 : #if !defined(PETSC_USE_COMPLEX)
227 392 : if (beta[j]==0.0) im = (alphai[j]>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
228 392 : else im = alphai[j]/beta[j];
229 : #endif
230 : pos = 0;
231 1861 : for (j=1;j<n;j++) {
232 1469 : if (beta[j]==0.0) re2 = (PetscRealPart(alpha[j])>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
233 1469 : else re2 = alpha[j]/beta[j];
234 : #if !defined(PETSC_USE_COMPLEX)
235 1469 : if (beta[j]==0.0) im2 = (alphai[j]>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
236 1469 : else im2 = alphai[j]/beta[j];
237 1469 : PetscCall(SlepcCompareSmallestMagnitude(re,im,re2,im2,&result,NULL));
238 : #else
239 : PetscCall(SlepcCompareSmallestMagnitude(re,0.0,re2,0.0,&result,NULL));
240 : #endif
241 1469 : if (result > 0) {
242 938 : re = re2;
243 : #if !defined(PETSC_USE_COMPLEX)
244 938 : im = im2;
245 : #endif
246 938 : pos = j;
247 : }
248 : }
249 :
250 : #if !defined(PETSC_USE_COMPLEX)
251 392 : PetscCheck(im==0.0,PETSC_COMM_SELF,PETSC_ERR_SUP,"DSNEP found a complex eigenvalue; try rerunning with complex scalars");
252 : #endif
253 392 : mu = alpha[pos]/beta[pos];
254 392 : PetscCall(PetscArraycpy(X,W+pos*ld,n));
255 392 : norm = BLASnrm2_(&n,X,&one);
256 392 : PetscCallBLAS("LAPACKlascl",LAPACKlascl_("G",&zero,&zero,&norm,&done,&n,&one,X,&n,&info));
257 392 : SlepcCheckLapackInfo("lascl",info);
258 :
259 : /* correct eigenvalue approximation */
260 392 : lambda = lambda - mu;
261 : }
262 185 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_A],&A));
263 185 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_B],&B));
264 185 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_W],&W));
265 185 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_X],&X));
266 :
267 185 : PetscCheck(it<maxit,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"DSNEP did not converge");
268 185 : ds->t = 1;
269 185 : wr[0] = lambda;
270 185 : if (wi) wi[0] = 0.0;
271 185 : PetscFunctionReturn(PETSC_SUCCESS);
272 : }
273 :
274 : #if defined(PETSC_USE_COMPLEX)
275 : /*
276 : Newton refinement for eigenpairs computed with contour integral.
277 : k - number of eigenpairs to refine
278 : wr - eigenvalues (eigenvectors are stored in DS_MAT_X)
279 : */
280 : static PetscErrorCode DSNEPNewtonRefine(DS ds,PetscInt k,PetscScalar *wr)
281 : {
282 : DS_NEP *ctx = (DS_NEP*)ds->data;
283 : PetscScalar *X,*W,*U,*R,sone=1.0,szero=0.0;
284 : PetscReal norm;
285 : PetscInt i,j,ii,nwu=0,*p,jstart=0,jend=k;
286 : const PetscInt *range;
287 : PetscBLASInt n,*perm,info,ld,one=1,n1;
288 : PetscMPIInt len,size,root;
289 : PetscLayout map;
290 :
291 : PetscFunctionBegin;
292 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_X],&X));
293 : PetscCall(PetscBLASIntCast(ds->n,&n));
294 : PetscCall(PetscBLASIntCast(ds->ld,&ld));
295 : n1 = n+1;
296 : p = ds->perm;
297 : PetscCall(PetscArrayzero(p,k));
298 : PetscCall(DSAllocateWork_Private(ds,(n+2)*(n+1),0,n+1));
299 : U = ds->work+nwu; nwu += (n+1)*(n+1);
300 : R = ds->work+nwu; /*nwu += n+1;*/
301 : perm = ds->iwork;
302 : if (ds->pmode==DS_PARALLEL_DISTRIBUTED) {
303 : PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)ds),PETSC_DECIDE,k,1,&map));
304 : PetscCall(PetscLayoutGetRange(map,&jstart,&jend));
305 : }
306 : for (ii=0;ii<ctx->Nit;ii++) {
307 : for (j=jstart;j<jend;j++) {
308 : if (p[j]<2) {
309 : PetscCall(DSNEPComputeMatrix(ds,wr[j],PETSC_FALSE,DS_MAT_W));
310 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_W],&W));
311 : PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,W,&ld,X+ld*j,&one,&szero,R,&one));
312 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_W],&W));
313 : norm = BLASnrm2_(&n,R,&one);
314 : if (norm/PetscAbsScalar(wr[j]) > ctx->rtol) {
315 : PetscCall(PetscInfo(NULL,"Refining eigenpair %" PetscInt_FMT ", residual=%g\n",j,(double)(norm/PetscAbsScalar(wr[j]))));
316 : p[j] = 1;
317 : R[n] = 0.0;
318 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_W],&W));
319 : for (i=0;i<n;i++) {
320 : PetscCall(PetscArraycpy(U+i*n1,W+i*ld,n));
321 : U[n+i*n1] = PetscConj(X[j*ld+i]);
322 : }
323 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_W],&W));
324 : U[n+n*n1] = 0.0;
325 : PetscCall(DSNEPComputeMatrix(ds,wr[j],PETSC_TRUE,DS_MAT_W));
326 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_W],&W));
327 : PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,W,&ld,X+ld*j,&one,&szero,U+n*(n+1),&one));
328 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_W],&W));
329 : /* solve system */
330 : PetscCallBLAS("LAPACKgetrf",LAPACKgetrf_(&n1,&n1,U,&n1,perm,&info));
331 : SlepcCheckLapackInfo("getrf",info);
332 : PetscCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&n1,&one,U,&n1,perm,R,&n1,&info));
333 : SlepcCheckLapackInfo("getrs",info);
334 : wr[j] -= R[n];
335 : for (i=0;i<n;i++) X[j*ld+i] -= R[i];
336 : /* normalization */
337 : norm = BLASnrm2_(&n,X+ld*j,&one);
338 : for (i=0;i<n;i++) X[ld*j+i] /= norm;
339 : } else p[j] = 2;
340 : }
341 : }
342 : }
343 : if (ds->pmode==DS_PARALLEL_DISTRIBUTED) { /* communicate results */
344 : PetscCall(PetscMPIIntCast(k,&len));
345 : PetscCall(MPIU_Allreduce(MPI_IN_PLACE,p,len,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)ds)));
346 : PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ds),&size));
347 : PetscCall(PetscLayoutGetRanges(map,&range));
348 : for (j=0;j<k;j++) {
349 : if (p[j]) { /* j-th eigenpair has been refined */
350 : for (root=0;root<size;root++) if (range[root+1]>j) break;
351 : PetscCall(PetscMPIIntCast(1,&len));
352 : PetscCallMPI(MPI_Bcast(wr+j,len,MPIU_SCALAR,root,PetscObjectComm((PetscObject)ds)));
353 : PetscCall(PetscMPIIntCast(n,&len));
354 : PetscCallMPI(MPI_Bcast(X+ld*j,len,MPIU_SCALAR,root,PetscObjectComm((PetscObject)ds)));
355 : }
356 : }
357 : PetscCall(PetscLayoutDestroy(&map));
358 : }
359 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_X],&X));
360 : PetscFunctionReturn(PETSC_SUCCESS);
361 : }
362 :
363 : PetscErrorCode DSSolve_NEP_Contour(DS ds,PetscScalar *wr,PetscScalar *wi)
364 : {
365 : DS_NEP *ctx = (DS_NEP*)ds->data;
366 : PetscScalar *alpha,*beta,*Q,*Z,*X,*U,*V,*W,*work,*Rc,*R,*w,*z,*zn,*S;
367 : PetscScalar sone=1.0,szero=0.0,center,a;
368 : PetscReal *rwork,norm,radius,vscale,rgscale,*sigma;
369 : PetscBLASInt info,n,*perm,p,pp,ld,lwork,k_,rk_,colA,rowA,one=1;
370 : PetscInt mid,lds,nnod=ctx->nnod,k,i,ii,jj,j,s,off,rk,nwu=0,nw,lrwork,*inside,kstart=0,kend=nnod;
371 : PetscMPIInt len;
372 : PetscBool isellipse;
373 : PetscRandom rand;
374 :
375 : PetscFunctionBegin;
376 : PetscCheck(ctx->rg,PetscObjectComm((PetscObject)ds),PETSC_ERR_ORDER,"The contour solver requires a region passed with DSNEPSetRG()");
377 : /* Contour parameters */
378 : PetscCall(PetscObjectTypeCompare((PetscObject)ctx->rg,RGELLIPSE,&isellipse));
379 : PetscCheck(isellipse,PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Region must be Ellipse");
380 : PetscCall(RGEllipseGetParameters(ctx->rg,¢er,&radius,&vscale));
381 : PetscCall(RGGetScale(ctx->rg,&rgscale));
382 : if (ds->pmode==DS_PARALLEL_DISTRIBUTED) {
383 : if (!ctx->map) PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)ds),PETSC_DECIDE,ctx->nnod,1,&ctx->map));
384 : PetscCall(PetscLayoutGetRange(ctx->map,&kstart,&kend));
385 : }
386 :
387 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_W)); /* size n */
388 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_Q)); /* size mid*n */
389 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_Z)); /* size mid*n */
390 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_U)); /* size mid*n */
391 : PetscCall(DSAllocateMat_Private(ds,DS_MAT_V)); /* size mid*n */
392 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_Q],&Q));
393 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_Z],&Z));
394 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_U],&U));
395 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_V],&V));
396 : mid = ctx->max_mid;
397 : PetscCall(PetscBLASIntCast(ds->n,&n));
398 : p = n; /* maximum number of columns for the probing matrix */
399 : PetscCall(PetscBLASIntCast(ds->ld,&ld));
400 : PetscCall(PetscBLASIntCast(mid*n,&rowA));
401 : nw = 2*n*(p+mid)+3*nnod+2*mid*n*p;
402 : lrwork = 9*mid*n;
403 :
404 : /* workspace query and memory allocation */
405 : lwork = -1;
406 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&rowA,Q,&rowA,Z,&rowA,NULL,NULL,NULL,&ld,V,&rowA,&a,&lwork,NULL,&info));
407 : PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(a),&lwork));
408 : PetscCall(DSAllocateWork_Private(ds,lwork+nw,lrwork,n+1));
409 :
410 : sigma = ds->rwork;
411 : rwork = ds->rwork+mid*n;
412 : perm = ds->iwork;
413 : z = ds->work+nwu; nwu += nnod; /* quadrature points */
414 : zn = ds->work+nwu; nwu += nnod; /* normalized quadrature points */
415 : w = ds->work+nwu; nwu += nnod; /* quadrature weights */
416 : Rc = ds->work+nwu; nwu += n*p;
417 : R = ds->work+nwu; nwu += n*p;
418 : alpha = ds->work+nwu; nwu += mid*n;
419 : beta = ds->work+nwu; nwu += mid*n;
420 : S = ds->work+nwu; nwu += 2*mid*n*p;
421 : work = ds->work+nwu;
422 :
423 : /* Compute quadrature parameters */
424 : PetscCall(RGComputeQuadrature(ctx->rg,RG_QUADRULE_TRAPEZOIDAL,nnod,z,zn,w));
425 :
426 : /* Set random matrix */
427 : PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)ds),&rand));
428 : PetscCall(PetscRandomSetSeed(rand,0x12345678));
429 : PetscCall(PetscRandomSeed(rand));
430 : for (j=0;j<p;j++)
431 : for (i=0;i<n;i++) PetscCall(PetscRandomGetValue(rand,Rc+i+j*n));
432 : PetscCall(PetscArrayzero(S,2*mid*n*p));
433 : /* Loop of integration points */
434 : for (k=kstart;k<kend;k++) {
435 : PetscCall(PetscInfo(NULL,"Solving integration point %" PetscInt_FMT "\n",k));
436 : PetscCall(PetscArraycpy(R,Rc,p*n));
437 : PetscCall(DSNEPComputeMatrix(ds,z[k],PETSC_FALSE,DS_MAT_W));
438 :
439 : /* LU factorization */
440 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_W],&W));
441 : PetscCallBLAS("LAPACKgetrf",LAPACKgetrf_(&n,&n,W,&ld,perm,&info));
442 : SlepcCheckLapackInfo("getrf",info);
443 : PetscCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&n,&p,W,&ld,perm,R,&n,&info));
444 : SlepcCheckLapackInfo("getrs",info);
445 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_W],&W));
446 :
447 : /* Moments computation */
448 : for (s=0;s<2*ctx->max_mid;s++) {
449 : off = s*n*p;
450 : for (j=0;j<p;j++)
451 : for (i=0;i<n;i++) S[off+i+j*n] += w[k]*R[j*n+i];
452 : w[k] *= zn[k];
453 : }
454 : }
455 :
456 : if (ds->pmode==DS_PARALLEL_DISTRIBUTED) { /* compute final S via reduction */
457 : PetscCall(PetscMPIIntCast(2*mid*n*p,&len));
458 : PetscCall(MPIU_Allreduce(MPI_IN_PLACE,S,len,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)ds)));
459 : }
460 : p = ctx->spls?PetscMin(ctx->spls,n):n;
461 : pp = p;
462 : do {
463 : p = pp;
464 : PetscCall(PetscBLASIntCast(mid*p,&colA));
465 :
466 : PetscCall(PetscInfo(ds,"Computing SVD of size %" PetscBLASInt_FMT "x%" PetscBLASInt_FMT "\n",rowA,colA));
467 : for (jj=0;jj<mid;jj++) {
468 : for (ii=0;ii<mid;ii++) {
469 : off = jj*p*rowA+ii*n;
470 : for (j=0;j<p;j++)
471 : for (i=0;i<n;i++) Q[off+j*rowA+i] = S[((jj+ii)*n+j)*n+i];
472 : }
473 : }
474 : PetscCallBLAS("LAPACKgesvd",LAPACKgesvd_("S","S",&rowA,&colA,Q,&rowA,sigma,U,&rowA,V,&colA,work,&lwork,rwork,&info));
475 : SlepcCheckLapackInfo("gesvd",info);
476 :
477 : rk = colA;
478 : for (i=1;i<colA;i++) if (sigma[i]/sigma[0]<PETSC_MACHINE_EPSILON*1e4) {rk = i; break;}
479 : if (rk<colA || p==n) break;
480 : pp *= 2;
481 : } while (pp<=n);
482 : PetscCall(PetscInfo(ds,"Solving generalized eigenproblem of size %" PetscInt_FMT "\n",rk));
483 : for (jj=0;jj<mid;jj++) {
484 : for (ii=0;ii<mid;ii++) {
485 : off = jj*p*rowA+ii*n;
486 : for (j=0;j<p;j++)
487 : for (i=0;i<n;i++) Q[off+j*rowA+i] = S[((jj+ii+1)*n+j)*n+i];
488 : }
489 : }
490 : PetscCall(PetscBLASIntCast(rk,&rk_));
491 : PetscCallBLAS("BLASgemm",BLASgemm_("N","C",&rowA,&rk_,&colA,&sone,Q,&rowA,V,&colA,&szero,Z,&rowA));
492 : PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&rk_,&rk_,&rowA,&sone,U,&rowA,Z,&rowA,&szero,Q,&rk_));
493 : PetscCall(PetscArrayzero(Z,n*mid*n*mid));
494 : for (j=0;j<rk;j++) Z[j+j*rk_] = sigma[j];
495 : PetscCallBLAS("LAPACK" LAPGEEV,LAPACKggevalt_("N","V",&rk_,Q,&rk_,Z,&rk_,alpha,beta,NULL,&ld,V,&rk_,work,&lwork,rwork,&info));
496 : SlepcCheckLapackInfo(LAPGEEV,info);
497 : for (i=0;i<rk;i++) wr[i] = (center+radius*alpha[i]/beta[i])*rgscale;
498 : PetscCall(PetscMalloc1(rk,&inside));
499 : PetscCall(RGCheckInside(ctx->rg,rk,wr,wi,inside));
500 : k=0;
501 : for (i=0;i<rk;i++)
502 : if (inside[i]==1) inside[k++] = i;
503 : /* Discard values outside region */
504 : lds = ld*mid;
505 : PetscCall(PetscArrayzero(Q,lds*lds));
506 : PetscCall(PetscArrayzero(Z,lds*lds));
507 : for (i=0;i<k;i++) Q[i+i*lds] = (center*beta[inside[i]]+radius*alpha[inside[i]])*rgscale;
508 : for (i=0;i<k;i++) Z[i+i*lds] = beta[inside[i]];
509 : for (i=0;i<k;i++) wr[i] = Q[i+i*lds]/Z[i+i*lds];
510 : for (j=0;j<k;j++) for (i=0;i<rk;i++) V[j*rk+i] = sigma[i]*V[inside[j]*rk+i];
511 : PetscCall(PetscBLASIntCast(k,&k_));
512 : PetscCall(MatDenseGetArray(ds->omat[DS_MAT_X],&X));
513 : PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n,&k_,&rk_,&sone,U,&rowA,V,&rk_,&szero,X,&ld));
514 : /* Normalize */
515 : for (j=0;j<k;j++) {
516 : norm = BLASnrm2_(&n,X+ld*j,&one);
517 : for (i=0;i<n;i++) X[ld*j+i] /= norm;
518 : }
519 : PetscCall(PetscFree(inside));
520 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_X],&X));
521 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_Q],&Q));
522 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_Z],&Z));
523 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_U],&U));
524 : PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_V],&V));
525 :
526 : /* Newton refinement */
527 : if (ctx->Nit) PetscCall(DSNEPNewtonRefine(ds,k,wr));
528 : ds->t = k;
529 : PetscCall(PetscRandomDestroy(&rand));
530 : PetscFunctionReturn(PETSC_SUCCESS);
531 : }
532 : #endif
533 :
534 : #if !defined(PETSC_HAVE_MPIUNI)
535 44 : static PetscErrorCode DSSynchronize_NEP(DS ds,PetscScalar eigr[],PetscScalar eigi[])
536 : {
537 44 : DS_NEP *ctx = (DS_NEP*)ds->data;
538 44 : PetscInt ld=ds->ld,k=0;
539 44 : PetscMPIInt n,n2,rank,size,off=0;
540 44 : PetscScalar *X;
541 :
542 44 : PetscFunctionBegin;
543 44 : if (!ds->method) { /* SLP */
544 44 : if (ds->state>=DS_STATE_CONDENSED) k += ds->n;
545 44 : if (eigr) k += 1;
546 44 : if (eigi) k += 1;
547 44 : PetscCall(PetscMPIIntCast(1,&n));
548 44 : PetscCall(PetscMPIIntCast(ds->n,&n2));
549 : } else { /* Contour */
550 0 : if (ds->state>=DS_STATE_CONDENSED) k += ctx->max_mid*ds->n*ld;
551 0 : if (eigr) k += ctx->max_mid*ds->n;
552 0 : if (eigi) k += ctx->max_mid*ds->n;
553 0 : PetscCall(PetscMPIIntCast(ctx->max_mid*ds->n,&n));
554 0 : PetscCall(PetscMPIIntCast(ctx->max_mid*ds->n*ld,&n2));
555 : }
556 44 : PetscCall(DSAllocateWork_Private(ds,k,0,0));
557 44 : PetscCall(PetscMPIIntCast(k*sizeof(PetscScalar),&size));
558 44 : if (ds->state>=DS_STATE_CONDENSED) PetscCall(MatDenseGetArray(ds->omat[DS_MAT_X],&X));
559 44 : PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ds),&rank));
560 44 : if (!rank) {
561 22 : if (ds->state>=DS_STATE_CONDENSED) PetscCallMPI(MPI_Pack(X,n2,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
562 22 : if (eigr) PetscCallMPI(MPI_Pack(eigr,n,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
563 : #if !defined(PETSC_USE_COMPLEX)
564 22 : if (eigi) PetscCallMPI(MPI_Pack(eigi,n,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
565 : #endif
566 : }
567 88 : PetscCallMPI(MPI_Bcast(ds->work,size,MPI_BYTE,0,PetscObjectComm((PetscObject)ds)));
568 44 : if (rank) {
569 22 : if (ds->state>=DS_STATE_CONDENSED) PetscCallMPI(MPI_Unpack(ds->work,size,&off,X,n2,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
570 22 : if (eigr) PetscCallMPI(MPI_Unpack(ds->work,size,&off,eigr,n,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
571 : #if !defined(PETSC_USE_COMPLEX)
572 22 : if (eigi) PetscCallMPI(MPI_Unpack(ds->work,size,&off,eigi,n,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
573 : #endif
574 : }
575 44 : if (ds->state>=DS_STATE_CONDENSED) PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_X],&X));
576 44 : PetscFunctionReturn(PETSC_SUCCESS);
577 : }
578 : #endif
579 :
580 20 : static PetscErrorCode DSNEPSetFN_NEP(DS ds,PetscInt n,FN fn[])
581 : {
582 20 : DS_NEP *ctx = (DS_NEP*)ds->data;
583 20 : PetscInt i;
584 :
585 20 : PetscFunctionBegin;
586 20 : PetscCheck(n>0,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more functions, you have %" PetscInt_FMT,n);
587 20 : PetscCheck(n<=DS_NUM_EXTRA,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Too many functions, you specified %" PetscInt_FMT " but the limit is %d",n,DS_NUM_EXTRA);
588 20 : if (ds->ld) PetscCall(PetscInfo(ds,"DSNEPSetFN() called after DSAllocate()\n"));
589 80 : for (i=0;i<n;i++) PetscCall(PetscObjectReference((PetscObject)fn[i]));
590 20 : for (i=0;i<ctx->nf;i++) PetscCall(FNDestroy(&ctx->f[i]));
591 80 : for (i=0;i<n;i++) ctx->f[i] = fn[i];
592 20 : ctx->nf = n;
593 20 : PetscFunctionReturn(PETSC_SUCCESS);
594 : }
595 :
596 : /*@
597 : DSNEPSetFN - Sets a number of functions that define the nonlinear
598 : eigenproblem.
599 :
600 : Collective
601 :
602 : Input Parameters:
603 : + ds - the direct solver context
604 : . n - number of functions
605 : - fn - array of functions
606 :
607 : Notes:
608 : The nonlinear eigenproblem is defined in terms of the split nonlinear
609 : operator T(lambda) = sum_i A_i*f_i(lambda).
610 :
611 : This function must be called before DSAllocate(). Then DSAllocate()
612 : will allocate an extra matrix A_i per each function, that can be
613 : filled in the usual way.
614 :
615 : Level: advanced
616 :
617 : .seealso: DSNEPGetFN(), DSAllocate()
618 : @*/
619 20 : PetscErrorCode DSNEPSetFN(DS ds,PetscInt n,FN fn[])
620 : {
621 20 : PetscInt i;
622 :
623 20 : PetscFunctionBegin;
624 20 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
625 80 : PetscValidLogicalCollectiveInt(ds,n,2);
626 20 : PetscAssertPointer(fn,3);
627 80 : for (i=0;i<n;i++) {
628 60 : PetscValidHeaderSpecific(fn[i],FN_CLASSID,3);
629 60 : PetscCheckSameComm(ds,1,fn[i],3);
630 : }
631 20 : PetscTryMethod(ds,"DSNEPSetFN_C",(DS,PetscInt,FN[]),(ds,n,fn));
632 20 : PetscFunctionReturn(PETSC_SUCCESS);
633 : }
634 :
635 3 : static PetscErrorCode DSNEPGetFN_NEP(DS ds,PetscInt k,FN *fn)
636 : {
637 3 : DS_NEP *ctx = (DS_NEP*)ds->data;
638 :
639 3 : PetscFunctionBegin;
640 3 : PetscCheck(k>=0 && k<ctx->nf,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,ctx->nf-1);
641 3 : *fn = ctx->f[k];
642 3 : PetscFunctionReturn(PETSC_SUCCESS);
643 : }
644 :
645 : /*@
646 : DSNEPGetFN - Gets the functions associated with the nonlinear DS.
647 :
648 : Not Collective
649 :
650 : Input Parameters:
651 : + ds - the direct solver context
652 : - k - the index of the requested function (starting in 0)
653 :
654 : Output Parameter:
655 : . fn - the function
656 :
657 : Level: advanced
658 :
659 : .seealso: DSNEPSetFN()
660 : @*/
661 3 : PetscErrorCode DSNEPGetFN(DS ds,PetscInt k,FN *fn)
662 : {
663 3 : PetscFunctionBegin;
664 3 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
665 3 : PetscAssertPointer(fn,3);
666 3 : PetscUseMethod(ds,"DSNEPGetFN_C",(DS,PetscInt,FN*),(ds,k,fn));
667 3 : PetscFunctionReturn(PETSC_SUCCESS);
668 : }
669 :
670 2 : static PetscErrorCode DSNEPGetNumFN_NEP(DS ds,PetscInt *n)
671 : {
672 2 : DS_NEP *ctx = (DS_NEP*)ds->data;
673 :
674 2 : PetscFunctionBegin;
675 2 : *n = ctx->nf;
676 2 : PetscFunctionReturn(PETSC_SUCCESS);
677 : }
678 :
679 : /*@
680 : DSNEPGetNumFN - Returns the number of functions stored internally by
681 : the DS.
682 :
683 : Not Collective
684 :
685 : Input Parameter:
686 : . ds - the direct solver context
687 :
688 : Output Parameters:
689 : . n - the number of functions passed in DSNEPSetFN()
690 :
691 : Level: advanced
692 :
693 : .seealso: DSNEPSetFN()
694 : @*/
695 2 : PetscErrorCode DSNEPGetNumFN(DS ds,PetscInt *n)
696 : {
697 2 : PetscFunctionBegin;
698 2 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
699 2 : PetscAssertPointer(n,2);
700 2 : PetscUseMethod(ds,"DSNEPGetNumFN_C",(DS,PetscInt*),(ds,n));
701 2 : PetscFunctionReturn(PETSC_SUCCESS);
702 : }
703 :
704 1 : static PetscErrorCode DSNEPSetMinimality_NEP(DS ds,PetscInt n)
705 : {
706 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
707 :
708 1 : PetscFunctionBegin;
709 1 : if (n == PETSC_DECIDE || n == PETSC_DEFAULT) ctx->max_mid = 4;
710 : else {
711 1 : PetscCheck(n>0,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The minimality value must be > 0");
712 1 : ctx->max_mid = n;
713 : }
714 1 : PetscFunctionReturn(PETSC_SUCCESS);
715 : }
716 :
717 : /*@
718 : DSNEPSetMinimality - Sets the maximum minimality index used internally by
719 : the DSNEP.
720 :
721 : Logically Collective
722 :
723 : Input Parameters:
724 : + ds - the direct solver context
725 : - n - the maximum minimality index
726 :
727 : Options Database Key:
728 : . -ds_nep_minimality <n> - sets the maximum minimality index
729 :
730 : Notes:
731 : The maximum minimality index is used only in the contour integral method,
732 : and is related to the highest momemts used in the method. The default
733 : value is 1, an larger value might give better accuracy in some cases, but
734 : at a higher cost.
735 :
736 : Level: advanced
737 :
738 : .seealso: DSNEPGetMinimality()
739 : @*/
740 1 : PetscErrorCode DSNEPSetMinimality(DS ds,PetscInt n)
741 : {
742 1 : PetscFunctionBegin;
743 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
744 4 : PetscValidLogicalCollectiveInt(ds,n,2);
745 1 : PetscTryMethod(ds,"DSNEPSetMinimality_C",(DS,PetscInt),(ds,n));
746 1 : PetscFunctionReturn(PETSC_SUCCESS);
747 : }
748 :
749 21 : static PetscErrorCode DSNEPGetMinimality_NEP(DS ds,PetscInt *n)
750 : {
751 21 : DS_NEP *ctx = (DS_NEP*)ds->data;
752 :
753 21 : PetscFunctionBegin;
754 21 : *n = ctx->max_mid;
755 21 : PetscFunctionReturn(PETSC_SUCCESS);
756 : }
757 :
758 : /*@
759 : DSNEPGetMinimality - Returns the maximum minimality index used internally by
760 : the DSNEP.
761 :
762 : Not Collective
763 :
764 : Input Parameter:
765 : . ds - the direct solver context
766 :
767 : Output Parameters:
768 : . n - the maximum minimality index passed in DSNEPSetMinimality()
769 :
770 : Level: advanced
771 :
772 : .seealso: DSNEPSetMinimality()
773 : @*/
774 21 : PetscErrorCode DSNEPGetMinimality(DS ds,PetscInt *n)
775 : {
776 21 : PetscFunctionBegin;
777 21 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
778 21 : PetscAssertPointer(n,2);
779 21 : PetscUseMethod(ds,"DSNEPGetMinimality_C",(DS,PetscInt*),(ds,n));
780 21 : PetscFunctionReturn(PETSC_SUCCESS);
781 : }
782 :
783 2 : static PetscErrorCode DSNEPSetRefine_NEP(DS ds,PetscReal tol,PetscInt its)
784 : {
785 2 : DS_NEP *ctx = (DS_NEP*)ds->data;
786 :
787 2 : PetscFunctionBegin;
788 2 : if (tol == (PetscReal)PETSC_DEFAULT) ctx->rtol = PETSC_MACHINE_EPSILON/PetscSqrtReal(PETSC_SQRT_MACHINE_EPSILON);
789 : else {
790 1 : PetscCheck(tol>0.0,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The tolerance must be > 0");
791 1 : ctx->rtol = tol;
792 : }
793 2 : if (its == PETSC_DECIDE || its == PETSC_DEFAULT) ctx->Nit = 3;
794 : else {
795 1 : PetscCheck(its>=0,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The number of iterations must be >= 0");
796 1 : ctx->Nit = its;
797 : }
798 2 : PetscFunctionReturn(PETSC_SUCCESS);
799 : }
800 :
801 : /*@
802 : DSNEPSetRefine - Sets the tolerance and the number of iterations of Newton iterative
803 : refinement for eigenpairs.
804 :
805 : Logically Collective
806 :
807 : Input Parameters:
808 : + ds - the direct solver context
809 : . tol - the tolerance
810 : - its - the number of iterations
811 :
812 : Options Database Key:
813 : + -ds_nep_refine_tol <tol> - sets the tolerance
814 : - -ds_nep_refine_its <its> - sets the number of Newton iterations
815 :
816 : Notes:
817 : Iterative refinement of eigenpairs is currently used only in the contour
818 : integral method.
819 :
820 : Level: advanced
821 :
822 : .seealso: DSNEPGetRefine()
823 : @*/
824 2 : PetscErrorCode DSNEPSetRefine(DS ds,PetscReal tol,PetscInt its)
825 : {
826 2 : PetscFunctionBegin;
827 2 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
828 8 : PetscValidLogicalCollectiveReal(ds,tol,2);
829 8 : PetscValidLogicalCollectiveInt(ds,its,3);
830 2 : PetscTryMethod(ds,"DSNEPSetRefine_C",(DS,PetscReal,PetscInt),(ds,tol,its));
831 2 : PetscFunctionReturn(PETSC_SUCCESS);
832 : }
833 :
834 1 : static PetscErrorCode DSNEPGetRefine_NEP(DS ds,PetscReal *tol,PetscInt *its)
835 : {
836 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
837 :
838 1 : PetscFunctionBegin;
839 1 : if (tol) *tol = ctx->rtol;
840 1 : if (its) *its = ctx->Nit;
841 1 : PetscFunctionReturn(PETSC_SUCCESS);
842 : }
843 :
844 : /*@
845 : DSNEPGetRefine - Returns the tolerance and the number of iterations of Newton iterative
846 : refinement for eigenpairs.
847 :
848 : Not Collective
849 :
850 : Input Parameter:
851 : . ds - the direct solver context
852 :
853 : Output Parameters:
854 : + tol - the tolerance
855 : - its - the number of iterations
856 :
857 : Level: advanced
858 :
859 : .seealso: DSNEPSetRefine()
860 : @*/
861 1 : PetscErrorCode DSNEPGetRefine(DS ds,PetscReal *tol,PetscInt *its)
862 : {
863 1 : PetscFunctionBegin;
864 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
865 1 : PetscUseMethod(ds,"DSNEPGetRefine_C",(DS,PetscReal*,PetscInt*),(ds,tol,its));
866 1 : PetscFunctionReturn(PETSC_SUCCESS);
867 : }
868 :
869 1 : static PetscErrorCode DSNEPSetIntegrationPoints_NEP(DS ds,PetscInt ip)
870 : {
871 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
872 :
873 1 : PetscFunctionBegin;
874 1 : if (ip == PETSC_DECIDE || ip == PETSC_DEFAULT) ctx->nnod = 64;
875 : else {
876 1 : PetscCheck(ip>0,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The number of integration points must be > 0");
877 1 : ctx->nnod = ip;
878 : }
879 1 : PetscCall(PetscLayoutDestroy(&ctx->map)); /* need to redistribute at next solve */
880 1 : PetscFunctionReturn(PETSC_SUCCESS);
881 : }
882 :
883 : /*@
884 : DSNEPSetIntegrationPoints - Sets the number of integration points to be
885 : used in the contour integral method.
886 :
887 : Logically Collective
888 :
889 : Input Parameters:
890 : + ds - the direct solver context
891 : - ip - the number of integration points
892 :
893 : Options Database Key:
894 : . -ds_nep_integration_points <ip> - sets the number of integration points
895 :
896 : Notes:
897 : This parameter is relevant only in the contour integral method.
898 :
899 : Level: advanced
900 :
901 : .seealso: DSNEPGetIntegrationPoints()
902 : @*/
903 1 : PetscErrorCode DSNEPSetIntegrationPoints(DS ds,PetscInt ip)
904 : {
905 1 : PetscFunctionBegin;
906 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
907 4 : PetscValidLogicalCollectiveInt(ds,ip,2);
908 1 : PetscTryMethod(ds,"DSNEPSetIntegrationPoints_C",(DS,PetscInt),(ds,ip));
909 1 : PetscFunctionReturn(PETSC_SUCCESS);
910 : }
911 :
912 1 : static PetscErrorCode DSNEPGetIntegrationPoints_NEP(DS ds,PetscInt *ip)
913 : {
914 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
915 :
916 1 : PetscFunctionBegin;
917 1 : *ip = ctx->nnod;
918 1 : PetscFunctionReturn(PETSC_SUCCESS);
919 : }
920 :
921 : /*@
922 : DSNEPGetIntegrationPoints - Returns the number of integration points used
923 : in the contour integral method.
924 :
925 : Not Collective
926 :
927 : Input Parameter:
928 : . ds - the direct solver context
929 :
930 : Output Parameters:
931 : . ip - the number of integration points
932 :
933 : Level: advanced
934 :
935 : .seealso: DSNEPSetIntegrationPoints()
936 : @*/
937 1 : PetscErrorCode DSNEPGetIntegrationPoints(DS ds,PetscInt *ip)
938 : {
939 1 : PetscFunctionBegin;
940 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
941 1 : PetscAssertPointer(ip,2);
942 1 : PetscUseMethod(ds,"DSNEPGetIntegrationPoints_C",(DS,PetscInt*),(ds,ip));
943 1 : PetscFunctionReturn(PETSC_SUCCESS);
944 : }
945 :
946 1 : static PetscErrorCode DSNEPSetSamplingSize_NEP(DS ds,PetscInt p)
947 : {
948 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
949 :
950 1 : PetscFunctionBegin;
951 1 : if (p == PETSC_DECIDE || p == PETSC_DEFAULT) ctx->spls = 0;
952 : else {
953 1 : PetscCheck(p>=20,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The sample size cannot be smaller than 20");
954 1 : ctx->spls = p;
955 : }
956 1 : PetscFunctionReturn(PETSC_SUCCESS);
957 : }
958 :
959 : /*@
960 : DSNEPSetSamplingSize - Sets the number of sampling columns to be
961 : used in the contour integral method.
962 :
963 : Logically Collective
964 :
965 : Input Parameters:
966 : + ds - the direct solver context
967 : - p - the number of columns for the sampling matrix
968 :
969 : Options Database Key:
970 : . -ds_nep_sampling_size <p> - sets the number of sampling columns
971 :
972 : Notes:
973 : This parameter is relevant only in the contour integral method.
974 :
975 : Level: advanced
976 :
977 : .seealso: DSNEPGetSamplingSize()
978 : @*/
979 1 : PetscErrorCode DSNEPSetSamplingSize(DS ds,PetscInt p)
980 : {
981 1 : PetscFunctionBegin;
982 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
983 4 : PetscValidLogicalCollectiveInt(ds,p,2);
984 1 : PetscTryMethod(ds,"DSNEPSetSamplingSize_C",(DS,PetscInt),(ds,p));
985 1 : PetscFunctionReturn(PETSC_SUCCESS);
986 : }
987 :
988 1 : static PetscErrorCode DSNEPGetSamplingSize_NEP(DS ds,PetscInt *p)
989 : {
990 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
991 :
992 1 : PetscFunctionBegin;
993 1 : *p = ctx->spls;
994 1 : PetscFunctionReturn(PETSC_SUCCESS);
995 : }
996 :
997 : /*@
998 : DSNEPGetSamplingSize - Returns the number of sampling columns used
999 : in the contour integral method.
1000 :
1001 : Not Collective
1002 :
1003 : Input Parameter:
1004 : . ds - the direct solver context
1005 :
1006 : Output Parameters:
1007 : . p - the number of columns for the sampling matrix
1008 :
1009 : Level: advanced
1010 :
1011 : .seealso: DSNEPSetSamplingSize()
1012 : @*/
1013 1 : PetscErrorCode DSNEPGetSamplingSize(DS ds,PetscInt *p)
1014 : {
1015 1 : PetscFunctionBegin;
1016 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
1017 1 : PetscAssertPointer(p,2);
1018 1 : PetscUseMethod(ds,"DSNEPGetSamplingSize_C",(DS,PetscInt*),(ds,p));
1019 1 : PetscFunctionReturn(PETSC_SUCCESS);
1020 : }
1021 :
1022 17 : static PetscErrorCode DSNEPSetComputeMatrixFunction_NEP(DS ds,PetscErrorCode (*fun)(DS,PetscScalar,PetscBool,DSMatType,void*),void *ctx)
1023 : {
1024 17 : DS_NEP *dsctx = (DS_NEP*)ds->data;
1025 :
1026 17 : PetscFunctionBegin;
1027 17 : dsctx->computematrix = fun;
1028 17 : dsctx->computematrixctx = ctx;
1029 17 : PetscFunctionReturn(PETSC_SUCCESS);
1030 : }
1031 :
1032 : /*@C
1033 : DSNEPSetComputeMatrixFunction - Sets a user-provided subroutine to compute
1034 : the matrices T(lambda) or T'(lambda).
1035 :
1036 : Logically Collective
1037 :
1038 : Input Parameters:
1039 : + ds - the direct solver context
1040 : . fun - a pointer to the user function
1041 : - ctx - a context pointer (the last parameter to the user function)
1042 :
1043 : Calling sequence of fun:
1044 : $ PetscErrorCode fun(DS ds,PetscScalar lambda,PetscBool deriv,DSMatType mat,void *ctx)
1045 : + ds - the direct solver object
1046 : . lambda - point where T(lambda) or T'(lambda) must be evaluated
1047 : . deriv - if true compute T'(lambda), otherwise compute T(lambda)
1048 : . mat - the DS matrix where the result must be stored
1049 : - ctx - optional context, as set by DSNEPSetComputeMatrixFunction()
1050 :
1051 : Note:
1052 : The result is computed as T(lambda) = sum_i E_i*f_i(lambda), and similarly
1053 : for the derivative.
1054 :
1055 : Level: developer
1056 :
1057 : .seealso: DSNEPGetComputeMatrixFunction()
1058 : @*/
1059 17 : PetscErrorCode DSNEPSetComputeMatrixFunction(DS ds,PetscErrorCode (*fun)(DS ds,PetscScalar lambda,PetscBool deriv,DSMatType mat,void *ctx),void *ctx)
1060 : {
1061 17 : PetscFunctionBegin;
1062 17 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
1063 17 : PetscTryMethod(ds,"DSNEPSetComputeMatrixFunction_C",(DS,PetscErrorCode (*)(DS,PetscScalar,PetscBool,DSMatType,void*),void*),(ds,fun,ctx));
1064 17 : PetscFunctionReturn(PETSC_SUCCESS);
1065 : }
1066 :
1067 0 : static PetscErrorCode DSNEPGetComputeMatrixFunction_NEP(DS ds,PetscErrorCode (**fun)(DS,PetscScalar,PetscBool,DSMatType,void*),void **ctx)
1068 : {
1069 0 : DS_NEP *dsctx = (DS_NEP*)ds->data;
1070 :
1071 0 : PetscFunctionBegin;
1072 0 : if (fun) *fun = dsctx->computematrix;
1073 0 : if (ctx) *ctx = dsctx->computematrixctx;
1074 0 : PetscFunctionReturn(PETSC_SUCCESS);
1075 : }
1076 :
1077 : /*@C
1078 : DSNEPGetComputeMatrixFunction - Returns the user-provided callback function
1079 : set in DSNEPSetComputeMatrixFunction().
1080 :
1081 : Not Collective
1082 :
1083 : Input Parameter:
1084 : . ds - the direct solver context
1085 :
1086 : Output Parameters:
1087 : + fun - the pointer to the user function
1088 : - ctx - the context pointer
1089 :
1090 : Level: developer
1091 :
1092 : .seealso: DSNEPSetComputeMatrixFunction()
1093 : @*/
1094 0 : PetscErrorCode DSNEPGetComputeMatrixFunction(DS ds,PetscErrorCode (**fun)(DS,PetscScalar,PetscBool,DSMatType,void*),void **ctx)
1095 : {
1096 0 : PetscFunctionBegin;
1097 0 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
1098 0 : PetscUseMethod(ds,"DSNEPGetComputeMatrixFunction_C",(DS,PetscErrorCode (**)(DS,PetscScalar,PetscBool,DSMatType,void*),void**),(ds,fun,ctx));
1099 0 : PetscFunctionReturn(PETSC_SUCCESS);
1100 : }
1101 :
1102 1 : static PetscErrorCode DSNEPSetRG_NEP(DS ds,RG rg)
1103 : {
1104 1 : DS_NEP *dsctx = (DS_NEP*)ds->data;
1105 :
1106 1 : PetscFunctionBegin;
1107 1 : PetscCall(PetscObjectReference((PetscObject)rg));
1108 1 : PetscCall(RGDestroy(&dsctx->rg));
1109 1 : dsctx->rg = rg;
1110 1 : PetscFunctionReturn(PETSC_SUCCESS);
1111 : }
1112 :
1113 : /*@
1114 : DSNEPSetRG - Associates a region object to the DSNEP solver.
1115 :
1116 : Collective
1117 :
1118 : Input Parameters:
1119 : + ds - the direct solver context
1120 : - rg - the region context
1121 :
1122 : Notes:
1123 : The region is used only in the contour integral method, and
1124 : should enclose the wanted eigenvalues.
1125 :
1126 : Level: developer
1127 :
1128 : .seealso: DSNEPGetRG()
1129 : @*/
1130 1 : PetscErrorCode DSNEPSetRG(DS ds,RG rg)
1131 : {
1132 1 : PetscFunctionBegin;
1133 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
1134 1 : if (rg) {
1135 1 : PetscValidHeaderSpecific(rg,RG_CLASSID,2);
1136 1 : PetscCheckSameComm(ds,1,rg,2);
1137 : }
1138 1 : PetscTryMethod(ds,"DSNEPSetRG_C",(DS,RG),(ds,rg));
1139 1 : PetscFunctionReturn(PETSC_SUCCESS);
1140 : }
1141 :
1142 1 : static PetscErrorCode DSNEPGetRG_NEP(DS ds,RG *rg)
1143 : {
1144 1 : DS_NEP *ctx = (DS_NEP*)ds->data;
1145 :
1146 1 : PetscFunctionBegin;
1147 1 : if (!ctx->rg) {
1148 1 : PetscCall(RGCreate(PetscObjectComm((PetscObject)ds),&ctx->rg));
1149 1 : PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->rg,(PetscObject)ds,1));
1150 1 : PetscCall(RGSetOptionsPrefix(ctx->rg,((PetscObject)ds)->prefix));
1151 1 : PetscCall(RGAppendOptionsPrefix(ctx->rg,"ds_nep_"));
1152 1 : PetscCall(PetscObjectSetOptions((PetscObject)ctx->rg,((PetscObject)ds)->options));
1153 : }
1154 1 : *rg = ctx->rg;
1155 1 : PetscFunctionReturn(PETSC_SUCCESS);
1156 : }
1157 :
1158 : /*@
1159 : DSNEPGetRG - Obtain the region object associated to the DSNEP solver.
1160 :
1161 : Collective
1162 :
1163 : Input Parameter:
1164 : . ds - the direct solver context
1165 :
1166 : Output Parameter:
1167 : . rg - the region context
1168 :
1169 : Level: developer
1170 :
1171 : .seealso: DSNEPSetRG()
1172 : @*/
1173 1 : PetscErrorCode DSNEPGetRG(DS ds,RG *rg)
1174 : {
1175 1 : PetscFunctionBegin;
1176 1 : PetscValidHeaderSpecific(ds,DS_CLASSID,1);
1177 1 : PetscAssertPointer(rg,2);
1178 1 : PetscUseMethod(ds,"DSNEPGetRG_C",(DS,RG*),(ds,rg));
1179 1 : PetscFunctionReturn(PETSC_SUCCESS);
1180 : }
1181 :
1182 19 : static PetscErrorCode DSSetFromOptions_NEP(DS ds,PetscOptionItems *PetscOptionsObject)
1183 : {
1184 19 : PetscInt k;
1185 19 : PetscBool flg;
1186 : #if defined(PETSC_USE_COMPLEX)
1187 : PetscReal r;
1188 : PetscBool flg1;
1189 : DS_NEP *ctx = (DS_NEP*)ds->data;
1190 : #endif
1191 :
1192 19 : PetscFunctionBegin;
1193 19 : PetscOptionsHeadBegin(PetscOptionsObject,"DS NEP Options");
1194 :
1195 19 : PetscCall(PetscOptionsInt("-ds_nep_minimality","Maximum minimality index","DSNEPSetMinimality",4,&k,&flg));
1196 19 : if (flg) PetscCall(DSNEPSetMinimality(ds,k));
1197 :
1198 19 : PetscCall(PetscOptionsInt("-ds_nep_integration_points","Number of integration points","DSNEPSetIntegrationPoints",64,&k,&flg));
1199 19 : if (flg) PetscCall(DSNEPSetIntegrationPoints(ds,k));
1200 :
1201 19 : PetscCall(PetscOptionsInt("-ds_nep_sampling_size","Number of sampling columns","DSNEPSetSamplingSize",0,&k,&flg));
1202 19 : if (flg) PetscCall(DSNEPSetSamplingSize(ds,k));
1203 :
1204 : #if defined(PETSC_USE_COMPLEX)
1205 : r = ctx->rtol;
1206 : PetscCall(PetscOptionsReal("-ds_nep_refine_tol","Refinement tolerance","DSNEPSetRefine",ctx->rtol,&r,&flg1));
1207 : k = ctx->Nit;
1208 : PetscCall(PetscOptionsInt("-ds_nep_refine_its","Number of iterative refinement iterations","DSNEPSetRefine",ctx->Nit,&k,&flg));
1209 : if (flg1||flg) PetscCall(DSNEPSetRefine(ds,r,k));
1210 :
1211 : if (ds->method==1) {
1212 : if (!ctx->rg) PetscCall(DSNEPGetRG(ds,&ctx->rg));
1213 : PetscCall(RGSetFromOptions(ctx->rg));
1214 : }
1215 : #endif
1216 :
1217 19 : PetscOptionsHeadEnd();
1218 19 : PetscFunctionReturn(PETSC_SUCCESS);
1219 : }
1220 :
1221 20 : static PetscErrorCode DSDestroy_NEP(DS ds)
1222 : {
1223 20 : DS_NEP *ctx = (DS_NEP*)ds->data;
1224 20 : PetscInt i;
1225 :
1226 20 : PetscFunctionBegin;
1227 80 : for (i=0;i<ctx->nf;i++) PetscCall(FNDestroy(&ctx->f[i]));
1228 20 : PetscCall(RGDestroy(&ctx->rg));
1229 20 : PetscCall(PetscLayoutDestroy(&ctx->map));
1230 20 : PetscCall(PetscFree(ds->data));
1231 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetFN_C",NULL));
1232 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetFN_C",NULL));
1233 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetNumFN_C",NULL));
1234 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetMinimality_C",NULL));
1235 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetMinimality_C",NULL));
1236 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetRefine_C",NULL));
1237 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetRefine_C",NULL));
1238 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetIntegrationPoints_C",NULL));
1239 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetIntegrationPoints_C",NULL));
1240 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetSamplingSize_C",NULL));
1241 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetSamplingSize_C",NULL));
1242 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetRG_C",NULL));
1243 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetRG_C",NULL));
1244 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetComputeMatrixFunction_C",NULL));
1245 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetComputeMatrixFunction_C",NULL));
1246 20 : PetscFunctionReturn(PETSC_SUCCESS);
1247 : }
1248 :
1249 4388 : static PetscErrorCode DSMatGetSize_NEP(DS ds,DSMatType t,PetscInt *rows,PetscInt *cols)
1250 : {
1251 4388 : DS_NEP *ctx = (DS_NEP*)ds->data;
1252 :
1253 4388 : PetscFunctionBegin;
1254 4388 : *rows = ds->n;
1255 4388 : if (t==DS_MAT_Q || t==DS_MAT_Z || t==DS_MAT_U || t==DS_MAT_V) *rows *= ctx->max_mid;
1256 4388 : *cols = ds->n;
1257 4388 : if (t==DS_MAT_Q || t==DS_MAT_Z || t==DS_MAT_U || t==DS_MAT_V || t==DS_MAT_X || t==DS_MAT_Y) *cols *= ctx->max_mid;
1258 4388 : PetscFunctionReturn(PETSC_SUCCESS);
1259 : }
1260 :
1261 : /*MC
1262 : DSNEP - Dense Nonlinear Eigenvalue Problem.
1263 :
1264 : Level: beginner
1265 :
1266 : Notes:
1267 : The problem is expressed as T(lambda)*x = 0, where T(lambda) is a
1268 : parameter-dependent matrix written as T(lambda) = sum_i E_i*f_i(lambda).
1269 : The eigenvalues lambda are the arguments returned by DSSolve()..
1270 :
1271 : The coefficient matrices E_i are the extra matrices of the DS, and
1272 : the scalar functions f_i are passed via DSNEPSetFN(). Optionally, a
1273 : callback function to fill the E_i matrices can be set with
1274 : DSNEPSetComputeMatrixFunction().
1275 :
1276 : Used DS matrices:
1277 : + DS_MAT_Ex - coefficient matrices of the split form of T(lambda)
1278 : . DS_MAT_A - (workspace) T(lambda) evaluated at a given lambda (SLP only)
1279 : . DS_MAT_B - (workspace) T'(lambda) evaluated at a given lambda (SLP only)
1280 : . DS_MAT_Q - (workspace) left Hankel matrix (contour only)
1281 : . DS_MAT_Z - (workspace) right Hankel matrix (contour only)
1282 : . DS_MAT_U - (workspace) left singular vectors (contour only)
1283 : . DS_MAT_V - (workspace) right singular vectors (contour only)
1284 : - DS_MAT_W - (workspace) auxiliary matrix of size nxn
1285 :
1286 : Implemented methods:
1287 : + 0 - Successive Linear Problems (SLP), computes just one eigenpair
1288 : - 1 - Contour integral, computes all eigenvalues inside a region
1289 :
1290 : .seealso: DSCreate(), DSSetType(), DSType, DSNEPSetFN(), DSNEPSetComputeMatrixFunction()
1291 : M*/
1292 20 : SLEPC_EXTERN PetscErrorCode DSCreate_NEP(DS ds)
1293 : {
1294 20 : DS_NEP *ctx;
1295 :
1296 20 : PetscFunctionBegin;
1297 20 : PetscCall(PetscNew(&ctx));
1298 20 : ds->data = (void*)ctx;
1299 20 : ctx->max_mid = 4;
1300 20 : ctx->nnod = 64;
1301 20 : ctx->Nit = 3;
1302 20 : ctx->rtol = PETSC_MACHINE_EPSILON/PetscSqrtReal(PETSC_SQRT_MACHINE_EPSILON);
1303 :
1304 20 : ds->ops->allocate = DSAllocate_NEP;
1305 20 : ds->ops->setfromoptions = DSSetFromOptions_NEP;
1306 20 : ds->ops->view = DSView_NEP;
1307 20 : ds->ops->vectors = DSVectors_NEP;
1308 20 : ds->ops->solve[0] = DSSolve_NEP_SLP;
1309 : #if defined(PETSC_USE_COMPLEX)
1310 : ds->ops->solve[1] = DSSolve_NEP_Contour;
1311 : #endif
1312 20 : ds->ops->sort = DSSort_NEP;
1313 : #if !defined(PETSC_HAVE_MPIUNI)
1314 20 : ds->ops->synchronize = DSSynchronize_NEP;
1315 : #endif
1316 20 : ds->ops->destroy = DSDestroy_NEP;
1317 20 : ds->ops->matgetsize = DSMatGetSize_NEP;
1318 :
1319 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetFN_C",DSNEPSetFN_NEP));
1320 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetFN_C",DSNEPGetFN_NEP));
1321 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetNumFN_C",DSNEPGetNumFN_NEP));
1322 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetMinimality_C",DSNEPGetMinimality_NEP));
1323 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetMinimality_C",DSNEPSetMinimality_NEP));
1324 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetRefine_C",DSNEPGetRefine_NEP));
1325 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetRefine_C",DSNEPSetRefine_NEP));
1326 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetIntegrationPoints_C",DSNEPGetIntegrationPoints_NEP));
1327 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetIntegrationPoints_C",DSNEPSetIntegrationPoints_NEP));
1328 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetSamplingSize_C",DSNEPGetSamplingSize_NEP));
1329 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetSamplingSize_C",DSNEPSetSamplingSize_NEP));
1330 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetRG_C",DSNEPSetRG_NEP));
1331 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetRG_C",DSNEPGetRG_NEP));
1332 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPSetComputeMatrixFunction_C",DSNEPSetComputeMatrixFunction_NEP));
1333 20 : PetscCall(PetscObjectComposeFunction((PetscObject)ds,"DSNEPGetComputeMatrixFunction_C",DSNEPGetComputeMatrixFunction_NEP));
1334 20 : PetscFunctionReturn(PETSC_SUCCESS);
1335 : }
|