static PetscErrorCode BVOrthogonalize_GS(BV V,Mat R) { PetscErrorCode ierr; PetscScalar *r=NULL; PetscReal norm; PetscInt j,ldr; PetscFunctionBegin; ldr = V->k; if (R) { ierr = MatDenseGetArray(R,&r);CHKERRQ(ierr); ierr = PetscMemzero(r+V->l*ldr,ldr*(ldr-V->l)*sizeof(PetscScalar));CHKERRQ(ierr); } for (j=V->l;j<V->k;j++) { if (R) { ierr = BVOrthogonalizeColumn(V,j,r+j*ldr,&norm,NULL);CHKERRQ(ierr); r[j+j*ldr] = norm; } else { ierr = BVOrthogonalizeColumn(V,j,NULL,&norm,NULL);CHKERRQ(ierr); } ierr = BVScaleColumn(V,j,1.0/norm);CHKERRQ(ierr); } if (R) { ierr = MatDenseRestoreArray(R,&r);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode SVDOneSideTRLanczosMGS(SVD svd,PetscReal *alpha,PetscReal *beta,BV V,BV U,PetscInt nconv,PetscInt l,PetscInt n) { PetscErrorCode ierr; PetscReal a,b; PetscScalar gamma; PetscInt i,k=nconv+l; Vec ui,ui1,vi; 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 = BVNormColumn(U,k,NORM_2,&a);CHKERRQ(ierr); ierr = BVScaleColumn(U,k,1.0/a);CHKERRQ(ierr); alpha[k] = a; 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 = BVOrthogonalizeColumn(V,i,NULL,&b,NULL);CHKERRQ(ierr); ierr = BVScaleColumn(V,i,1.0/b);CHKERRQ(ierr); beta[i-1] = b; ierr = BVGetColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,i,&ui);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_FALSE,vi,ui);CHKERRQ(ierr); ierr = BVRestoreColumn(V,i,&vi);CHKERRQ(ierr); ierr = BVGetColumn(U,i-1,&ui1);CHKERRQ(ierr); ierr = VecAXPY(ui,-b,ui1);CHKERRQ(ierr); ierr = BVRestoreColumn(U,i-1,&ui1);CHKERRQ(ierr); ierr = BVRestoreColumn(U,i,&ui);CHKERRQ(ierr); ierr = BVNormColumn(U,i,NORM_2,&a);CHKERRQ(ierr); ierr = BVScaleColumn(U,i,1.0/a);CHKERRQ(ierr); alpha[i] = a; } 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 = BVOrthogonalizeColumn(V,n,NULL,&b,NULL);CHKERRQ(ierr); beta[n-1] = b; PetscFunctionReturn(0); }
/*@ BVInsertVecs - Insert a set of vectors into the specified columns. Collective on BV Input Parameters: + V - basis vectors . s - first column of V to be overwritten . W - set of vectors to be copied - orth - flag indicating if the vectors must be orthogonalized Input/Output Parameter: . m - number of input vectors, on output the number of linearly independent vectors Notes: Copies the contents of vectors W to V(:,s:s+n). If the orthogonalization flag is set, then the vectors are copied one by one and then orthogonalized against the previous ones. If any of them is linearly dependent then it is discarded and the value of m is decreased. Level: intermediate .seealso: BVInsertVec(), BVOrthogonalizeColumn() @*/ PetscErrorCode BVInsertVecs(BV V,PetscInt s,PetscInt *m,Vec *W,PetscBool orth) { PetscErrorCode ierr; PetscInt n,N,i,ndep; PetscBool lindep; PetscReal norm; Vec v; PetscFunctionBegin; PetscValidHeaderSpecific(V,BV_CLASSID,1); PetscValidLogicalCollectiveInt(V,s,2); PetscValidPointer(m,3); PetscValidLogicalCollectiveInt(V,*m,3); if (!*m) PetscFunctionReturn(0); if (*m<0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",*m); PetscValidPointer(W,4); PetscValidHeaderSpecific(*W,VEC_CLASSID,4); PetscValidLogicalCollectiveBool(V,orth,5); PetscValidType(V,1); BVCheckSizes(V,1); PetscCheckSameComm(V,1,*W,4); ierr = VecGetSize(*W,&N);CHKERRQ(ierr); ierr = VecGetLocalSize(*W,&n);CHKERRQ(ierr); if (N!=V->N || n!=V->n) SETERRQ4(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %D, local %D) do not match BV sizes (global %D, local %D)",N,n,V->N,V->n); if (s<0 || s>=V->m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument s has wrong value %D, should be between 0 and %D",s,V->m-1); if (s+(*m)>V->m) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Too many vectors provided, there is only room for %D",V->m); ndep = 0; for (i=0;i<*m;i++) { ierr = BVGetColumn(V,s+i-ndep,&v);CHKERRQ(ierr); ierr = VecCopy(W[i],v);CHKERRQ(ierr); ierr = BVRestoreColumn(V,s+i-ndep,&v);CHKERRQ(ierr); if (orth) { ierr = BVOrthogonalizeColumn(V,s+i-ndep,NULL,&norm,&lindep);CHKERRQ(ierr); if (norm==0.0 || lindep) { ierr = PetscInfo1(V,"Removing linearly dependent vector %D\n",i);CHKERRQ(ierr); ndep++; } else { ierr = BVScaleColumn(V,s+i-ndep,1.0/norm);CHKERRQ(ierr); } } } *m -= ndep; ierr = PetscObjectStateIncrease((PetscObject)V);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ SVDGetSingularTriplet - Gets the i-th triplet of the singular value decomposition as computed by SVDSolve(). The solution consists in the singular value and its left and right singular vectors. Not Collective, but vectors are shared by all processors that share the SVD Input Parameters: + svd - singular value solver context - i - index of the solution Output Parameters: + sigma - singular value . u - left singular vector - v - right singular vector Note: The index i should be a value between 0 and nconv-1 (see SVDGetConverged()). Both U or V can be NULL if singular vectors are not required. Level: beginner .seealso: SVDSolve(), SVDGetConverged() @*/ PetscErrorCode SVDGetSingularTriplet(SVD svd,PetscInt i,PetscReal *sigma,Vec u,Vec v) { PetscErrorCode ierr; PetscReal norm; PetscInt j,M,N; Vec w,tl,vj,uj; PetscFunctionBegin; PetscValidHeaderSpecific(svd,SVD_CLASSID,1); if (u) { PetscValidHeaderSpecific(u,VEC_CLASSID,4); PetscCheckSameComm(svd,1,u,4); } if (v) { PetscValidHeaderSpecific(v,VEC_CLASSID,5); PetscCheckSameComm(svd,1,v,5); } if (svd->reason == SVD_CONVERGED_ITERATING) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_WRONGSTATE,"SVDSolve must be called first"); if (i<0 || i>=svd->nconv) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range"); *sigma = svd->sigma[svd->perm[i]]; ierr = MatGetSize(svd->OP,&M,&N);CHKERRQ(ierr); if (M<N) { w = u; u = v; v = w; } if (u) { if (!svd->lvecsavail) { /* generate left singular vectors on U */ if (!svd->U) { ierr = SVDGetBV(svd,NULL,&svd->U);CHKERRQ(ierr); } ierr = SVDMatGetVecs(svd,NULL,&tl);CHKERRQ(ierr); ierr = BVSetSizesFromVec(svd->U,tl,svd->ncv);CHKERRQ(ierr); ierr = VecDestroy(&tl);CHKERRQ(ierr); for (j=0;j<svd->nconv;j++) { ierr = BVGetColumn(svd->V,j,&vj);CHKERRQ(ierr); ierr = BVGetColumn(svd->U,j,&uj);CHKERRQ(ierr); ierr = SVDMatMult(svd,PETSC_FALSE,vj,uj);CHKERRQ(ierr); ierr = BVRestoreColumn(svd->V,j,&vj);CHKERRQ(ierr); ierr = BVRestoreColumn(svd->U,j,&uj);CHKERRQ(ierr); ierr = BVOrthogonalizeColumn(svd->U,j,NULL,&norm,NULL);CHKERRQ(ierr); ierr = BVScaleColumn(svd->U,j,1.0/norm);CHKERRQ(ierr); } svd->lvecsavail = PETSC_TRUE; } ierr = BVCopyVec(svd->U,svd->perm[i],u);CHKERRQ(ierr); } if (v) { ierr = BVCopyVec(svd->V,svd->perm[i],v);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* EPSGetStartVector - Generate a suitable vector to be used as the starting vector for the recurrence that builds the right subspace. Collective on EPS and Vec Input Parameters: + eps - the eigensolver context - i - iteration number Output Parameters: . breakdown - flag indicating that a breakdown has occurred Notes: The start vector is computed from another vector: for the first step (i=0), the first initial vector is used (see EPSSetInitialSpace()); otherwise a random vector is created. Then this vector is forced to be in the range of OP (only for generalized definite problems) and orthonormalized with respect to all V-vectors up to i-1. The resulting vector is placed in V[i]. The flag breakdown is set to true if either i=0 and the vector belongs to the deflation space, or i>0 and the vector is linearly dependent with respect to the V-vectors. */ PetscErrorCode EPSGetStartVector(EPS eps,PetscInt i,PetscBool *breakdown) { PetscErrorCode ierr; PetscReal norm; PetscBool lindep; Vec w,z; PetscFunctionBegin; PetscValidHeaderSpecific(eps,EPS_CLASSID,1); PetscValidLogicalCollectiveInt(eps,i,2); /* For the first step, use the first initial vector, otherwise a random one */ if (i>0 || eps->nini==0) { ierr = BVSetRandomColumn(eps->V,i,eps->rand);CHKERRQ(ierr); } ierr = BVGetVec(eps->V,&w);CHKERRQ(ierr); ierr = BVCopyVec(eps->V,i,w);CHKERRQ(ierr); /* Force the vector to be in the range of OP for definite generalized problems */ ierr = BVGetColumn(eps->V,i,&z);CHKERRQ(ierr); if (eps->ispositive || (eps->isgeneralized && eps->ishermitian)) { ierr = STApply(eps->st,w,z);CHKERRQ(ierr); } else { ierr = VecCopy(w,z);CHKERRQ(ierr); } ierr = BVRestoreColumn(eps->V,i,&z);CHKERRQ(ierr); ierr = VecDestroy(&w);CHKERRQ(ierr); /* Orthonormalize the vector with respect to previous vectors */ ierr = BVOrthogonalizeColumn(eps->V,i,NULL,&norm,&lindep);CHKERRQ(ierr); if (breakdown) *breakdown = lindep; else if (lindep || norm == 0.0) { if (i==0) SETERRQ(PetscObjectComm((PetscObject)eps),1,"Initial vector is zero or belongs to the deflation space"); else SETERRQ(PetscObjectComm((PetscObject)eps),1,"Unable to generate more start vectors"); } ierr = BVScaleColumn(eps->V,i,1.0/norm);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); }
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; BV X; Mat M; Vec v,t,*C; PetscInt i,j,n=20,k=8,nc=2; PetscViewer view; PetscBool verbose; PetscReal norm; PetscScalar alpha; SlepcInitialize(&argc,&argv,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-k",&k,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-nc",&nc,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-verbose",&verbose);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Test BV orthogonalization with %D columns + %D constraints, of length %D.\n",k,nc,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,k);CHKERRQ(ierr); ierr = BVSetFromOptions(X);CHKERRQ(ierr); /* Generate constraints and attach them to X */ if (nc>0) { ierr = VecDuplicateVecs(t,nc,&C);CHKERRQ(ierr); for (j=0;j<nc;j++) { for (i=0;i<=j;i++) { ierr = VecSetValue(C[j],i,1.0,INSERT_VALUES);CHKERRQ(ierr); } ierr = VecAssemblyBegin(C[j]);CHKERRQ(ierr); ierr = VecAssemblyEnd(C[j]);CHKERRQ(ierr); } ierr = BVInsertConstraints(X,&nc,C);CHKERRQ(ierr); ierr = VecDestroyVecs(nc,&C);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<k;j++) { ierr = BVGetColumn(X,j,&v);CHKERRQ(ierr); ierr = VecZeroEntries(v);CHKERRQ(ierr); for (i=0;i<=n/2;i++) { if (i+j<n) { alpha = (3.0*i+j-2)/(2*(i+j+1)); ierr = VecSetValue(v,i+j,alpha,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); } /* Test BVOrthogonalizeColumn */ for (j=0;j<k;j++) { ierr = BVOrthogonalizeColumn(X,j,NULL,&norm,NULL);CHKERRQ(ierr); alpha = 1.0/norm; ierr = BVScaleColumn(X,j,alpha);CHKERRQ(ierr); } if (verbose) { ierr = BVView(X,view);CHKERRQ(ierr); } /* Check orthogonality */ ierr = MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&M);CHKERRQ(ierr); ierr = BVDot(X,X,M);CHKERRQ(ierr); ierr = MatShift(M,-1.0);CHKERRQ(ierr); ierr = MatNorm(M,NORM_1,&norm);CHKERRQ(ierr); if (norm<100*PETSC_MACHINE_EPSILON) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Level of orthogonality < 100*eps\n");CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"Level of orthogonality: %g\n",(double)norm);CHKERRQ(ierr); } ierr = MatDestroy(&M);CHKERRQ(ierr); ierr = BVDestroy(&X);CHKERRQ(ierr); ierr = VecDestroy(&t);CHKERRQ(ierr); ierr = SlepcFinalize(); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; Vec t,v; Mat B,M; BV X; PetscInt i,j,n=10,k=5,Istart,Iend,col[3]; PetscScalar value[3],alpha; PetscReal nrm; PetscViewer view; PetscBool verbose,FirstBlock=PETSC_FALSE,LastBlock=PETSC_FALSE; SlepcInitialize(&argc,&argv,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-k",&k,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-verbose",&verbose);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Test BV with non-standard inner product (n=%D, k=%D).\n",n,k);CHKERRQ(ierr); /* Create inner product matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&B);CHKERRQ(ierr); ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr); ierr = MatSetFromOptions(B);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)B,"B");CHKERRQ(ierr); ierr = MatGetOwnershipRange(B,&Istart,&Iend);CHKERRQ(ierr); if (Istart==0) FirstBlock=PETSC_TRUE; if (Iend==n) LastBlock=PETSC_TRUE; value[0]=-1.0; value[1]=2.0; value[2]=-1.0; for (i=(FirstBlock? Istart+1: Istart); i<(LastBlock? Iend-1: Iend); i++) { col[0]=i-1; col[1]=i; col[2]=i+1; ierr = MatSetValues(B,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); } if (LastBlock) { i=n-1; col[0]=n-2; col[1]=n-1; ierr = MatSetValues(B,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); } if (FirstBlock) { i=0; col[0]=0; col[1]=1; value[0]=2.0; value[1]=-1.0; ierr = MatSetValues(B,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatGetVecs(B,&t,NULL);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,k);CHKERRQ(ierr); ierr = BVSetFromOptions(X);CHKERRQ(ierr); ierr = BVSetMatrix(X,B,PETSC_FALSE);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<k;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 = MatView(B,view);CHKERRQ(ierr); ierr = BVView(X,view);CHKERRQ(ierr); } /* Test BVNormColumn */ ierr = BVNormColumn(X,0,NORM_2,&nrm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"B-Norm or X[0] = %g\n",(double)nrm);CHKERRQ(ierr); /* Test BVOrthogonalizeColumn */ for (j=0;j<k;j++) { ierr = BVOrthogonalizeColumn(X,j,NULL,&nrm,NULL);CHKERRQ(ierr); alpha = 1.0/nrm; ierr = BVScaleColumn(X,j,alpha);CHKERRQ(ierr); } if (verbose) { ierr = BVView(X,view);CHKERRQ(ierr); } /* Check orthogonality */ ierr = MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&M);CHKERRQ(ierr); ierr = BVDot(X,X,M);CHKERRQ(ierr); ierr = MatShift(M,-1.0);CHKERRQ(ierr); ierr = MatNorm(M,NORM_1,&nrm);CHKERRQ(ierr); if (nrm<100*PETSC_MACHINE_EPSILON) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Level of orthogonality < 100*eps\n");CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"Level of orthogonality: %g\n",(double)nrm);CHKERRQ(ierr); } ierr = BVDestroy(&X);CHKERRQ(ierr); ierr = MatDestroy(&M);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); ierr = VecDestroy(&t);CHKERRQ(ierr); ierr = SlepcFinalize(); return 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); }