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