PetscErrorCode PEPComputeVectors_Schur(PEP pep) { PetscErrorCode ierr; PetscInt n,i; Mat Z; Vec v; #if !defined(PETSC_USE_COMPLEX) Vec v1; PetscScalar tmp; PetscReal norm,normi; #endif PetscFunctionBegin; ierr = DSGetDimensions(pep->ds,&n,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DSVectors(pep->ds,DS_MAT_X,NULL,NULL);CHKERRQ(ierr); ierr = DSGetMat(pep->ds,DS_MAT_X,&Z);CHKERRQ(ierr); ierr = BVSetActiveColumns(pep->V,0,n);CHKERRQ(ierr); ierr = BVMultInPlace(pep->V,Z,0,n);CHKERRQ(ierr); ierr = MatDestroy(&Z);CHKERRQ(ierr); /* Fix eigenvectors if balancing was used */ if ((pep->scale==PEP_SCALE_DIAGONAL || pep->scale==PEP_SCALE_BOTH) && pep->Dr && (pep->refine!=PEP_REFINE_MULTIPLE)) { for (i=0;i<n;i++) { ierr = BVGetColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = VecPointwiseMult(v,v,pep->Dr);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i,&v);CHKERRQ(ierr); } } /* normalization */ for (i=0;i<n;i++) { #if !defined(PETSC_USE_COMPLEX) if (pep->eigi[i] != 0.0) { ierr = BVGetColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = BVGetColumn(pep->V,i+1,&v1);CHKERRQ(ierr); ierr = VecNorm(v,NORM_2,&norm);CHKERRQ(ierr); ierr = VecNorm(v1,NORM_2,&normi);CHKERRQ(ierr); tmp = 1.0 / SlepcAbsEigenvalue(norm,normi); ierr = VecScale(v,tmp);CHKERRQ(ierr); ierr = VecScale(v1,tmp);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i+1,&v1);CHKERRQ(ierr); i++; } else #endif { ierr = BVGetColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = VecNormalize(v,NULL);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i,&v);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/* Custom CGS orthogonalization, preprocess after first orthogonalization */ static PetscErrorCode SVDOrthogonalizeCGS(BV V,PetscInt i,PetscScalar* h,PetscReal a,BVOrthogRefineType refine,PetscReal eta,PetscReal *norm) { PetscErrorCode ierr; PetscReal sum,onorm; PetscScalar dot; PetscInt j; PetscFunctionBegin; switch (refine) { case BV_ORTHOG_REFINE_NEVER: ierr = BVNormColumn(V,i,NORM_2,norm);CHKERRQ(ierr); break; case BV_ORTHOG_REFINE_ALWAYS: ierr = BVSetActiveColumns(V,0,i);CHKERRQ(ierr); ierr = BVDotColumn(V,i,h);CHKERRQ(ierr); ierr = BVMultColumn(V,-1.0,1.0,i,h);CHKERRQ(ierr); ierr = BVNormColumn(V,i,NORM_2,norm);CHKERRQ(ierr); break; case BV_ORTHOG_REFINE_IFNEEDED: dot = h[i]; onorm = PetscSqrtReal(PetscRealPart(dot)) / a; sum = 0.0; for (j=0;j<i;j++) { sum += PetscRealPart(h[j] * PetscConj(h[j])); } *norm = PetscRealPart(dot)/(a*a) - sum; if (*norm>0.0) *norm = PetscSqrtReal(*norm); else { ierr = BVNormColumn(V,i,NORM_2,norm);CHKERRQ(ierr); } if (*norm < eta*onorm) { ierr = BVSetActiveColumns(V,0,i);CHKERRQ(ierr); ierr = BVDotColumn(V,i,h);CHKERRQ(ierr); ierr = BVMultColumn(V,-1.0,1.0,i,h);CHKERRQ(ierr); ierr = BVNormColumn(V,i,NORM_2,norm);CHKERRQ(ierr); } break; } PetscFunctionReturn(0); }
PetscErrorCode PEPComputeVectors_Indefinite(PEP pep) { PetscErrorCode ierr; PetscInt n,i; Mat Z; Vec v; #if !defined(PETSC_USE_COMPLEX) Vec v1; PetscScalar tmp; PetscReal norm,normi; #endif PetscFunctionBegin; ierr = DSGetDimensions(pep->ds,&n,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DSVectors(pep->ds,DS_MAT_X,NULL,NULL);CHKERRQ(ierr); ierr = DSGetMat(pep->ds,DS_MAT_X,&Z);CHKERRQ(ierr); ierr = BVSetActiveColumns(pep->V,0,n);CHKERRQ(ierr); ierr = BVMultInPlace(pep->V,Z,0,n);CHKERRQ(ierr); ierr = MatDestroy(&Z);CHKERRQ(ierr); /* normalization */ for (i=0;i<n;i++) { #if !defined(PETSC_USE_COMPLEX) if (pep->eigi[i] != 0.0) { ierr = BVGetColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = BVGetColumn(pep->V,i+1,&v1);CHKERRQ(ierr); ierr = VecNorm(v,NORM_2,&norm);CHKERRQ(ierr); ierr = VecNorm(v1,NORM_2,&normi);CHKERRQ(ierr); tmp = 1.0 / SlepcAbsEigenvalue(norm,normi); ierr = VecScale(v,tmp);CHKERRQ(ierr); ierr = VecScale(v1,tmp);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i+1,&v1);CHKERRQ(ierr); i++; } else #endif { ierr = BVGetColumn(pep->V,i,&v);CHKERRQ(ierr); ierr = VecNormalize(v,NULL);CHKERRQ(ierr); ierr = BVRestoreColumn(pep->V,i,&v);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/* EPSComputeVectors_XD - Compute eigenvectors from the vectors provided by the eigensolver. This version is intended for solvers that provide Schur vectors from the QZ decomposition. Given the partial Schur decomposition OP*V=V*T, the following steps are performed: 1) compute eigenvectors of (S,T): S*Z=T*Z*D 2) compute eigenvectors of OP: X=V*Z */ PetscErrorCode EPSComputeVectors_XD(EPS eps) { PetscErrorCode ierr; Mat X; PetscBool symm; PetscFunctionBegin; ierr = PetscObjectTypeCompareAny((PetscObject)eps->ds,&symm,DSHEP,"");CHKERRQ(ierr); if (symm) PetscFunctionReturn(0); ierr = DSVectors(eps->ds,DS_MAT_X,NULL,NULL);CHKERRQ(ierr); ierr = DSNormalize(eps->ds,DS_MAT_X,-1);CHKERRQ(ierr); /* V <- V * X */ ierr = DSGetMat(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = BVSetActiveColumns(eps->V,0,eps->nconv);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,X,0,eps->nconv);CHKERRQ(ierr); ierr = DSRestoreMat(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* EPSLocalLanczos - Local reorthogonalization. This is the simplest variant. At each Lanczos step, the corresponding Lanczos vector is orthogonalized with respect to the two previous Lanczos vectors, according to the three term Lanczos recurrence. WARNING: This variant does not track the loss of orthogonality that occurs in finite-precision arithmetic and, therefore, the generated vectors are not guaranteed to be (semi-)orthogonal. */ static PetscErrorCode EPSLocalLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown) { PetscErrorCode ierr; PetscInt i,j,m = *M; Vec vj,vj1; PetscBool *which,lwhich[100]; PetscScalar *hwork,lhwork[100]; PetscFunctionBegin; if (m > 100) { ierr = PetscMalloc2(m,&which,m,&hwork);CHKERRQ(ierr); } else { which = lwhich; hwork = lhwork; } for (i=0;i<k;i++) which[i] = PETSC_TRUE; ierr = BVSetActiveColumns(eps->V,0,m);CHKERRQ(ierr); for (j=k;j<m;j++) { ierr = BVGetColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVGetColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); ierr = STApply(eps->st,vj,vj1);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); which[j] = PETSC_TRUE; if (j-2>=k) which[j-2] = PETSC_FALSE; ierr = BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,beta+j,breakdown);CHKERRQ(ierr); alpha[j] = PetscRealPart(hwork[j]); if (*breakdown) { *M = j+1; break; } else { ierr = BVScaleColumn(eps->V,j+1,1/beta[j]);CHKERRQ(ierr); } } if (m > 100) { ierr = PetscFree2(which,hwork);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode EPSSolve_Lanczos(EPS eps) { EPS_LANCZOS *lanczos = (EPS_LANCZOS*)eps->data; PetscErrorCode ierr; PetscInt nconv,i,j,k,l,x,n,*perm,restart,ncv=eps->ncv,r,ld; Vec vi,vj,w; Mat U; PetscScalar *Y,*ritz,stmp; PetscReal *d,*e,*bnd,anorm,beta,norm,rtmp,resnorm; PetscBool breakdown; char *conv,ctmp; PetscFunctionBegin; ierr = DSGetLeadingDimension(eps->ds,&ld);CHKERRQ(ierr); ierr = PetscMalloc4(ncv,&ritz,ncv,&bnd,ncv,&perm,ncv,&conv);CHKERRQ(ierr); /* The first Lanczos vector is the normalized initial vector */ ierr = EPSGetStartVector(eps,0,NULL);CHKERRQ(ierr); anorm = -1.0; nconv = 0; /* Restart loop */ while (eps->reason == EPS_CONVERGED_ITERATING) { eps->its++; /* Compute an ncv-step Lanczos factorization */ n = PetscMin(nconv+eps->mpd,ncv); ierr = DSGetArrayReal(eps->ds,DS_MAT_T,&d);CHKERRQ(ierr); e = d + ld; ierr = EPSBasicLanczos(eps,d,e,nconv,&n,&breakdown,anorm);CHKERRQ(ierr); beta = e[n-1]; ierr = DSRestoreArrayReal(eps->ds,DS_MAT_T,&d);CHKERRQ(ierr); ierr = DSSetDimensions(eps->ds,n,0,nconv,0);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); ierr = BVSetActiveColumns(eps->V,nconv,n);CHKERRQ(ierr); /* Solve projected problem */ ierr = DSSolve(eps->ds,ritz,NULL);CHKERRQ(ierr); ierr = DSSort(eps->ds,ritz,NULL,NULL,NULL,NULL);CHKERRQ(ierr); /* Estimate ||A|| */ for (i=nconv;i<n;i++) anorm = PetscMax(anorm,PetscAbsReal(PetscRealPart(ritz[i]))); /* Compute residual norm estimates as beta*abs(Y(m,:)) + eps*||A|| */ ierr = DSGetArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); for (i=nconv;i<n;i++) { resnorm = beta*PetscAbsScalar(Y[n-1+i*ld]) + PETSC_MACHINE_EPSILON*anorm; ierr = (*eps->converged)(eps,ritz[i],eps->eigi[i],resnorm,&bnd[i],eps->convergedctx);CHKERRQ(ierr); if (bnd[i]<eps->tol) conv[i] = 'C'; else conv[i] = 'N'; } ierr = DSRestoreArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); /* purge repeated ritz values */ if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL) { for (i=nconv+1;i<n;i++) { if (conv[i] == 'C' && PetscAbsScalar((ritz[i]-ritz[i-1])/ritz[i]) < eps->tol) conv[i] = 'R'; } } /* Compute restart vector */ if (breakdown) { ierr = PetscInfo2(eps,"Breakdown in Lanczos method (it=%D norm=%g)\n",eps->its,(double)beta);CHKERRQ(ierr); } else { restart = nconv; while (restart<n && conv[restart] != 'N') restart++; if (restart >= n) { breakdown = PETSC_TRUE; } else { for (i=restart+1;i<n;i++) { if (conv[i] == 'N') { ierr = SlepcSCCompare(eps->sc,ritz[restart],0.0,ritz[i],0.0,&r);CHKERRQ(ierr); if (r>0) restart = i; } } ierr = DSGetArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); ierr = BVMultColumn(eps->V,1.0,0.0,n,Y+restart*ld+nconv);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); } } /* Count and put converged eigenvalues first */ for (i=nconv;i<n;i++) perm[i] = i; for (k=nconv;k<n;k++) { if (conv[perm[k]] != 'C') { j = k + 1; while (j<n && conv[perm[j]] != 'C') j++; if (j>=n) break; l = perm[k]; perm[k] = perm[j]; perm[j] = l; } } /* Sort eigenvectors according to permutation */ ierr = DSGetArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); for (i=nconv;i<k;i++) { x = perm[i]; if (x != i) { j = i + 1; while (perm[j] != i) j++; /* swap eigenvalues i and j */ stmp = ritz[x]; ritz[x] = ritz[i]; ritz[i] = stmp; rtmp = bnd[x]; bnd[x] = bnd[i]; bnd[i] = rtmp; ctmp = conv[x]; conv[x] = conv[i]; conv[i] = ctmp; perm[j] = x; perm[i] = i; /* swap eigenvectors i and j */ for (l=0;l<n;l++) { stmp = Y[l+x*ld]; Y[l+x*ld] = Y[l+i*ld]; Y[l+i*ld] = stmp; } } } ierr = DSRestoreArray(eps->ds,DS_MAT_Q,&Y);CHKERRQ(ierr); /* compute converged eigenvectors */ ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,nconv,k);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); /* purge spurious ritz values */ if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL) { for (i=nconv;i<k;i++) { ierr = BVGetColumn(eps->V,i,&vi);CHKERRQ(ierr); ierr = VecNorm(vi,NORM_2,&norm);CHKERRQ(ierr); ierr = VecScale(vi,1.0/norm);CHKERRQ(ierr); w = eps->work[0]; ierr = STApply(eps->st,vi,w);CHKERRQ(ierr); ierr = VecAXPY(w,-ritz[i],vi);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,i,&vi);CHKERRQ(ierr); ierr = VecNorm(w,NORM_2,&norm);CHKERRQ(ierr); ierr = (*eps->converged)(eps,ritz[i],eps->eigi[i],norm,&bnd[i],eps->convergedctx);CHKERRQ(ierr); if (bnd[i]>=eps->tol) conv[i] = 'S'; } for (i=nconv;i<k;i++) { if (conv[i] != 'C') { j = i + 1; while (j<k && conv[j] != 'C') j++; if (j>=k) break; /* swap eigenvalues i and j */ stmp = ritz[j]; ritz[j] = ritz[i]; ritz[i] = stmp; rtmp = bnd[j]; bnd[j] = bnd[i]; bnd[i] = rtmp; ctmp = conv[j]; conv[j] = conv[i]; conv[i] = ctmp; /* swap eigenvectors i and j */ ierr = BVGetColumn(eps->V,i,&vi);CHKERRQ(ierr); ierr = BVGetColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = VecSwap(vi,vj);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,i,&vi);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j,&vj);CHKERRQ(ierr); } } k = i; } /* store ritz values and estimated errors */ for (i=nconv;i<n;i++) { eps->eigr[i] = ritz[i]; eps->errest[i] = bnd[i]; } ierr = EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,n);CHKERRQ(ierr); nconv = k; if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS; if (nconv >= eps->nev) eps->reason = EPS_CONVERGED_TOL; if (eps->reason == EPS_CONVERGED_ITERATING) { /* copy restart vector */ ierr = BVCopyColumn(eps->V,n,nconv);CHKERRQ(ierr); if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL && !breakdown) { /* Reorthonormalize restart vector */ ierr = BVOrthogonalizeColumn(eps->V,nconv,NULL,&norm,&breakdown);CHKERRQ(ierr); ierr = BVScaleColumn(eps->V,nconv,1.0/norm);CHKERRQ(ierr); } if (breakdown) { /* Use random vector for restarting */ ierr = PetscInfo(eps,"Using random vector for restart\n");CHKERRQ(ierr); ierr = EPSGetStartVector(eps,nconv,&breakdown);CHKERRQ(ierr); } if (breakdown) { /* give up */ eps->reason = EPS_DIVERGED_BREAKDOWN; ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr); } } } eps->nconv = nconv; ierr = PetscFree4(ritz,bnd,perm,conv);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* EPSPartialLanczos - Partial reorthogonalization. */ static PetscErrorCode EPSPartialLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscReal anorm) { PetscErrorCode ierr; EPS_LANCZOS *lanczos = (EPS_LANCZOS*)eps->data; PetscInt i,j,m = *M; Vec vj,vj1; PetscReal norm,*omega,lomega[100],*omega_old,lomega_old[100],eps1,delta,eta; PetscBool *which,lwhich[100],*which2,lwhich2[100]; PetscBool reorth = PETSC_FALSE,force_reorth = PETSC_FALSE; PetscBool fro = PETSC_FALSE,estimate_anorm = PETSC_FALSE; PetscScalar *hwork,lhwork[100]; PetscFunctionBegin; if (m>100) { ierr = PetscMalloc5(m,&omega,m,&omega_old,m,&which,m,&which2,m,&hwork);CHKERRQ(ierr); } else { omega = lomega; omega_old = lomega_old; which = lwhich; which2 = lwhich2; hwork = lhwork; } eps1 = PetscSqrtReal((PetscReal)eps->n)*PETSC_MACHINE_EPSILON/2; delta = PETSC_SQRT_MACHINE_EPSILON/PetscSqrtReal((PetscReal)eps->ncv); eta = PetscPowReal(PETSC_MACHINE_EPSILON,3.0/4.0)/PetscSqrtReal((PetscReal)eps->ncv); if (anorm < 0.0) { anorm = 1.0; estimate_anorm = PETSC_TRUE; } for (i=0;i<m-k;i++) omega[i] = omega_old[i] = 0.0; for (i=0;i<k;i++) which[i] = PETSC_TRUE; ierr = BVSetActiveColumns(eps->V,0,m);CHKERRQ(ierr); for (j=k;j<m;j++) { ierr = BVGetColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVGetColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); ierr = STApply(eps->st,vj,vj1);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); if (fro) { /* Lanczos step with full reorthogonalization */ ierr = BVOrthogonalizeColumn(eps->V,j+1,hwork,&norm,breakdown);CHKERRQ(ierr); alpha[j] = PetscRealPart(hwork[j]); } else { /* Lanczos step */ which[j] = PETSC_TRUE; if (j-2>=k) which[j-2] = PETSC_FALSE; ierr = BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,&norm,breakdown);CHKERRQ(ierr); alpha[j] = PetscRealPart(hwork[j]); beta[j] = norm; /* Estimate ||A|| if needed */ if (estimate_anorm) { if (j>k) anorm = PetscMax(anorm,PetscAbsReal(alpha[j])+norm+beta[j-1]); else anorm = PetscMax(anorm,PetscAbsReal(alpha[j])+norm); } /* Check if reorthogonalization is needed */ reorth = PETSC_FALSE; if (j>k) { update_omega(omega,omega_old,j,alpha,beta-1,eps1,anorm); for (i=0;i<j-k;i++) { if (PetscAbsScalar(omega[i]) > delta) reorth = PETSC_TRUE; } } if (reorth || force_reorth) { for (i=0;i<k;i++) which2[i] = PETSC_FALSE; for (i=k;i<=j;i++) which2[i] = PETSC_TRUE; if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_PERIODIC) { /* Periodic reorthogonalization */ if (force_reorth) force_reorth = PETSC_FALSE; else force_reorth = PETSC_TRUE; for (i=0;i<j-k;i++) omega[i] = eps1; } else { /* Partial reorthogonalization */ if (force_reorth) force_reorth = PETSC_FALSE; else { force_reorth = PETSC_TRUE; compute_int(which2+k,omega,j-k,delta,eta); for (i=0;i<j-k;i++) { if (which2[i+k]) omega[i] = eps1; } } } ierr = BVOrthogonalizeSomeColumn(eps->V,j+1,which2,hwork,&norm,breakdown);CHKERRQ(ierr); } } if (*breakdown || norm < eps->n*anorm*PETSC_MACHINE_EPSILON) { *M = j+1; break; } if (!fro && norm*delta < anorm*eps1) { fro = PETSC_TRUE; ierr = PetscInfo1(eps,"Switching to full reorthogonalization at iteration %D\n",eps->its);CHKERRQ(ierr); } beta[j] = norm; ierr = BVScaleColumn(eps->V,j+1,1.0/norm);CHKERRQ(ierr); } if (m>100) { ierr = PetscFree5(omega,omega_old,which,which2,hwork);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* EPSSelectiveLanczos - Selective reorthogonalization. */ static PetscErrorCode EPSSelectiveLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscReal anorm) { PetscErrorCode ierr; EPS_LANCZOS *lanczos = (EPS_LANCZOS*)eps->data; PetscInt i,j,m = *M,n,nritz=0,nritzo; Vec vj,vj1,av; PetscReal *d,*e,*ritz,norm; PetscScalar *Y,*hwork; PetscBool *which; PetscFunctionBegin; ierr = PetscCalloc6(m+1,&d,m,&e,m,&ritz,m*m,&Y,m,&which,m,&hwork);CHKERRQ(ierr); for (i=0;i<k;i++) which[i] = PETSC_TRUE; for (j=k;j<m;j++) { ierr = BVSetActiveColumns(eps->V,0,m);CHKERRQ(ierr); /* Lanczos step */ ierr = BVGetColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVGetColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); ierr = STApply(eps->st,vj,vj1);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j,&vj);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); which[j] = PETSC_TRUE; if (j-2>=k) which[j-2] = PETSC_FALSE; ierr = BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,&norm,breakdown);CHKERRQ(ierr); alpha[j] = PetscRealPart(hwork[j]); beta[j] = norm; if (*breakdown) { *M = j+1; break; } /* Compute eigenvalues and eigenvectors Y of the tridiagonal block */ n = j-k+1; for (i=0;i<n;i++) { d[i] = alpha[i+k]; e[i] = beta[i+k]; } ierr = DenseTridiagonal(n,d,e,ritz,Y);CHKERRQ(ierr); /* Estimate ||A|| */ for (i=0;i<n;i++) if (PetscAbsReal(ritz[i]) > anorm) anorm = PetscAbsReal(ritz[i]); /* Compute nearly converged Ritz vectors */ nritzo = 0; for (i=0;i<n;i++) { if (norm*PetscAbsScalar(Y[i*n+n-1]) < PETSC_SQRT_MACHINE_EPSILON*anorm) nritzo++; } if (nritzo>nritz) { nritz = 0; for (i=0;i<n;i++) { if (norm*PetscAbsScalar(Y[i*n+n-1]) < PETSC_SQRT_MACHINE_EPSILON*anorm) { ierr = BVSetActiveColumns(eps->V,k,k+n);CHKERRQ(ierr); ierr = BVGetColumn(lanczos->AV,nritz,&av);CHKERRQ(ierr); ierr = BVMultVec(eps->V,1.0,0.0,av,Y+i*n);CHKERRQ(ierr); ierr = BVRestoreColumn(lanczos->AV,nritz,&av);CHKERRQ(ierr); nritz++; } } } if (nritz > 0) { ierr = BVGetColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); ierr = BVSetActiveColumns(lanczos->AV,0,nritz);CHKERRQ(ierr); ierr = BVOrthogonalizeVec(lanczos->AV,vj1,hwork,&norm,breakdown);CHKERRQ(ierr); ierr = BVRestoreColumn(eps->V,j+1,&vj1);CHKERRQ(ierr); if (*breakdown) { *M = j+1; break; } } ierr = BVScaleColumn(eps->V,j+1,1.0/norm);CHKERRQ(ierr); } ierr = PetscFree6(d,e,ritz,Y,which,hwork);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode EPSSolve_Arnoldi(EPS eps) { PetscErrorCode ierr; PetscInt k,nv,ld; Mat U; PetscScalar *H,*X; PetscReal beta,gamma=1.0; PetscBool breakdown,harmonic,refined; BVOrthogRefineType orthog_ref; EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data; PetscFunctionBegin; ierr = DSGetLeadingDimension(eps->ds,&ld);CHKERRQ(ierr); ierr = DSGetRefined(eps->ds,&refined);CHKERRQ(ierr); harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE; ierr = BVGetOrthogonalization(eps->V,NULL,&orthog_ref,NULL);CHKERRQ(ierr); /* Get the starting Arnoldi vector */ ierr = EPSGetStartVector(eps,0,NULL);CHKERRQ(ierr); /* Restart loop */ while (eps->reason == EPS_CONVERGED_ITERATING) { eps->its++; /* Compute an nv-step Arnoldi factorization */ nv = PetscMin(eps->nconv+eps->mpd,eps->ncv); ierr = DSSetDimensions(eps->ds,nv,0,eps->nconv,0);CHKERRQ(ierr); ierr = DSGetArray(eps->ds,DS_MAT_A,&H);CHKERRQ(ierr); if (!arnoldi->delayed) { ierr = EPSBasicArnoldi(eps,PETSC_FALSE,H,ld,eps->nconv,&nv,&beta,&breakdown);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)eps),1,"Not implemented"); /*if (orthog_ref == BV_ORTHOG_REFINE_NEVER) { ierr = EPSDelayedArnoldi1(eps,H,ld,eps->V,eps->nconv,&nv,f,&beta,&breakdown);CHKERRQ(ierr); } else { ierr = EPSDelayedArnoldi(eps,H,ld,eps->V,eps->nconv,&nv,f,&beta,&breakdown);CHKERRQ(ierr); }*/ ierr = DSRestoreArray(eps->ds,DS_MAT_A,&H);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); ierr = BVSetActiveColumns(eps->V,eps->nconv,nv);CHKERRQ(ierr); /* Compute translation of Krylov decomposition if harmonic extraction used */ if (harmonic) { ierr = DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,NULL,&gamma);CHKERRQ(ierr); } /* Solve projected problem */ ierr = DSSolve(eps->ds,eps->eigr,eps->eigi);CHKERRQ(ierr); ierr = DSSort(eps->ds,eps->eigr,eps->eigi,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DSUpdateExtraRow(eps->ds);CHKERRQ(ierr); /* Check convergence */ ierr = EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);CHKERRQ(ierr); if (refined) { ierr = DSGetArray(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = BVMultColumn(eps->V,1.0,0.0,k,X+k*ld);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,nv);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); ierr = BVOrthogonalizeColumn(eps->V,k,NULL,NULL,NULL);CHKERRQ(ierr); } else { ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,nv);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); } eps->nconv = k; ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);CHKERRQ(ierr); if (breakdown && k<eps->nev) { ierr = PetscInfo2(eps,"Breakdown in Arnoldi method (it=%D norm=%g)\n",eps->its,(double)beta);CHKERRQ(ierr); ierr = EPSGetStartVector(eps,k,&breakdown);CHKERRQ(ierr); if (breakdown) { eps->reason = EPS_DIVERGED_BREAKDOWN; ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr); } } if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS; if (eps->nconv >= eps->nev) eps->reason = EPS_CONVERGED_TOL; } /* truncate Schur decomposition and change the state to raw so that PSVectors() computes eigenvectors from scratch */ ierr = DSSetDimensions(eps->ds,eps->nconv,0,0,0);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; Vec t,v; Mat Q,M; BV X,Y; PetscInt i,j,n=10,kx=6,lx=3,ky=5,ly=2; PetscScalar *q,*z; PetscReal nrm; PetscViewer view; PetscBool verbose,trans; SlepcInitialize(&argc,&argv,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-kx",&kx,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-lx",&lx,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-ky",&ky,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-ly",&ly,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-verbose",&verbose);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"First BV with %D active columns (%D leading columns) of dimension %D.\n",kx,lx,n);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Second BV with %D active columns (%D leading columns) of dimension %D.\n",ky,ly,n);CHKERRQ(ierr); /* Create template vector */ ierr = VecCreate(PETSC_COMM_WORLD,&t);CHKERRQ(ierr); ierr = VecSetSizes(t,PETSC_DECIDE,n);CHKERRQ(ierr); ierr = VecSetFromOptions(t);CHKERRQ(ierr); /* Create BV object X */ ierr = BVCreate(PETSC_COMM_WORLD,&X);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)X,"X");CHKERRQ(ierr); ierr = BVSetSizesFromVec(X,t,kx+2);CHKERRQ(ierr); /* two extra columns to test active columns */ ierr = BVSetFromOptions(X);CHKERRQ(ierr); ierr = BVSetActiveColumns(X,lx,kx);CHKERRQ(ierr); /* Set up viewer */ ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&view);CHKERRQ(ierr); if (verbose) { ierr = PetscViewerPushFormat(view,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr); } /* Fill X entries */ for (j=0;j<kx+2;j++) { ierr = BVGetColumn(X,j,&v);CHKERRQ(ierr); ierr = VecZeroEntries(v);CHKERRQ(ierr); for (i=0;i<4;i++) { if (i+j<n) { ierr = VecSetValue(v,i+j,(PetscScalar)(3*i+j-2),INSERT_VALUES);CHKERRQ(ierr); } } ierr = VecAssemblyBegin(v);CHKERRQ(ierr); ierr = VecAssemblyEnd(v);CHKERRQ(ierr); ierr = BVRestoreColumn(X,j,&v);CHKERRQ(ierr); } if (verbose) { ierr = BVView(X,view);CHKERRQ(ierr); } /* Create BV object Y */ ierr = BVCreate(PETSC_COMM_WORLD,&Y);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)Y,"Y");CHKERRQ(ierr); ierr = BVSetSizesFromVec(Y,t,ky+1);CHKERRQ(ierr); ierr = BVSetFromOptions(Y);CHKERRQ(ierr); ierr = BVSetActiveColumns(Y,ly,ky);CHKERRQ(ierr); /* Fill Y entries */ for (j=0;j<ky+1;j++) { ierr = BVGetColumn(Y,j,&v);CHKERRQ(ierr); ierr = VecSet(v,(PetscScalar)(j+1)/4.0);CHKERRQ(ierr); ierr = BVRestoreColumn(Y,j,&v);CHKERRQ(ierr); } if (verbose) { ierr = BVView(Y,view);CHKERRQ(ierr); } /* Create Mat */ ierr = MatCreateSeqDense(PETSC_COMM_SELF,kx,ky,NULL,&Q);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)Q,"Q");CHKERRQ(ierr); ierr = MatDenseGetArray(Q,&q);CHKERRQ(ierr); for (i=0;i<kx;i++) for (j=0;j<ky;j++) q[i+j*kx] = (i<j)? 2.0: -0.5; ierr = MatDenseRestoreArray(Q,&q);CHKERRQ(ierr); if (verbose) { ierr = MatView(Q,NULL);CHKERRQ(ierr); } /* Test BVMult */ ierr = BVMult(Y,2.0,1.0,X,Q);CHKERRQ(ierr); if (verbose) { ierr = PetscPrintf(PETSC_COMM_WORLD,"After BVMult - - - - - - - - -\n");CHKERRQ(ierr); ierr = BVView(Y,view);CHKERRQ(ierr); } /* Test BVMultVec */ ierr = BVGetColumn(Y,0,&v);CHKERRQ(ierr); ierr = PetscMalloc1(kx-lx,&z);CHKERRQ(ierr); z[0] = 2.0; for (i=1;i<kx-lx;i++) z[i] = -0.5*z[i-1]; ierr = BVMultVec(X,-1.0,1.0,v,z);CHKERRQ(ierr); ierr = PetscFree(z);CHKERRQ(ierr); ierr = BVRestoreColumn(Y,0,&v);CHKERRQ(ierr); if (verbose) { ierr = PetscPrintf(PETSC_COMM_WORLD,"After BVMultVec - - - - - - -\n");CHKERRQ(ierr); ierr = BVView(Y,view);CHKERRQ(ierr); } /* Test BVDot */ ierr = MatCreateSeqDense(PETSC_COMM_SELF,ky,kx,NULL,&M);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)M,"M");CHKERRQ(ierr); ierr = BVDot(X,Y,M);CHKERRQ(ierr); if (verbose) { ierr = PetscPrintf(PETSC_COMM_WORLD,"After BVDot - - - - - - - - -\n");CHKERRQ(ierr); ierr = MatView(M,NULL);CHKERRQ(ierr); } /* Test BVDotVec */ ierr = BVGetColumn(Y,0,&v);CHKERRQ(ierr); ierr = PetscMalloc1(kx-lx,&z);CHKERRQ(ierr); ierr = BVDotVec(X,v,z);CHKERRQ(ierr); ierr = BVRestoreColumn(Y,0,&v);CHKERRQ(ierr); if (verbose) { ierr = PetscPrintf(PETSC_COMM_WORLD,"After BVDotVec - - - - - - -\n");CHKERRQ(ierr); ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,kx-lx,z,&v);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)v,"z");CHKERRQ(ierr); ierr = VecView(v,view);CHKERRQ(ierr); ierr = VecDestroy(&v);CHKERRQ(ierr); } ierr = PetscFree(z);CHKERRQ(ierr); /* Test BVMultInPlace and BVScale */ ierr = PetscOptionsHasName(NULL,"-trans",&trans);CHKERRQ(ierr); if (trans) { Mat Qt; ierr = MatTranspose(Q,MAT_INITIAL_MATRIX,&Qt);CHKERRQ(ierr); ierr = BVMultInPlaceTranspose(X,Qt,lx+1,ky);CHKERRQ(ierr); ierr = MatDestroy(&Qt);CHKERRQ(ierr); } else { ierr = BVMultInPlace(X,Q,lx+1,ky);CHKERRQ(ierr); } ierr = BVScale(X,2.0);CHKERRQ(ierr); if (verbose) { ierr = PetscPrintf(PETSC_COMM_WORLD,"After BVMultInPlace - - - - -\n");CHKERRQ(ierr); ierr = BVView(X,view);CHKERRQ(ierr); } /* Test BVNorm */ ierr = BVNormColumn(X,lx,NORM_2,&nrm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"2-Norm or X[%D] = %g\n",lx,(double)nrm);CHKERRQ(ierr); ierr = BVNorm(X,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Frobenius Norm or X = %g\n",(double)nrm);CHKERRQ(ierr); ierr = BVDestroy(&X);CHKERRQ(ierr); ierr = BVDestroy(&Y);CHKERRQ(ierr); ierr = MatDestroy(&Q);CHKERRQ(ierr); ierr = MatDestroy(&M);CHKERRQ(ierr); ierr = VecDestroy(&t);CHKERRQ(ierr); ierr = SlepcFinalize(); return 0; }
PetscErrorCode EPSSolve_KrylovSchur_Default(EPS eps) { PetscErrorCode ierr; EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data; PetscInt i,j,*pj,k,l,nv,ld; Mat U; PetscScalar *S,*Q,*g; PetscReal beta,gamma=1.0; PetscBool breakdown,harmonic; PetscFunctionBegin; ierr = DSGetLeadingDimension(eps->ds,&ld);CHKERRQ(ierr); harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE; if (harmonic) { ierr = PetscMalloc1(ld,&g);CHKERRQ(ierr); } if (eps->arbitrary) pj = &j; else pj = NULL; /* Get the starting Arnoldi vector */ ierr = EPSGetStartVector(eps,0,NULL);CHKERRQ(ierr); l = 0; /* Restart loop */ while (eps->reason == EPS_CONVERGED_ITERATING) { eps->its++; /* Compute an nv-step Arnoldi factorization */ nv = PetscMin(eps->nconv+eps->mpd,eps->ncv); ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,ld,eps->nconv+l,&nv,&beta,&breakdown);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSSetDimensions(eps->ds,nv,0,eps->nconv,eps->nconv+l);CHKERRQ(ierr); if (l==0) { ierr = DSSetState(eps->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); } else { ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); } ierr = BVSetActiveColumns(eps->V,eps->nconv,nv);CHKERRQ(ierr); /* Compute translation of Krylov decomposition if harmonic extraction used */ if (harmonic) { ierr = DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,g,&gamma);CHKERRQ(ierr); } /* Solve projected problem */ ierr = DSSolve(eps->ds,eps->eigr,eps->eigi);CHKERRQ(ierr); if (eps->arbitrary) { ierr = EPSGetArbitraryValues(eps,eps->rr,eps->ri);CHKERRQ(ierr); j=1; } ierr = DSSort(eps->ds,eps->eigr,eps->eigi,eps->rr,eps->ri,pj);CHKERRQ(ierr); /* Check convergence */ ierr = EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);CHKERRQ(ierr); if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS; if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL; /* Update l */ if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0; else { l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep)); #if !defined(PETSC_USE_COMPLEX) ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); if (S[k+l+(k+l-1)*ld] != 0.0) { if (k+l<nv-1) l = l+1; else l = l-1; } ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); #endif } if (eps->reason == EPS_CONVERGED_ITERATING) { if (breakdown) { /* Start a new Arnoldi factorization */ ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%g)\n",eps->its,(double)beta);CHKERRQ(ierr); if (k<eps->nev) { ierr = EPSGetStartVector(eps,k,&breakdown);CHKERRQ(ierr); if (breakdown) { eps->reason = EPS_DIVERGED_BREAKDOWN; ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr); } } } else { /* Undo translation of Krylov decomposition */ if (harmonic) { ierr = DSSetDimensions(eps->ds,nv,0,k,l);CHKERRQ(ierr); ierr = DSTranslateHarmonic(eps->ds,0.0,beta,PETSC_TRUE,g,&gamma);CHKERRQ(ierr); /* gamma u^ = u - U*g~ */ ierr = BVMultColumn(eps->V,-1.0,1.0,nv,g);CHKERRQ(ierr); ierr = BVScaleColumn(eps->V,nv,1.0/gamma);CHKERRQ(ierr); } /* Prepare the Rayleigh quotient for restart */ ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSGetArray(eps->ds,DS_MAT_Q,&Q);CHKERRQ(ierr); for (i=k;i<k+l;i++) { S[k+l+i*ld] = Q[nv-1+i*ld]*beta*gamma; } ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_Q,&Q);CHKERRQ(ierr); } } /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */ ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,k+l);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) { ierr = BVCopyColumn(eps->V,nv,k+l);CHKERRQ(ierr); } eps->nconv = k; ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);CHKERRQ(ierr); } if (harmonic) { ierr = PetscFree(g);CHKERRQ(ierr); } /* truncate Schur decomposition and change the state to raw so that PSVectors() computes eigenvectors from scratch */ ierr = DSSetDimensions(eps->ds,eps->nconv,0,0,0);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode NEPSolve_NArnoldi(NEP nep) { PetscErrorCode ierr; Mat T=nep->function,Tsigma; Vec f,r=nep->work[0],x=nep->work[1],w=nep->work[2]; PetscScalar *X,lambda; PetscReal beta,resnorm=0.0,nrm; PetscInt n; PetscBool breakdown; KSPConvergedReason kspreason; PetscFunctionBegin; /* get initial space and shift */ ierr = NEPGetDefaultShift(nep,&lambda);CHKERRQ(ierr); if (!nep->nini) { ierr = BVSetRandomColumn(nep->V,0,nep->rand);CHKERRQ(ierr); ierr = BVNormColumn(nep->V,0,NORM_2,&nrm);CHKERRQ(ierr); ierr = BVScaleColumn(nep->V,0,1.0/nrm);CHKERRQ(ierr); n = 1; } else n = nep->nini; /* build projected matrices for initial space */ ierr = DSSetDimensions(nep->ds,n,0,0,0);CHKERRQ(ierr); ierr = NEPProjectOperator(nep,0,n);CHKERRQ(ierr); /* prepare linear solver */ ierr = NEPComputeFunction(nep,lambda,T,T);CHKERRQ(ierr); ierr = MatDuplicate(T,MAT_COPY_VALUES,&Tsigma);CHKERRQ(ierr); ierr = KSPSetOperators(nep->ksp,Tsigma,Tsigma);CHKERRQ(ierr); /* Restart loop */ while (nep->reason == NEP_CONVERGED_ITERATING) { nep->its++; /* solve projected problem */ ierr = DSSetDimensions(nep->ds,n,0,0,0);CHKERRQ(ierr); ierr = DSSetState(nep->ds,DS_STATE_RAW);CHKERRQ(ierr); ierr = DSSolve(nep->ds,nep->eigr,NULL);CHKERRQ(ierr); lambda = nep->eigr[0]; /* compute Ritz vector, x = V*s */ ierr = DSGetArray(nep->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = BVSetActiveColumns(nep->V,0,n);CHKERRQ(ierr); ierr = BVMultVec(nep->V,1.0,0.0,x,X);CHKERRQ(ierr); ierr = DSRestoreArray(nep->ds,DS_MAT_X,&X);CHKERRQ(ierr); /* compute the residual, r = T(lambda)*x */ ierr = NEPApplyFunction(nep,lambda,x,w,r,NULL,NULL);CHKERRQ(ierr); /* convergence test */ ierr = VecNorm(r,NORM_2,&resnorm);CHKERRQ(ierr); nep->errest[nep->nconv] = resnorm; if (resnorm<=nep->rtol) { ierr = BVInsertVec(nep->V,nep->nconv,x);CHKERRQ(ierr); nep->nconv = nep->nconv + 1; nep->reason = NEP_CONVERGED_FNORM_RELATIVE; } ierr = NEPMonitor(nep,nep->its,nep->nconv,nep->eigr,nep->errest,1);CHKERRQ(ierr); if (nep->reason == NEP_CONVERGED_ITERATING) { /* continuation vector: f = T(sigma)\r */ ierr = BVGetColumn(nep->V,n,&f);CHKERRQ(ierr); ierr = NEP_KSPSolve(nep,r,f);CHKERRQ(ierr); ierr = BVRestoreColumn(nep->V,n,&f);CHKERRQ(ierr); ierr = KSPGetConvergedReason(nep->ksp,&kspreason);CHKERRQ(ierr); if (kspreason<0) { ierr = PetscInfo1(nep,"iter=%D, linear solve failed, stopping solve\n",nep->its);CHKERRQ(ierr); nep->reason = NEP_DIVERGED_LINEAR_SOLVE; break; } /* orthonormalize */ ierr = BVOrthogonalizeColumn(nep->V,n,NULL,&beta,&breakdown);CHKERRQ(ierr); if (breakdown || beta==0.0) { ierr = PetscInfo1(nep,"iter=%D, orthogonalization failed, stopping solve\n",nep->its);CHKERRQ(ierr); nep->reason = NEP_DIVERGED_BREAKDOWN; break; } ierr = BVScaleColumn(nep->V,n,1.0/beta);CHKERRQ(ierr); /* update projected matrices */ ierr = DSSetDimensions(nep->ds,n+1,0,0,0);CHKERRQ(ierr); ierr = NEPProjectOperator(nep,n,n+1);CHKERRQ(ierr); n++; } if (nep->its >= nep->max_it) nep->reason = NEP_DIVERGED_MAX_IT; } ierr = MatDestroy(&Tsigma);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SVDSolve_TRLanczos(SVD svd) { PetscErrorCode ierr; SVD_TRLANCZOS *lanczos = (SVD_TRLANCZOS*)svd->data; PetscReal *alpha,*beta,lastbeta,norm; PetscScalar *Q,*swork=NULL,*w; PetscInt i,k,l,nv,ld; Mat U,VT; PetscBool conv; BVOrthogType orthog; PetscFunctionBegin; /* allocate working space */ ierr = DSGetLeadingDimension(svd->ds,&ld);CHKERRQ(ierr); ierr = BVGetOrthogonalization(svd->V,&orthog,NULL,NULL);CHKERRQ(ierr); ierr = PetscMalloc1(ld,&w);CHKERRQ(ierr); if (lanczos->oneside && orthog == BV_ORTHOG_CGS) { ierr = PetscMalloc1(svd->ncv+1,&swork);CHKERRQ(ierr); } /* normalize start vector */ if (!svd->nini) { ierr = BVSetRandomColumn(svd->V,0,svd->rand);CHKERRQ(ierr); ierr = BVNormColumn(svd->V,0,NORM_2,&norm);CHKERRQ(ierr); ierr = BVScaleColumn(svd->V,0,1.0/norm);CHKERRQ(ierr); } l = 0; while (svd->reason == SVD_CONVERGED_ITERATING) { svd->its++; /* inner loop */ nv = PetscMin(svd->nconv+svd->mpd,svd->ncv); ierr = BVSetActiveColumns(svd->V,svd->nconv,nv);CHKERRQ(ierr); ierr = BVSetActiveColumns(svd->U,svd->nconv,nv);CHKERRQ(ierr); ierr = DSGetArrayReal(svd->ds,DS_MAT_T,&alpha);CHKERRQ(ierr); beta = alpha + ld; if (lanczos->oneside) { if (orthog == BV_ORTHOG_MGS) { ierr = SVDOneSideTRLanczosMGS(svd,alpha,beta,svd->V,svd->U,svd->nconv,l,nv);CHKERRQ(ierr); } else { ierr = SVDOneSideTRLanczosCGS(svd,alpha,beta,svd->V,svd->U,svd->nconv,l,nv,swork);CHKERRQ(ierr); } } else { ierr = SVDTwoSideLanczos(svd,alpha,beta,svd->V,svd->U,svd->nconv+l,nv);CHKERRQ(ierr); } lastbeta = beta[nv-1]; ierr = DSRestoreArrayReal(svd->ds,DS_MAT_T,&alpha);CHKERRQ(ierr); ierr = BVScaleColumn(svd->V,nv,1.0/lastbeta);CHKERRQ(ierr); /* compute SVD of general matrix */ ierr = DSSetDimensions(svd->ds,nv,nv,svd->nconv,svd->nconv+l);CHKERRQ(ierr); if (l==0) { ierr = DSSetState(svd->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); } else { ierr = DSSetState(svd->ds,DS_STATE_RAW);CHKERRQ(ierr); } ierr = DSSolve(svd->ds,w,NULL);CHKERRQ(ierr); ierr = DSSort(svd->ds,w,NULL,NULL,NULL,NULL);CHKERRQ(ierr); /* compute error estimates */ k = 0; conv = PETSC_TRUE; ierr = DSGetArray(svd->ds,DS_MAT_U,&Q);CHKERRQ(ierr); ierr = DSGetArrayReal(svd->ds,DS_MAT_T,&alpha);CHKERRQ(ierr); beta = alpha + ld; for (i=svd->nconv;i<nv;i++) { svd->sigma[i] = PetscRealPart(w[i]); beta[i] = PetscRealPart(Q[nv-1+i*ld])*lastbeta; svd->errest[i] = PetscAbsScalar(beta[i]); if (svd->sigma[i] > svd->tol) svd->errest[i] /= svd->sigma[i]; if (conv) { if (svd->errest[i] < svd->tol) k++; else conv = PETSC_FALSE; } } ierr = DSRestoreArrayReal(svd->ds,DS_MAT_T,&alpha);CHKERRQ(ierr); ierr = DSRestoreArray(svd->ds,DS_MAT_U,&Q);CHKERRQ(ierr); /* check convergence and update l */ if (svd->its >= svd->max_it) svd->reason = SVD_DIVERGED_ITS; if (svd->nconv+k >= svd->nsv) svd->reason = SVD_CONVERGED_TOL; if (svd->reason != SVD_CONVERGED_ITERATING) l = 0; else l = PetscMax((nv-svd->nconv-k)/2,0); /* compute converged singular vectors and restart vectors */ ierr = DSGetMat(svd->ds,DS_MAT_VT,&VT);CHKERRQ(ierr); ierr = BVMultInPlaceTranspose(svd->V,VT,svd->nconv,svd->nconv+k+l);CHKERRQ(ierr); ierr = MatDestroy(&VT);CHKERRQ(ierr); ierr = DSGetMat(svd->ds,DS_MAT_U,&U);CHKERRQ(ierr); ierr = BVMultInPlace(svd->U,U,svd->nconv,svd->nconv+k+l);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); /* copy the last vector to be the next initial vector */ if (svd->reason == SVD_CONVERGED_ITERATING) { ierr = BVCopyColumn(svd->V,nv,svd->nconv+k+l);CHKERRQ(ierr); } svd->nconv += k; ierr = SVDMonitor(svd,svd->its,svd->nconv,svd->sigma,svd->errest,nv);CHKERRQ(ierr); } /* orthonormalize U columns in one side method */ if (lanczos->oneside) { for (i=0;i<svd->nconv;i++) { ierr = BVOrthogonalizeColumn(svd->U,i,NULL,&norm,NULL);CHKERRQ(ierr); ierr = BVScaleColumn(svd->U,i,1.0/norm);CHKERRQ(ierr); } } /* free working space */ ierr = PetscFree(w);CHKERRQ(ierr); if (swork) { ierr = PetscFree(swork);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode SVDOneSideTRLanczosCGS(SVD svd,PetscReal *alpha,PetscReal *beta,BV V,BV U,PetscInt nconv,PetscInt l,PetscInt n,PetscScalar* work) { PetscErrorCode ierr; PetscReal a,b,eta; PetscScalar gamma; PetscInt i,j,k=nconv+l; Vec ui,ui1,vi; BVOrthogRefineType refine; PetscFunctionBegin; ierr = BVGetColumn(V,k,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,k,&ui);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_FALSE,vi,ui);CHKERRQ(ierr); ierr = BVRestoreColumn(V,k,&vi);CHKERRQ(ierr); ierr = BVRestoreColumn(U,k,&ui);CHKERRQ(ierr); if (l>0) { ierr = BVMultColumn(U,-1.0,1.0,k,&gamma);CHKERRQ(ierr); beta[nconv] = PetscRealPart(gamma); } ierr = BVGetOrthogonalization(V,NULL,&refine,&eta);CHKERRQ(ierr); for (i=k+1;i<n;i++) { ierr = BVGetColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,i-1,&ui1);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_TRUE,ui1,vi);CHKERRQ(ierr); ierr = BVRestoreColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVRestoreColumn(U,i-1,&ui1);CHKERRQ(ierr); ierr = BVNormColumn(U,i-1,NORM_2,&a);CHKERRQ(ierr); if (refine == BV_ORTHOG_REFINE_IFNEEDED) { ierr = BVSetActiveColumns(V,0,i+1);CHKERRQ(ierr); ierr = BVGetColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVDotVec(V,vi,work);CHKERRQ(ierr); ierr = BVRestoreColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVSetActiveColumns(V,0,i);CHKERRQ(ierr); } else { ierr = BVSetActiveColumns(V,0,i);CHKERRQ(ierr); ierr = BVDotColumn(V,i,work);CHKERRQ(ierr); } ierr = BVScaleColumn(U,i-1,1.0/a);CHKERRQ(ierr); for (j=0;j<i;j++) work[j] = work[j] / a; ierr = BVMultColumn(V,-1.0,1.0/a,i,work);CHKERRQ(ierr); ierr = SVDOrthogonalizeCGS(V,i,work,a,refine,eta,&b);CHKERRQ(ierr); ierr = BVScaleColumn(V,i,1.0/b);CHKERRQ(ierr); ierr = BVGetColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,i,&ui);CHKERRQ(ierr); ierr = BVGetColumn(U,i-1,&ui1);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_FALSE,vi,ui);CHKERRQ(ierr); ierr = VecAXPY(ui,-b,ui1);CHKERRQ(ierr); ierr = BVRestoreColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVRestoreColumn(U,i,&ui);CHKERRQ(ierr); ierr = BVRestoreColumn(U,i-1,&ui1);CHKERRQ(ierr); alpha[i-1] = a; beta[i-1] = b; } ierr = BVGetColumn(V,n,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,n-1,&ui1);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_TRUE,ui1,vi);CHKERRQ(ierr); ierr = BVRestoreColumn(V,n,&vi);CHKERRQ(ierr); ierr = BVRestoreColumn(U,n-1,&ui1);CHKERRQ(ierr); ierr = BVNormColumn(svd->U,n-1,NORM_2,&a);CHKERRQ(ierr); if (refine == BV_ORTHOG_REFINE_IFNEEDED) { ierr = BVSetActiveColumns(V,0,n+1);CHKERRQ(ierr); ierr = BVGetColumn(V,n,&vi);CHKERRQ(ierr); ierr = BVDotVec(V,vi,work);CHKERRQ(ierr); ierr = BVRestoreColumn(V,n,&vi);CHKERRQ(ierr); } else { ierr = BVSetActiveColumns(V,0,n);CHKERRQ(ierr); ierr = BVDotColumn(V,n,work);CHKERRQ(ierr); } ierr = BVScaleColumn(U,n-1,1.0/a);CHKERRQ(ierr); for (j=0;j<n;j++) work[j] = work[j] / a; ierr = BVMultColumn(V,-1.0,1.0/a,n,work);CHKERRQ(ierr); ierr = SVDOrthogonalizeCGS(V,n,work,a,refine,eta,&b);CHKERRQ(ierr); ierr = BVSetActiveColumns(V,nconv,n);CHKERRQ(ierr); alpha[n-1] = a; beta[n-1] = b; PetscFunctionReturn(0); }