Actual source code: neprefine.c
slepc-3.17.1 2022-04-11
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, 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: */
10: /*
11: Newton refinement for NEP, simple version
12: */
14: #include <slepc/private/nepimpl.h>
15: #include <slepcblaslapack.h>
17: #define NREF_MAXIT 10
19: typedef struct {
20: VecScatter *scatter_id,nst;
21: Mat *A;
22: Vec nv,vg,v,w;
23: FN *fn;
24: } NEPSimpNRefctx;
26: typedef struct {
27: Mat M1;
28: Vec M2,M3;
29: PetscScalar M4,m3;
30: } NEP_REFINE_MATSHELL;
32: static PetscErrorCode MatMult_FS(Mat M ,Vec x,Vec y)
33: {
34: NEP_REFINE_MATSHELL *ctx;
35: PetscScalar t;
37: MatShellGetContext(M,&ctx);
38: VecDot(x,ctx->M3,&t);
39: t *= ctx->m3/ctx->M4;
40: MatMult(ctx->M1,x,y);
41: VecAXPY(y,-t,ctx->M2);
42: PetscFunctionReturn(0);
43: }
45: static PetscErrorCode NEPSimpleNRefSetUp(NEP nep,NEPSimpNRefctx **ctx_)
46: {
47: PetscInt i,si,j,n0,m0,nloc,*idx1,*idx2,ne;
48: IS is1,is2;
49: NEPSimpNRefctx *ctx;
50: Vec v;
51: PetscMPIInt rank,size;
52: MPI_Comm child;
54: PetscCalloc1(1,ctx_);
55: ctx = *ctx_;
56: if (nep->npart==1) {
57: ctx->A = nep->A;
58: ctx->fn = nep->f;
59: nep->refinesubc = NULL;
60: ctx->scatter_id = NULL;
61: } else {
62: PetscSubcommGetChild(nep->refinesubc,&child);
63: PetscMalloc2(nep->nt,&ctx->A,nep->npart,&ctx->scatter_id);
65: /* Duplicate matrices */
66: for (i=0;i<nep->nt;i++) {
67: MatCreateRedundantMatrix(nep->A[i],0,child,MAT_INITIAL_MATRIX,&ctx->A[i]);
68: PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->A[i]);
69: }
70: MatCreateVecs(ctx->A[0],&ctx->v,NULL);
71: PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->v);
73: /* Duplicate FNs */
74: PetscMalloc1(nep->nt,&ctx->fn);
75: for (i=0;i<nep->nt;i++) FNDuplicate(nep->f[i],child,&ctx->fn[i]);
77: /* Create scatters for sending vectors to each subcommucator */
78: BVGetColumn(nep->V,0,&v);
79: VecGetOwnershipRange(v,&n0,&m0);
80: BVRestoreColumn(nep->V,0,&v);
81: VecGetLocalSize(ctx->v,&nloc);
82: PetscMalloc2(m0-n0,&idx1,m0-n0,&idx2);
83: VecCreateMPI(PetscObjectComm((PetscObject)nep),nloc,PETSC_DECIDE,&ctx->vg);
84: for (si=0;si<nep->npart;si++) {
85: j = 0;
86: for (i=n0;i<m0;i++) {
87: idx1[j] = i;
88: idx2[j++] = i+nep->n*si;
89: }
90: ISCreateGeneral(PetscObjectComm((PetscObject)nep),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
91: ISCreateGeneral(PetscObjectComm((PetscObject)nep),(m0-n0),idx2,PETSC_COPY_VALUES,&is2);
92: BVGetColumn(nep->V,0,&v);
93: VecScatterCreate(v,is1,ctx->vg,is2,&ctx->scatter_id[si]);
94: BVRestoreColumn(nep->V,0,&v);
95: ISDestroy(&is1);
96: ISDestroy(&is2);
97: }
98: PetscFree2(idx1,idx2);
99: }
100: if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
101: MPI_Comm_rank(PetscObjectComm((PetscObject)ctx->A[0]),&rank);
102: MPI_Comm_size(PetscObjectComm((PetscObject)ctx->A[0]),&size);
103: if (size>1) {
104: if (nep->npart==1) BVGetColumn(nep->V,0,&v);
105: else v = ctx->v;
106: VecGetOwnershipRange(v,&n0,&m0);
107: ne = (rank == size-1)?nep->n:0;
108: VecCreateMPI(PetscObjectComm((PetscObject)ctx->A[0]),ne,PETSC_DECIDE,&ctx->nv);
109: PetscMalloc1(m0-n0,&idx1);
110: for (i=n0;i<m0;i++) {
111: idx1[i-n0] = i;
112: }
113: ISCreateGeneral(PetscObjectComm((PetscObject)ctx->A[0]),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
114: VecScatterCreate(v,is1,ctx->nv,is1,&ctx->nst);
115: if (nep->npart==1) BVRestoreColumn(nep->V,0,&v);
116: PetscFree(idx1);
117: ISDestroy(&is1);
118: }
119: } PetscFunctionReturn(0);
120: }
122: /*
123: Gather Eigenpair idx from subcommunicator with color sc
124: */
125: static PetscErrorCode NEPSimpleNRefGatherEigenpair(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx,PetscInt *fail)
126: {
127: PetscMPIInt nproc,p;
128: MPI_Comm comm=((PetscObject)nep)->comm;
129: Vec v;
130: PetscScalar *array;
132: MPI_Comm_size(comm,&nproc);
133: p = (nproc/nep->npart)*(sc+1)+PetscMin(sc+1,nproc%nep->npart)-1;
134: if (nep->npart>1) {
135: /* Communicate convergence successful */
136: MPI_Bcast(fail,1,MPIU_INT,p,comm);
137: if (!(*fail)) {
138: /* Process 0 of subcommunicator sc broadcasts the eigenvalue */
139: MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm);
140: /* Gather nep->V[idx] from the subcommuniator sc */
141: BVGetColumn(nep->V,idx,&v);
142: if (nep->refinesubc->color==sc) {
143: VecGetArray(ctx->v,&array);
144: VecPlaceArray(ctx->vg,array);
145: }
146: VecScatterBegin(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
147: VecScatterEnd(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
148: if (nep->refinesubc->color==sc) {
149: VecResetArray(ctx->vg);
150: VecRestoreArray(ctx->v,&array);
151: }
152: BVRestoreColumn(nep->V,idx,&v);
153: }
154: } else {
155: if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT && !(*fail)) MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm);
156: }
157: PetscFunctionReturn(0);
158: }
160: static PetscErrorCode NEPSimpleNRefScatterEigenvector(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx)
161: {
162: Vec v;
163: PetscScalar *array;
165: if (nep->npart>1) {
166: BVGetColumn(nep->V,idx,&v);
167: if (nep->refinesubc->color==sc) {
168: VecGetArray(ctx->v,&array);
169: VecPlaceArray(ctx->vg,array);
170: }
171: VecScatterBegin(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
172: VecScatterEnd(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
173: if (nep->refinesubc->color==sc) {
174: VecResetArray(ctx->vg);
175: VecRestoreArray(ctx->v,&array);
176: }
177: BVRestoreColumn(nep->V,idx,&v);
178: }
179: PetscFunctionReturn(0);
180: }
182: static PetscErrorCode NEPSimpleNRefSetUpSystem(NEP nep,NEPSimpNRefctx *ctx,Mat *A,PetscInt idx,Mat *Mt,Mat *T,Mat *P,PetscBool ini,Vec t,Vec v)
183: {
184: PetscErrorCode ierr;
185: PetscInt i,st,ml,m0,n0,m1,mg;
186: PetscInt *dnz,*onz,ncols,*cols2=NULL,*nnz,nt=nep->nt;
187: PetscScalar zero=0.0,*coeffs,*coeffs2;
188: PetscMPIInt rank,size;
189: MPI_Comm comm;
190: const PetscInt *cols;
191: const PetscScalar *vals,*array;
192: NEP_REFINE_MATSHELL *fctx;
193: Vec w=ctx->w;
194: Mat M;
196: PetscMalloc2(nt,&coeffs,nt,&coeffs2);
197: switch (nep->scheme) {
198: case NEP_REFINE_SCHEME_SCHUR:
199: if (ini) {
200: PetscCalloc1(1,&fctx);
201: MatGetSize(A[0],&m0,&n0);
202: MatCreateShell(PetscObjectComm((PetscObject)A[0]),PETSC_DECIDE,PETSC_DECIDE,m0,n0,fctx,T);
203: MatShellSetOperation(*T,MATOP_MULT,(void(*)(void))MatMult_FS);
204: } else MatShellGetContext(*T,&fctx);
205: M=fctx->M1;
206: break;
207: case NEP_REFINE_SCHEME_MBE:
208: M=*T;
209: break;
210: case NEP_REFINE_SCHEME_EXPLICIT:
211: M=*Mt;
212: break;
213: }
214: if (ini) MatDuplicate(A[0],MAT_COPY_VALUES,&M);
215: else MatCopy(A[0],M,DIFFERENT_NONZERO_PATTERN);
216: for (i=0;i<nt;i++) FNEvaluateFunction(ctx->fn[i],nep->eigr[idx],coeffs+i);
217: if (coeffs[0]!=1.0) MatScale(M,coeffs[0]);
218: for (i=1;i<nt;i++) MatAXPY(M,coeffs[i],A[i],(ini)?nep->mstr:SUBSET_NONZERO_PATTERN);
219: for (i=0;i<nt;i++) FNEvaluateDerivative(ctx->fn[i],nep->eigr[idx],coeffs2+i);
220: st = 0;
221: for (i=0;i<nt && PetscAbsScalar(coeffs2[i])==0.0;i++) st++;
222: MatMult(A[st],v,w);
223: if (coeffs2[st]!=1.0) VecScale(w,coeffs2[st]);
224: for (i=st+1;i<nt;i++) {
225: MatMult(A[i],v,t);
226: VecAXPY(w,coeffs2[i],t);
227: }
229: switch (nep->scheme) {
230: case NEP_REFINE_SCHEME_EXPLICIT:
231: comm = PetscObjectComm((PetscObject)A[0]);
232: MPI_Comm_rank(comm,&rank);
233: MPI_Comm_size(comm,&size);
234: MatGetSize(M,&mg,NULL);
235: MatGetOwnershipRange(M,&m0,&m1);
236: if (ini) {
237: MatCreate(comm,T);
238: MatGetLocalSize(M,&ml,NULL);
239: if (rank==size-1) ml++;
240: MatSetSizes(*T,ml,ml,mg+1,mg+1);
241: MatSetFromOptions(*T);
242: MatSetUp(*T);
243: /* Preallocate M */
244: if (size>1) {
245: ierr = MatPreallocateInitialize(comm,ml,ml,dnz,onz);
246: for (i=m0;i<m1;i++) {
247: MatGetRow(M,i,&ncols,&cols,NULL);
248: MatPreallocateSet(i,ncols,cols,dnz,onz);
249: MatPreallocateSet(i,1,&mg,dnz,onz);
250: MatRestoreRow(M,i,&ncols,&cols,NULL);
251: }
252: if (rank==size-1) {
253: PetscCalloc1(mg+1,&cols2);
254: for (i=0;i<mg+1;i++) cols2[i]=i;
255: MatPreallocateSet(m1,mg+1,cols2,dnz,onz);
256: PetscFree(cols2);
257: }
258: MatMPIAIJSetPreallocation(*T,0,dnz,0,onz);
259: ierr = MatPreallocateFinalize(dnz,onz);
260: } else {
261: PetscCalloc1(mg+1,&nnz);
262: for (i=0;i<mg;i++) {
263: MatGetRow(M,i,&ncols,NULL,NULL);
264: nnz[i] = ncols+1;
265: MatRestoreRow(M,i,&ncols,NULL,NULL);
266: }
267: nnz[mg] = mg+1;
268: MatSeqAIJSetPreallocation(*T,0,nnz);
269: PetscFree(nnz);
270: }
271: *Mt = M;
272: *P = *T;
273: }
275: /* Set values */
276: VecGetArrayRead(w,&array);
277: for (i=m0;i<m1;i++) {
278: MatGetRow(M,i,&ncols,&cols,&vals);
279: MatSetValues(*T,1,&i,ncols,cols,vals,INSERT_VALUES);
280: MatRestoreRow(M,i,&ncols,&cols,&vals);
281: MatSetValues(*T,1,&i,1,&mg,array+i-m0,INSERT_VALUES);
282: }
283: VecRestoreArrayRead(w,&array);
284: VecConjugate(v);
285: MPI_Comm_size(PetscObjectComm((PetscObject)A[0]),&size);
286: MPI_Comm_rank(PetscObjectComm((PetscObject)A[0]),&rank);
287: if (size>1) {
288: if (rank==size-1) {
289: PetscMalloc1(nep->n,&cols2);
290: for (i=0;i<nep->n;i++) cols2[i]=i;
291: }
292: VecScatterBegin(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
293: VecScatterEnd(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
294: VecGetArrayRead(ctx->nv,&array);
295: if (rank==size-1) {
296: MatSetValues(*T,1,&mg,nep->n,cols2,array,INSERT_VALUES);
297: MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
298: }
299: VecRestoreArrayRead(ctx->nv,&array);
300: } else {
301: PetscMalloc1(m1-m0,&cols2);
302: for (i=0;i<m1-m0;i++) cols2[i]=m0+i;
303: VecGetArrayRead(v,&array);
304: MatSetValues(*T,1,&mg,m1-m0,cols2,array,INSERT_VALUES);
305: MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
306: VecRestoreArrayRead(v,&array);
307: }
308: VecConjugate(v);
309: MatAssemblyBegin(*T,MAT_FINAL_ASSEMBLY);
310: MatAssemblyEnd(*T,MAT_FINAL_ASSEMBLY);
311: PetscFree(cols2);
312: break;
313: case NEP_REFINE_SCHEME_SCHUR:
314: fctx->M2 = ctx->w;
315: fctx->M3 = v;
316: fctx->m3 = 1.0+PetscConj(nep->eigr[idx])*nep->eigr[idx];
317: fctx->M4 = PetscConj(nep->eigr[idx]);
318: fctx->M1 = M;
319: if (ini) MatDuplicate(M,MAT_COPY_VALUES,P);
320: else MatCopy(M,*P,SAME_NONZERO_PATTERN);
321: if (fctx->M4!=0.0) {
322: VecConjugate(v);
323: VecPointwiseMult(t,v,w);
324: VecConjugate(v);
325: VecScale(t,-fctx->m3/fctx->M4);
326: MatDiagonalSet(*P,t,ADD_VALUES);
327: }
328: break;
329: case NEP_REFINE_SCHEME_MBE:
330: *T = M;
331: *P = M;
332: break;
333: }
334: PetscFree2(coeffs,coeffs2);
335: PetscFunctionReturn(0);
336: }
338: PetscErrorCode NEPNewtonRefinementSimple(NEP nep,PetscInt *maxits,PetscReal tol,PetscInt k)
339: {
340: PetscInt i,n,its,idx=0,*idx_sc,*its_sc,color,*fail_sc;
341: PetscMPIInt rank,size;
342: Mat Mt=NULL,T=NULL,P=NULL;
343: MPI_Comm comm;
344: Vec r,v,dv,rr=NULL,dvv=NULL,t[2];
345: const PetscScalar *array;
346: PetscScalar *array2,deig=0.0,tt[2],ttt;
347: PetscReal norm,error;
348: PetscBool ini=PETSC_TRUE,sc_pend,solved=PETSC_FALSE;
349: NEPSimpNRefctx *ctx;
350: NEP_REFINE_MATSHELL *fctx=NULL;
351: KSPConvergedReason reason;
353: PetscLogEventBegin(NEP_Refine,nep,0,0,0);
354: NEPSimpleNRefSetUp(nep,&ctx);
355: its = (maxits)?*maxits:NREF_MAXIT;
356: if (!nep->refineksp) NEPRefineGetKSP(nep,&nep->refineksp);
357: if (nep->npart==1) BVGetColumn(nep->V,0,&v);
358: else v = ctx->v;
359: VecDuplicate(v,&ctx->w);
360: VecDuplicate(v,&r);
361: VecDuplicate(v,&dv);
362: VecDuplicate(v,&t[0]);
363: VecDuplicate(v,&t[1]);
364: if (nep->npart==1) {
365: BVRestoreColumn(nep->V,0,&v);
366: PetscObjectGetComm((PetscObject)nep,&comm);
367: } else PetscSubcommGetChild(nep->refinesubc,&comm);
368: MPI_Comm_size(comm,&size);
369: MPI_Comm_rank(comm,&rank);
370: VecGetLocalSize(r,&n);
371: PetscMalloc3(nep->npart,&idx_sc,nep->npart,&its_sc,nep->npart,&fail_sc);
372: for (i=0;i<nep->npart;i++) fail_sc[i] = 0;
373: for (i=0;i<nep->npart;i++) its_sc[i] = 0;
374: color = (nep->npart==1)?0:nep->refinesubc->color;
376: /* Loop performing iterative refinements */
377: while (!solved) {
378: for (i=0;i<nep->npart;i++) {
379: sc_pend = PETSC_TRUE;
380: if (its_sc[i]==0) {
381: idx_sc[i] = idx++;
382: if (idx_sc[i]>=k) {
383: sc_pend = PETSC_FALSE;
384: } else NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]);
385: } else { /* Gather Eigenpair from subcommunicator i */
386: NEPSimpleNRefGatherEigenpair(nep,ctx,i,idx_sc[i],&fail_sc[i]);
387: }
388: while (sc_pend) {
389: if (!fail_sc[i]) NEPComputeError(nep,idx_sc[i],NEP_ERROR_RELATIVE,&error);
390: if (error<=tol || its_sc[i]>=its || fail_sc[i]) {
391: idx_sc[i] = idx++;
392: its_sc[i] = 0;
393: fail_sc[i] = 0;
394: if (idx_sc[i]<k) NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]);
395: } else {
396: sc_pend = PETSC_FALSE;
397: its_sc[i]++;
398: }
399: if (idx_sc[i]>=k) sc_pend = PETSC_FALSE;
400: }
401: }
402: solved = PETSC_TRUE;
403: for (i=0;i<nep->npart&&solved;i++) solved = PetscNot(idx_sc[i]<k);
404: if (idx_sc[color]<k) {
405: #if !defined(PETSC_USE_COMPLEX)
407: #endif
408: if (nep->npart==1) BVGetColumn(nep->V,idx_sc[color],&v);
409: else v = ctx->v;
410: NEPSimpleNRefSetUpSystem(nep,ctx,ctx->A,idx_sc[color],&Mt,&T,&P,ini,t[0],v);
411: NEP_KSPSetOperators(nep->refineksp,T,P);
412: if (ini) {
413: KSPSetFromOptions(nep->refineksp);
414: if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
415: MatCreateVecs(T,&dvv,NULL);
416: VecDuplicate(dvv,&rr);
417: }
418: ini = PETSC_FALSE;
419: }
420: switch (nep->scheme) {
421: case NEP_REFINE_SCHEME_EXPLICIT:
422: MatMult(Mt,v,r);
423: VecGetArrayRead(r,&array);
424: if (rank==size-1) {
425: VecGetArray(rr,&array2);
426: PetscArraycpy(array2,array,n);
427: array2[n] = 0.0;
428: VecRestoreArray(rr,&array2);
429: } else VecPlaceArray(rr,array);
430: KSPSolve(nep->refineksp,rr,dvv);
431: KSPGetConvergedReason(nep->refineksp,&reason);
432: if (reason>0) {
433: if (rank != size-1) VecResetArray(rr);
434: VecRestoreArrayRead(r,&array);
435: VecGetArrayRead(dvv,&array);
436: VecPlaceArray(dv,array);
437: VecAXPY(v,-1.0,dv);
438: VecNorm(v,NORM_2,&norm);
439: VecScale(v,1.0/norm);
440: VecResetArray(dv);
441: if (rank==size-1) nep->eigr[idx_sc[color]] -= array[n];
442: VecRestoreArrayRead(dvv,&array);
443: } else fail_sc[color] = 1;
444: break;
445: case NEP_REFINE_SCHEME_MBE:
446: MatMult(T,v,r);
447: /* Mixed block elimination */
448: VecConjugate(v);
449: KSPSolveTranspose(nep->refineksp,v,t[0]);
450: KSPGetConvergedReason(nep->refineksp,&reason);
451: if (reason>0) {
452: VecConjugate(t[0]);
453: VecDot(ctx->w,t[0],&tt[0]);
454: KSPSolve(nep->refineksp,ctx->w,t[1]);
455: KSPGetConvergedReason(nep->refineksp,&reason);
456: if (reason>0) {
457: VecDot(t[1],v,&tt[1]);
458: VecDot(r,t[0],&ttt);
459: tt[0] = ttt/tt[0];
460: VecAXPY(r,-tt[0],ctx->w);
461: KSPSolve(nep->refineksp,r,dv);
462: KSPGetConvergedReason(nep->refineksp,&reason);
463: if (reason>0) {
464: VecDot(dv,v,&ttt);
465: tt[1] = ttt/tt[1];
466: VecAXPY(dv,-tt[1],t[1]);
467: deig = tt[0]+tt[1];
468: }
469: }
470: VecConjugate(v);
471: VecAXPY(v,-1.0,dv);
472: VecNorm(v,NORM_2,&norm);
473: VecScale(v,1.0/norm);
474: nep->eigr[idx_sc[color]] -= deig;
475: fail_sc[color] = 0;
476: } else {
477: VecConjugate(v);
478: fail_sc[color] = 1;
479: }
480: break;
481: case NEP_REFINE_SCHEME_SCHUR:
482: fail_sc[color] = 1;
483: MatShellGetContext(T,&fctx);
484: if (fctx->M4!=0.0) {
485: MatMult(fctx->M1,v,r);
486: KSPSolve(nep->refineksp,r,dv);
487: KSPGetConvergedReason(nep->refineksp,&reason);
488: if (reason>0) {
489: VecDot(dv,v,&deig);
490: deig *= -fctx->m3/fctx->M4;
491: VecAXPY(v,-1.0,dv);
492: VecNorm(v,NORM_2,&norm);
493: VecScale(v,1.0/norm);
494: nep->eigr[idx_sc[color]] -= deig;
495: fail_sc[color] = 0;
496: }
497: }
498: break;
499: }
500: if (nep->npart==1) BVRestoreColumn(nep->V,idx_sc[color],&v);
501: }
502: }
503: VecDestroy(&t[0]);
504: VecDestroy(&t[1]);
505: VecDestroy(&dv);
506: VecDestroy(&ctx->w);
507: VecDestroy(&r);
508: PetscFree3(idx_sc,its_sc,fail_sc);
509: VecScatterDestroy(&ctx->nst);
510: if (nep->npart>1) {
511: VecDestroy(&ctx->vg);
512: VecDestroy(&ctx->v);
513: for (i=0;i<nep->nt;i++) MatDestroy(&ctx->A[i]);
514: for (i=0;i<nep->npart;i++) VecScatterDestroy(&ctx->scatter_id[i]);
515: PetscFree2(ctx->A,ctx->scatter_id);
516: }
517: if (fctx && nep->scheme==NEP_REFINE_SCHEME_SCHUR) {
518: MatDestroy(&P);
519: MatDestroy(&fctx->M1);
520: PetscFree(fctx);
521: }
522: if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
523: MatDestroy(&Mt);
524: VecDestroy(&dvv);
525: VecDestroy(&rr);
526: VecDestroy(&ctx->nv);
527: if (nep->npart>1) {
528: for (i=0;i<nep->nt;i++) FNDestroy(&ctx->fn[i]);
529: PetscFree(ctx->fn);
530: }
531: }
532: if (nep->scheme==NEP_REFINE_SCHEME_MBE) {
533: if (nep->npart>1) {
534: for (i=0;i<nep->nt;i++) FNDestroy(&ctx->fn[i]);
535: PetscFree(ctx->fn);
536: }
537: }
538: MatDestroy(&T);
539: PetscFree(ctx);
540: PetscLogEventEnd(NEP_Refine,nep,0,0,0);
541: PetscFunctionReturn(0);
542: }