/*@ EPSGetEigenpair - Gets the i-th solution of the eigenproblem as computed by EPSSolve(). The solution consists in both the eigenvalue and the eigenvector. Logically Collective on EPS Input Parameters: + eps - eigensolver context - i - index of the solution Output Parameters: + eigr - real part of eigenvalue . eigi - imaginary part of eigenvalue . Vr - real part of eigenvector - Vi - imaginary part of eigenvector Notes: If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is configured with complex scalars the eigenvalue is stored directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is set to zero). The index i should be a value between 0 and nconv-1 (see EPSGetConverged()). Eigenpairs are indexed according to the ordering criterion established with EPSSetWhichEigenpairs(). The 2-norm of the eigenvector is one unless the problem is generalized Hermitian. In this case the eigenvector is normalized with respect to the norm defined by the B matrix. Level: beginner .seealso: EPSGetEigenvalue(), EPSGetEigenvector(), EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(), EPSGetInvariantSubspace() @*/ PetscErrorCode EPSGetEigenpair(EPS eps,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(eps,EPS_CLASSID,1); PetscValidLogicalCollectiveInt(eps,i,2); EPSCheckSolved(eps,1); if (i<0 || i>=eps->nconv) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range"); ierr = EPSGetEigenvalue(eps,i,eigr,eigi);CHKERRQ(ierr); if (Vr || Vi) { ierr = EPSGetEigenvector(eps,i,Vr,Vi);CHKERRQ(ierr); } PetscFunctionReturn(0); }
std::pair<Real, Real> SlepcEigenSolver<T>::get_eigenvalue(unsigned int i) { int ierr=0; PetscReal re, im; // real and imaginary part of the ith eigenvalue. PetscScalar kr, ki; ierr = EPSGetEigenvalue(_eps, i, &kr, &ki); LIBMESH_CHKERRABORT(ierr); #ifdef LIBMESH_USE_COMPLEX_NUMBERS re = PetscRealPart(kr); im = PetscImaginaryPart(kr); #else re = kr; im = ki; #endif return std::make_pair(re, im); }
PETSC_EXTERN void PETSC_STDCALL epsgeteigenvalue_(EPS *eps,PetscInt *i,PetscScalar *eigr,PetscScalar *eigi, int *__ierr ){ *__ierr = EPSGetEigenvalue(*eps,*i,eigr,eigi); }
/* Compute cyclicly eigenvalue */ PetscErrorCode Arnoldi(com_lsa * com, Mat * A, Vec *v){ EPS eps; /* eigensolver context */ char load_path[PETSC_MAX_PATH_LEN],export_path[PETSC_MAX_PATH_LEN]; PetscInt end,first,validated; PetscErrorCode ierr; /* eigenvalues number is set to 100, can be changed if needed we choosed to fix it because mallocs weren't working properly */ PetscScalar eigenvalues[1000], ei, er; PetscReal re,im,vnorm; PetscInt eigen_nb,j,i,size,one=1, taille; Vec initialv,nullv,*vs; PetscBool flag,data_load,data_export,continuous_export,load_any; int exit_type=0, counter = 0, l; int sos_type = 911; Vec vecteur_initial; PetscViewer viewer; PetscBool need_new_init = PETSC_FALSE, exit = PETSC_FALSE; sprintf(load_path,"./arnoldi.bin"); sprintf(export_path,"./arnoldi.bin"); PetscViewerCreate(PETSC_COMM_WORLD,&viewer); // PetscViewerSetType(viewer,PETSCVIEWERBINARY); // if (skippheader) { PetscViewerBinarySetSkipHeader(viewer,PETSC_TRUE); } // PetscViewerFileSetMode(viewer,FILE_MODE_WRITE); // PetscViewerBinarySetUseMPIIO(viewer,PETSC_TRUE); // PetscViewerFileSetName(viewer,"arnoldidbg.txt"); /* create the eigensolver */ ierr=EPSCreate(PETSC_COMM_WORLD,&eps);CHKERRQ(ierr); /* set the matrix operator */ ierr=EPSSetOperators(eps,*A,PETSC_NULL); /* set options */ ierr=EPSSetType(eps,EPSARNOLDI); ierr=EPSSetFromOptions(eps);CHKERRQ(ierr); /* duplicate vector properties */ ierr=VecDuplicate(*v,&initialv);CHKERRQ(ierr); ierr=VecDuplicate(*v,&nullv);CHKERRQ(ierr); ierr=VecSet(nullv,(PetscScalar)0.0);CHKERRQ(ierr); /* ierr=VecSet(initialv,(PetscScalar)1.0);CHKERRQ(ierr);*/ ierr=VecSetRandom(initialv,PETSC_NULL);//initialize initial vector to random ierr=VecGetSize(initialv,&size);CHKERRQ(ierr); ierr=PetscOptionsGetInt(PETSC_NULL,"-ksp_ls_eigen",&eigen_nb,&flag);CHKERRQ(ierr); if(!flag) eigen_nb=EIGEN_ALL; ierr=PetscOptionsGetString(PETSC_NULL,"-ksp_arnoldi_load",load_path,PETSC_MAX_PATH_LEN,&data_load);CHKERRQ(ierr); ierr=PetscOptionsGetString(PETSC_NULL,"-ksp_arnoldi_export",export_path,PETSC_MAX_PATH_LEN,&data_export);CHKERRQ(ierr); ierr=PetscOptionsHasName(PETSC_NULL,"-ksp_arnoldi_load_any",&load_any);CHKERRQ(ierr); ierr=PetscOptionsHasName(PETSC_NULL,"-ksp_arnoldi_cexport",&continuous_export);CHKERRQ(ierr); if(load_any) PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi loading default data file\n"); PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi path in= %s out= %s\n",load_path,export_path); PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi allocating buffer of %d for invariant subspace\n",eigen_nb*2); vs=malloc(size*sizeof(Vec)); for(i=0;i<size;i++){ ierr=VecDuplicate(*v,&vs[i]);CHKERRQ(ierr); } ierr=VecDuplicate(initialv,&vecteur_initial);CHKERRQ(ierr); /* vecteur_initial = malloc(size * sizeof(PetscScalar));*/ // setting_out_vec_sizes( com, v); end=0; first=1; validated=1; while(!end){ /*check if the program need to exit */ if(exit == PETSC_TRUE) break; /* check if we received an exit message from Father*/ if(!mpi_lsa_com_type_recv(com,&exit_type)){ if(exit_type==666){ end=1; PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Sending Exit message\n"); mpi_lsa_com_type_send(com,&exit_type); break; } } /* check if we received some data from GMRES */ if(!mpi_lsa_com_vec_recv(com, &initialv)){ VecGetSize(initialv, &taille); /* printf(" ========= %d I RECEIVED %d DATA FROM GMRES ============\n",com->rank_world, taille);*/ /* ierr = VecCopy(vecteur_initial, initialv);*/ } /* */ /* if(!mpi_lsa_com_array_recv(com, &taille, vecteur_initial)){*/ /* // VecGetSize(initialv, &taille);*/ /* printf(" ========= %d I RECEIVED %d DATA FROM GMRES ============\n",com->rank_world, taille);*/ /* for (i = 0; i < taille; i++)*/ /* PetscPrintf(PETSC_COMM_WORLD,"==== > arnoldi %d [%d] = %e\n",com->rank_world, i, vecteur_initial[i]);*/ /* } */ for(j=0;j<eigen_nb;j++){ eigenvalues[j]=(PetscScalar)0.0; } //FIXME: refactoriser les if suivants + flags file read, c'est très très moche if(data_load&&load_any){ load_any=PETSC_FALSE; data_load=PETSC_TRUE; } ierr = VecAssemblyBegin(initialv);CHKERRQ(ierr); ierr = VecAssemblyEnd(initialv);CHKERRQ(ierr); if(!(data_load^=load_any)){ ierr=EPSSetInitialSpace(eps,1,&initialv);CHKERRQ(ierr); } else { /* PetscPrintf(PETSC_COMM_WORLD,"==== > I AM LOADING DATA FROM FILE\n");*/ /* PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Reading file %s\n",load_path);*/ ierr=readBinaryVecArray(load_path,(int*)one,&initialv);CHKERRQ(ierr); data_load=PETSC_FALSE; load_any=PETSC_FALSE; ierr=EPSSetInitialSpace(eps,1,&initialv);CHKERRQ(ierr); /* PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Has Read file %s\n",load_path);*/ } ierr=EPSSolve(eps);CHKERRQ(ierr); /*construct new initial vector*/ ierr=EPSGetInvariantSubspace(eps, vs);CHKERRQ(ierr); ++counter; /* get the number of guessed eigenvalues */ ierr=EPSGetConverged(eps,&eigen_nb);CHKERRQ(ierr); /* #ifdef DEBUG*/ /* PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi %d converged eigenvalues\n",eigen_nb);*/ /* #endif*/ /* send them */ for(j=0;j<eigen_nb;j++){ //EPSGetValue(eps,j,&er,&ei); //ierr = EPSGetEigenpair(eps,j,&er,&ei,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); ierr = EPSGetEigenvalue(eps,j,&er,&ei);CHKERRQ(ierr); #ifdef PETSC_USE_COMPLEX re=PetscRealPart(er); im=PetscImaginaryPart(er); #else re=er; im=ei; #endif eigenvalues[j]=(PetscScalar)re+PETSC_i*(PetscScalar)im; // #ifdef DEBUG if(im!=0.0) PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi %d/%d val : %e %e\n",j,eigen_nb,re,im); else PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi %d/%d val : %e\n",j,eigen_nb,er); // #endif } /* ierr=VecGetSize(initialv,&taille);CHKERRQ(ierr);*/ /* PetscPrintf(PETSC_COMM_WORLD,"==== > OUR INITIALV IS OF SIZE %d\n", taille);*/ /* vecteur_initial = realloc(vecteur_initial,taille); */ /* ierr=VecGetArray(initialv, &vecteur_initial);CHKERRQ(ierr);*/ /* for (i = 0; i < taille; i++)*/ /* PetscPrintf(PETSC_COMM_WORLD,"==== > initialv[%d] = %e\n", i, vecteur_initial[i]);*/ /* ierr= VecRestoreArray(initialv, &vecteur_initial);CHKERRQ(ierr);*/ if( eigen_nb != 0){ /* #ifdef DEBUG*/ /* PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Sending to LS\n");*/ /* #endif*/ /* send the data array */ mpi_lsa_com_array_send(com, &eigen_nb, eigenvalues); /*construct new initial vector*/ /* ierr=EPSGetInvariantSubspace(eps, vs);CHKERRQ(ierr);*/ ierr=VecCopy(vs[0],initialv);CHKERRQ(ierr); for(j=1;j<eigen_nb;j++){ ierr=VecAYPX(initialv,(PetscScalar)1.0,vs[j]); } ierr=VecNorm(initialv,NORM_2,&vnorm);CHKERRQ(ierr); ierr=VecAYPX(initialv,(PetscScalar)(1.0/vnorm),nullv);CHKERRQ(ierr); if(continuous_export){ /* ierr=writeBinaryVecArray(data_export?export_path:"./arnoldi.bin", 1, &initialv);*/ } if(!mpi_lsa_com_type_recv(com,&exit_type)){ if(exit_type==666){ end=1; PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Sending Exit message\n"); mpi_lsa_com_type_send(com,&exit_type); need_new_init = PETSC_FALSE; exit = PETSC_TRUE; break; } } }else{ need_new_init = PETSC_TRUE; PetscPrintf(PETSC_COMM_WORLD, "!!! Arnoldi has not converged so we change the initial vector !!!\n"); while(need_new_init){ // this was my first try to solve the poblem but it doesn't work better /*ierr=VecSetRandom(initialv,PETSC_NULL);CHKERRQ(ier);*/ // Now the best to do i think is to develop a kind of help from GMRES // Arnoldi when no convergence observed will send a msg to GMRES like an SOS //and GMRES will send a vector wich will be used to generate a new initial vector that make arnoldi converge **I HOPE ** //need_new_init = PETSC_TRUE // mpi_lsa_com_type_send(com,&sos_type); // here we send the message // ierr=VecDuplicate(initialv,&vec_tmp_receive); //PetscPrintf(PETSC_COMM_WORLD, "!!! Arnoldi has not converged so we change the initial vector !!!\n"); /* check if there's an incoming message */ if(!mpi_lsa_com_vec_recv(com, &initialv)){ /* if(!mpi_lsa_com_array_recv(com, &taille, vecteur_initial)){*/ /* printf(" ========= I RECEIVED SOME DATA FROM GMRES ============\n");*/ /* ierr = VecCopy(vecteur_initial, initialv);*/ need_new_init = PETSC_FALSE; }else{ if(!mpi_lsa_com_type_recv(com,&exit_type)){ if(exit_type==666){ end=1; /* PetscPrintf(PETSC_COMM_WORLD,"*} Arnoldi Sending Exit message\n");*/ mpi_lsa_com_type_send(com,&exit_type); need_new_init = PETSC_FALSE; exit = PETSC_TRUE; break; } } } //goto checking; //return 1; } if(exit == PETSC_TRUE) break; } // i will check it later } /* if(data_export){*/ /* ierr=writeBinaryVecArray(export_path, 1, &initialv);*/ /* }*/ for(i=0;i<eigen_nb;i++){ ierr=VecDestroy(&(vs[i]));CHKERRQ(ierr); } /* ierr=PetscFree(vs);CHKERRQ(ierr);*/ /* and destroy the eps */ ierr=EPSDestroy(&eps);CHKERRQ(ierr); ierr=VecDestroy(&initialv);CHKERRQ(ierr); ierr=VecDestroy(&nullv);CHKERRQ(ierr); return 0; }