/* BVOrthogonalizeCGS1 - Compute |v'| (estimated), |v| and one step of CGS with only one global synchronization */ PetscErrorCode BVOrthogonalizeCGS1(BV bv,PetscInt j,Vec v,PetscScalar *H,PetscReal *onorm,PetscReal *norm) { PetscErrorCode ierr; PetscInt i; PetscReal sum,nrm,beta; Vec w=v; PetscFunctionBegin; /* h = W^* v ; alpha = (v, v) */ bv->k = j; if (onorm || norm) { if (!v) { bv->k++; ierr = BVGetColumn(bv,j,&w);CHKERRQ(ierr); } ierr = BVDotVec(bv,w,H);CHKERRQ(ierr); if (!v) { ierr = BVRestoreColumn(bv,j,&w);CHKERRQ(ierr); bv->k--; beta = PetscSqrtReal(PetscRealPart(H[bv->nc+j])); } else { ierr = BVNormVec(bv,w,NORM_2,&beta);CHKERRQ(ierr); } } else { if (!v) { ierr = BVDotColumn(bv,j,H);CHKERRQ(ierr); } else { ierr = BVDotVec(bv,w,H);CHKERRQ(ierr); } } /* q = v - V h */ if (bv->indef) { for (i=0;i<bv->nc+j;i++) H[i] /= bv->omega[i]; /* apply inverse of signature */ } if (!v) { ierr = BVMultColumn(bv,-1.0,1.0,j,H);CHKERRQ(ierr); } else { ierr = BVMultVec(bv,-1.0,1.0,w,H);CHKERRQ(ierr); } if (bv->indef) { for (i=0;i<bv->nc+j;i++) H[i] *= bv->omega[i]; /* revert signature */ } /* compute |v| */ if (onorm) *onorm = beta; if (bv->indef) { if (!v) { ierr = BVNormColumn(bv,j,NORM_2,&nrm);CHKERRQ(ierr); } else { ierr = BVNormVec(bv,w,NORM_2,&nrm);CHKERRQ(ierr); } if (norm) *norm = nrm; bv->omega[bv->nc+j] = (nrm<0.0)? -1.0: 1.0; } else if (norm) { /* estimate |v'| from |v| */ sum = 0.0; for (i=0;i<bv->nc+j;i++) sum += PetscRealPart(H[i]*PetscConj(H[i])); *norm = beta*beta-sum; if (*norm <= 0.0) { if (!v) { ierr = BVNormColumn(bv,j,NORM_2,norm);CHKERRQ(ierr); } else { ierr = BVNormVec(bv,w,NORM_2,norm);CHKERRQ(ierr); } } else *norm = PetscSqrtReal(*norm); } 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); }
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 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); }