| EPS_LANCZOS *lanczos = (EPS_LANCZOS *)eps->data; |
| PetscErrorCode ierr; |
| Mat A; |
| int i,j,n,l,m = *M; |
| PetscReal norm,*omega,*omega_old,eps1,delta; |
| PetscScalar alpha,*a,*b; |
| PetscTruth reorth,force_reorth = PETSC_FALSE; |
| int i,j,n,l,nv,m = *M; |
| PetscReal norm,*omega,lomega[100],*omega_old,lomega_old[100],eps1,delta,eta; |
| PetscScalar alpha,*a,la[100],*b,lb[101]; |
| PetscTruth *which,lwhich[100],reorth,force_reorth = PETSC_FALSE,fro = PETSC_FALSE;; |
| Vec *VV,lVV[100]; |
| |
| PetscFunctionBegin; |
| l = m - k; |
| ierr = PetscMalloc((l+1)*sizeof(PetscScalar),&a);CHKERRQ(ierr); |
| ierr = PetscMalloc((l+1)*sizeof(PetscScalar),&b);CHKERRQ(ierr); |
| ierr = PetscMalloc(l*sizeof(PetscScalar),&omega);CHKERRQ(ierr); |
| ierr = PetscMalloc(l*sizeof(PetscScalar),&omega_old);CHKERRQ(ierr); |
| if (l>100) { |
| ierr = PetscMalloc(l*sizeof(PetscScalar),&a);CHKERRQ(ierr); |
| ierr = PetscMalloc((l+1)*sizeof(PetscScalar),&b);CHKERRQ(ierr); |
| ierr = PetscMalloc(l*sizeof(PetscScalar),&omega);CHKERRQ(ierr); |
| ierr = PetscMalloc(l*sizeof(PetscScalar),&omega_old);CHKERRQ(ierr); |
| ierr = PetscMalloc(l*sizeof(PetscTruth),&which);CHKERRQ(ierr); |
| } else { |
| a = la; |
| b = lb; |
| omega = lomega; |
| omega_old = lomega_old; |
| which = lwhich; |
| } |
| if (eps->nds+eps->ncv > 100) { |
| ierr = PetscMalloc((eps->nds+eps->ncv)*sizeof(Vec),&VV);CHKERRQ(ierr); |
| } else VV = lVV; |
| |
| ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr); |
| ierr = MatGetSize(A,&n,PETSC_NULL);CHKERRQ(ierr); |
| eps1 = sqrt((PetscReal)n)*PETSC_MACHINE_EPSILON/2; |
| delta = PETSC_SQRT_MACHINE_EPSILON/sqrt((PetscReal)eps->ncv); |
| eta = pow(PETSC_MACHINE_EPSILON,3.0/4.0)/sqrt((PetscReal)eps->ncv); |
| |
| for (j=k;j<m;j++) { |
| ierr = STApply(eps->OP,V[j],f);CHKERRQ(ierr); |
| eps->its++; |
| if (j>k) { |
| ierr = VecAXPY(f,-norm,V[j-1]);CHKERRQ(ierr); |
| } |
| ierr = VecDot(V[j],f,&alpha);CHKERRQ(ierr); |
| ierr = VecAXPY(f,-alpha,V[j]);CHKERRQ(ierr); |
| T[m*j+j] = a[j-k] = alpha; |
| |
| reorth = PETSC_FALSE; |
| if (j>k) { |
| ierr = STNorm(eps->OP,f,&b[j-k+1]);CHKERRQ(ierr); |
| update_omega(omega,omega_old,j-k,a,b,eps1,anorm); |
| for (i=0;i<j-k;i++) { |
| if (omega[i] > delta) reorth = PETSC_TRUE; |
| if (fro) { |
| /* Lanczos step with full reorthogonalization */ |
| ierr = EPSOrthogonalize(eps,eps->nds,eps->DS,f,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); |
| ierr = EPSOrthogonalize(eps,j+1,V,f,T+m*j,&norm,breakdown);CHKERRQ(ierr); |
| } else { |
| /* Lanczos step */ |
| if (j>k) { |
| ierr = VecAXPY(f,-norm,V[j-1]);CHKERRQ(ierr); |
| } |
| } |
| |
| if (reorth || force_reorth) { |
| if (force_reorth) force_reorth = PETSC_FALSE; |
| else force_reorth = PETSC_TRUE; |
| if (lanczos->reorthog == EPSLANCZOS_REORTHOG_PERIODIC) { |
| eps->OP->lineariterations++; |
| ierr = EPSOrthogonalize(eps,j+1,V,f,PETSC_NULL,&norm,breakdown);CHKERRQ(ierr); |
| ierr = VecDot(V[j],f,&alpha);CHKERRQ(ierr); |
| ierr = VecAXPY(f,-alpha,V[j]);CHKERRQ(ierr); |
| T[m*j+j] = a[j-k] = alpha; |
| |
| /* Check if reorthogonalization is needed */ |
| reorth = PETSC_FALSE; |
| if (j>k) { |
| ierr = STNorm(eps->OP,f,&b[j-k+1]);CHKERRQ(ierr); |
| update_omega(omega,omega_old,j-k,a,b,eps1,anorm); |
| for (i=0;i<j-k;i++) |
| omega[i] = eps1; |
| if (PetscAbsScalar(omega[i]) > delta) reorth = PETSC_TRUE; |
| } |
| |
| if (reorth || force_reorth) { |
| eps->OP->lineariterations++; |
| if (force_reorth) force_reorth = PETSC_FALSE; |
| else force_reorth = PETSC_TRUE; |
| if (lanczos->reorthog == EPSLANCZOS_REORTHOG_PERIODIC) { |
| /* Periodic reorthogonalization */ |
| ierr = EPSOrthogonalize(eps,eps->nds,eps->DS,f,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); |
| ierr = EPSOrthogonalize(eps,j+1,V,f,PETSC_NULL,&norm,breakdown);CHKERRQ(ierr); |
| for (i=0;i<j-k;i++) |
| omega[i] = eps1; |
| } else { |
| /* Partial reorthogonalization */ |
| compute_int(which,omega,j-k,delta,eta); |
| nv = 0; |
| for (i=0;i<j-k;i++) |
| if (which[i]) { |
| omega[i] = eps1; |
| VV[nv] = eps->V[i+k]; |
| nv++; |
| } |
| for (i=0;i<k;i++) { |
| VV[nv] = eps->V[i]; |
| nv++; |
| } |
| ierr = EPSOrthogonalize(eps,eps->nds,eps->DS,f,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); |
| ierr = EPSOrthogonalize(eps,nv,VV,f,PETSC_NULL,&norm,breakdown);CHKERRQ(ierr); |
| } |
| } else { |
| SETERRQ(1,"Not implemented yet :)"); |
| /* Deflation with locked vectors */ |
| ierr = EPSOrthogonalize(eps,eps->nds,eps->DS,f,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); |
| ierr = EPSOrthogonalize(eps,k,V,f,PETSC_NULL,&norm,breakdown);CHKERRQ(ierr); |
| } |
| } else { |
| ierr = EPSOrthogonalize(eps,k,V,f,PETSC_NULL,&norm,breakdown);CHKERRQ(ierr); |
| } |
| |
| if (*breakdown) { |
| if (*breakdown || norm < n*anorm*PETSC_MACHINE_EPSILON) { |
| *M = j+1; |
| break; |
| } |
| if (!fro && norm*delta < anorm*eps1) { |
| fro = PETSC_TRUE; |
| PetscInfo1(eps,"Switching to full reorthogonalization at iteration %i\n",eps->its); |
| } |
| if (j<m-1) { |
| T[m*j+j+1] = b[j-k+1] = norm; |
| ierr = VecScale(f,1.0/norm);CHKERRQ(ierr); |