void TrustRegionSolver3::calcSmallestEigVal(double &oEigVal, FloatArray &oEigVec, PetscSparseMtrx &K) { PetscErrorCode ierr; ST st; double eig_rtol = 1.0e-3; int max_iter = 10000; int nroot = 1; if ( !epsInit ) { /* * Create eigensolver context */ #ifdef __PARALLEL_MODE MPI_Comm comm = engngModel->giveParallelComm(); #else MPI_Comm comm = PETSC_COMM_SELF; #endif ierr = EPSCreate(comm, & eps); checkPetscError(ierr); epsInit = true; } ierr = EPSSetOperators( eps, * K.giveMtrx(), NULL ); checkPetscError(ierr); ierr = EPSSetProblemType(eps, EPS_NHEP); checkPetscError(ierr); ierr = EPSGetST(eps, & st); checkPetscError(ierr); // ierr = STSetType(st, STCAYLEY); // ierr = STSetType(st, STSINVERT); ierr = STSetType(st, STSHIFT); checkPetscError(ierr); ierr = STSetMatStructure(st, SAME_NONZERO_PATTERN); checkPetscError(ierr); ierr = EPSSetTolerances(eps, ( PetscReal ) eig_rtol, max_iter); checkPetscError(ierr); ierr = EPSSetDimensions(eps, ( PetscInt ) nroot, PETSC_DECIDE, PETSC_DECIDE); checkPetscError(ierr); ierr = EPSSetWhichEigenpairs(eps, EPS_SMALLEST_REAL); checkPetscError(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Solve the eigensystem * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ EPSConvergedReason eig_reason; int eig_nconv, eig_nite; ierr = EPSSolve(eps); checkPetscError(ierr); ierr = EPSGetConvergedReason(eps, & eig_reason); checkPetscError(ierr); ierr = EPSGetIterationNumber(eps, & eig_nite); checkPetscError(ierr); // printf("SLEPcSolver::solve EPSConvergedReason: %d, number of iterations: %d\n", eig_reason, eig_nite); ierr = EPSGetConverged(eps, & eig_nconv); checkPetscError(ierr); double smallest_eig_val = 1.0e20; if ( eig_nconv > 0 ) { // printf("SLEPcSolver :: solveYourselfAt: Convergence reached for RTOL=%20.15f\n", eig_rtol); FloatArray eig_vals(nroot); PetscScalar kr; Vec Vr; K.createVecGlobal(& Vr); FloatArray Vr_loc; for ( int i = 0; i < eig_nconv && i < nroot; i++ ) { // PetscErrorCode EPSGetEigenpair(EPS eps,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi) ierr = EPSGetEigenpair(eps, i, & kr, PETSC_NULL, Vr, PETSC_NULL); checkPetscError(ierr); //Store the eigenvalue eig_vals(i) = kr; if(kr < smallest_eig_val) { smallest_eig_val = kr; K.scatterG2L(Vr, Vr_loc); oEigVec = Vr_loc; } } ierr = VecDestroy(& Vr); checkPetscError(ierr); } else { // OOFEM_ERROR("No converged eigenpairs.\n"); printf("Warning: No converged eigenpairs.\n"); smallest_eig_val = 1.0; } oEigVal = smallest_eig_val; }
NM_Status SLEPcSolver :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) { FILE *outStream; PetscErrorCode ierr; int size; ST st; outStream = domain->giveEngngModel()->giveOutputStream(); // first check whether Lhs is defined if ( a->giveNumberOfRows() != a->giveNumberOfColumns() || b->giveNumberOfRows() != b->giveNumberOfRows() || a->giveNumberOfColumns() != b->giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } A = dynamic_cast< PetscSparseMtrx * >(&a); B = dynamic_cast< PetscSparseMtrx * >(&b); if ( !A || !B ) { OOFEM_ERROR("PetscSparseMtrx Expected"); } size = engngModel->giveParallelContext( A->giveDomainIndex() )->giveNumberOfNaturalEqs(); // A->giveLeqs(); _r.resize(size, nroot); _eigv.resize(nroot); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Create the eigensolver and set various options * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ int nconv, nite; EPSConvergedReason reason; #ifdef TIME_REPORT Timer timer; timer.startTimer(); #endif if ( !epsInit ) { /* * Create eigensolver context */ #ifdef __PARALLEL_MODE MPI_Comm comm = engngModel->giveParallelComm(); #else MPI_Comm comm = PETSC_COMM_SELF; #endif ierr = EPSCreate(comm, & eps); CHKERRQ(ierr); epsInit = true; } /* * Set operators. In this case, it is a generalized eigenvalue problem */ ierr = EPSSetOperators( eps, * A->giveMtrx(), * B->giveMtrx() ); CHKERRQ(ierr); ierr = EPSSetProblemType(eps, EPS_GHEP); CHKERRQ(ierr); ierr = EPSGetST(eps, & st); CHKERRQ(ierr); ierr = STSetType(st, STSINVERT); CHKERRQ(ierr); ierr = STSetMatStructure(st, SAME_NONZERO_PATTERN); CHKERRQ(ierr); ierr = EPSSetTolerances(eps, ( PetscReal ) rtol, PETSC_DECIDE); CHKERRQ(ierr); ierr = EPSSetDimensions(eps, ( PetscInt ) nroot, PETSC_DECIDE, PETSC_DECIDE); CHKERRQ(ierr); ierr = EPSSetWhichEigenpairs(eps, EPS_SMALLEST_MAGNITUDE); CHKERRQ(ierr); /* * Set solver parameters at runtime */ ierr = EPSSetFromOptions(eps); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Solve the eigensystem * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = EPSSolve(eps); CHKERRQ(ierr); ierr = EPSGetConvergedReason(eps, & reason); CHKERRQ(ierr); ierr = EPSGetIterationNumber(eps, & nite); CHKERRQ(ierr); OOFEM_LOG_INFO("SLEPcSolver::solve EPSConvergedReason: %d, number of iterations: %d\n", reason, nite); ierr = EPSGetConverged(eps, & nconv); CHKERRQ(ierr); if ( nconv > 0 ) { fprintf(outStream, "SLEPcSolver :: solveYourselfAt: Convergence reached for RTOL=%20.15f", rtol); PetscScalar kr; Vec Vr; ierr = MatGetVecs(* B->giveMtrx(), PETSC_NULL, & Vr); CHKERRQ(ierr); FloatArray Vr_loc; for ( int i = 0; i < nconv && i < nroot; i++ ) { ierr = EPSGetEigenpair(eps, nconv - i - 1, & kr, PETSC_NULL, Vr, PETSC_NULL); CHKERRQ(ierr); //Store the eigenvalue _eigv->at(i + 1) = kr; //Store the eigenvector A->scatterG2L(Vr, Vr_loc); for ( int j = 0; j < size; j++ ) { _r->at(j + 1, i + 1) = Vr_loc.at(j + 1); } } ierr = VecDestroy(Vr); CHKERRQ(ierr); } else { OOFEM_ERROR("No converged eigenpairs"); } #ifdef TIME_REPORT timer.stopTimer(); OOFEM_LOG_INFO( "SLEPcSolver info: user time consumed by solution: %.2fs\n", timer.getUtime() ); #endif return NM_Success; }