16 #ifndef dealii__parpack_solver_h 17 #define dealii__parpack_solver_h 19 #include <deal.II/base/config.h> 20 #include <deal.II/base/smartpointer.h> 21 #include <deal.II/base/memory_consumption.h> 22 #include <deal.II/lac/solver_control.h> 23 #include <deal.II/lac/vector.h> 24 #include <deal.II/base/index_set.h> 29 #ifdef DEAL_II_ARPACK_WITH_PARPACK 31 DEAL_II_NAMESPACE_OPEN
36 void pdnaupd_(MPI_Fint *comm,
int *ido,
char *bmat,
int *n,
char *which,
37 int *nev,
double *tol,
double *resid,
int *ncv,
38 double *v,
int *nloc,
int *iparam,
int *ipntr,
39 double *workd,
double *workl,
int *lworkl,
43 void pdsaupd_(MPI_Fint *comm,
int *ido,
char *bmat,
int *n,
char *which,
44 int *nev,
double *tol,
double *resid,
int *ncv,
45 double *v,
int *nloc,
int *iparam,
int *ipntr,
46 double *workd,
double *workl,
int *lworkl,
50 void pdneupd_(MPI_Fint *comm,
int *rvec,
char *howmany,
int *select,
double *d,
51 double *di,
double *z,
int *ldz,
double *sigmar,
52 double *sigmai,
double *workev,
char *bmat,
int *n,
char *which,
53 int *nev,
double *tol,
double *resid,
int *ncv,
54 double *v,
int *nloc,
int *iparam,
int *ipntr,
55 double *workd,
double *workl,
int *lworkl,
int *info);
58 void pdseupd_(MPI_Fint *comm,
int *rvec,
char *howmany,
int *select,
double *d,
59 double *z,
int *ldz,
double *sigmar,
60 char *bmat,
int *n,
char *which,
61 int *nev,
double *tol,
double *resid,
int *ncv,
62 double *v,
int *nloc,
int *iparam,
int *ipntr,
63 double *workd,
double *workl,
int *lworkl,
int *info);
129 template <
typename VectorType>
145 enum WhichEigenvalues
147 algebraically_largest,
148 algebraically_smallest,
153 largest_imaginary_part,
154 smallest_imaginary_part,
161 template <
typename MatrixType>
169 Shift (
const MatrixType &A,
181 void vmult (VectorType &dst,
const VectorType &src)
const 185 A.vmult_add(dst,src);
191 void Tvmult (VectorType &dst,
const VectorType &src)
const 195 A.Tvmult_add(dst,src);
208 struct AdditionalData
210 const unsigned int number_of_arnoldi_vectors;
211 const WhichEigenvalues eigenvalue_of_interest;
212 const bool symmetric;
214 const unsigned int number_of_arnoldi_vectors = 15,
215 const WhichEigenvalues eigenvalue_of_interest = largest_magnitude,
216 const bool symmetric =
false);
228 const MPI_Comm &mpi_communicator,
229 const AdditionalData &data = AdditionalData());
234 void reinit(const ::IndexSet &locally_owned_dofs );
239 void set_shift(
const double s );
246 template <
typename MatrixType1,
247 typename MatrixType2,
typename INVERSE>
249 (
const MatrixType1 &A,
250 const MatrixType2 &B,
251 const INVERSE &inverse,
252 std::vector<std::complex<double> > &eigenvalues,
253 std::vector<VectorType> &eigenvectors,
254 const unsigned int n_eigenvalues);
269 const AdditionalData additional_data;
276 MPI_Comm mpi_communicator;
281 MPI_Fint mpi_communicator_fortran;
293 std::vector<double> workl;
298 std::vector<double> workd;
320 std::vector<double> v;
326 std::vector<double> resid;
338 std::vector<double> z;
348 std::vector<double> workev;
353 std::vector<int> select;
358 VectorType src,dst,tmp;
363 std::vector< types::global_dof_index > local_indices;
376 << arg1 <<
"eigenpairs were requested, but only" 377 << arg2 <<
" converged");
380 <<
"Number of wanted eigenvalues " << arg1
381 <<
" is larger that the size of the matrix " << arg2);
384 <<
"Number of wanted eigenvalues " << arg1
385 <<
" is larger that the size of eigenvectors " << arg2);
388 <<
"Number of wanted eigenvalues " << arg1
389 <<
" is larger that the size of eigenvalues " << arg2);
391 DeclException2 (PArpackExcInvalidNumberofArnoldiVectors,
int,
int,
392 <<
"Number of Arnoldi vectors " << arg1
393 <<
" is larger that the size of the matrix " << arg2);
396 <<
"Number of Arnoldi vectors " << arg1
397 <<
" is too small to obtain " << arg2
401 <<
" is not supported. Check documentation of ARPACK");
404 <<
" is not supported. Check documentation of ARPACK");
407 <<
"Error with Pdnaupd, info " << arg1
408 <<
". Check documentation of ARPACK");
411 <<
"Error with Pdneupd, info " << arg1
412 <<
". Check documentation of ARPACK");
415 <<
"Maximum number " << arg1
416 <<
" of iterations reached.");
419 <<
"No shifts could be applied during implicit" 420 <<
" Arnoldi update, try increasing the number of" 421 <<
" Arnoldi vectors.");
424 template <
typename VectorType>
426 PArpackSolver<VectorType>::memory_consumption()
const 435 src.memory_consumption() +
436 dst.memory_consumption() +
437 tmp.memory_consumption() +
441 template <
typename VectorType>
442 PArpackSolver<VectorType>::AdditionalData::
443 AdditionalData (
const unsigned int number_of_arnoldi_vectors,
444 const WhichEigenvalues eigenvalue_of_interest,
445 const bool symmetric)
447 number_of_arnoldi_vectors(number_of_arnoldi_vectors),
448 eigenvalue_of_interest(eigenvalue_of_interest),
452 template <
typename VectorType>
453 PArpackSolver<VectorType>::PArpackSolver (
SolverControl &control,
454 const MPI_Comm &mpi_communicator,
455 const AdditionalData &data)
457 solver_control (control),
458 additional_data (data),
459 mpi_communicator( mpi_communicator ),
460 mpi_communicator_fortran ( MPI_Comm_c2f( mpi_communicator ) ),
465 template <
typename VectorType>
466 void PArpackSolver<VectorType>::set_shift(
const double s )
471 template <
typename VectorType>
472 void PArpackSolver<VectorType>::reinit(const ::IndexSet &locally_owned_dofs)
475 locally_owned_dofs.fill_index_vector(local_indices);
478 nloc = locally_owned_dofs.n_elements ();
479 ncv = additional_data.number_of_arnoldi_vectors;
481 Assert (local_indices.size() == nloc, ExcInternalError() );
485 v.resize (ldv*ncv, 0.0);
488 resid.resize(nloc, 1.0);
491 workd.resize(3*nloc,0.0);
493 lworkl = additional_data.symmetric ?
497 workl.resize (lworkl, 0.);
500 z.resize (ldz*ncv, 0.);
503 lworkev = additional_data.symmetric ?
507 workev.resize (lworkev, 0.);
509 select.resize (ncv, 0);
512 src.reinit (locally_owned_dofs,mpi_communicator);
513 dst.reinit (locally_owned_dofs,mpi_communicator);
514 tmp.reinit (locally_owned_dofs,mpi_communicator);
518 template <
typename VectorType>
519 template <
typename MatrixType1,
typename MatrixType2,
typename INVERSE>
520 void PArpackSolver<VectorType>::solve
521 (
const MatrixType1 &,
522 const MatrixType2 &mass_matrix,
523 const INVERSE &inverse,
524 std::vector<std::complex<double> > &eigenvalues,
525 std::vector<VectorType> &eigenvectors,
526 const unsigned int n_eigenvalues)
529 Assert (n_eigenvalues <= eigenvectors.size(),
530 PArpackExcInvalidEigenvectorSize(n_eigenvalues, eigenvectors.size()));
532 Assert (n_eigenvalues <= eigenvalues.size(),
533 PArpackExcInvalidEigenvalueSize(n_eigenvalues, eigenvalues.size()));
536 Assert (n_eigenvalues < mass_matrix.m(),
537 PArpackExcInvalidNumberofEigenvalues(n_eigenvalues, mass_matrix.m()));
539 Assert (additional_data.number_of_arnoldi_vectors < mass_matrix.m(),
540 PArpackExcInvalidNumberofArnoldiVectors(
541 additional_data.number_of_arnoldi_vectors, mass_matrix.m()));
543 Assert (additional_data.number_of_arnoldi_vectors > 2*n_eigenvalues+1,
544 PArpackExcSmallNumberofArnoldiVectors(
545 additional_data.number_of_arnoldi_vectors, n_eigenvalues));
572 switch (additional_data.eigenvalue_of_interest)
574 case algebraically_largest:
575 std::strcpy (which,
"LA");
577 case algebraically_smallest:
578 std::strcpy (which,
"SA");
580 case largest_magnitude:
581 std::strcpy (which,
"LM");
583 case smallest_magnitude:
584 std::strcpy (which,
"SM");
586 case largest_real_part:
587 std::strcpy (which,
"LR");
589 case smallest_real_part:
590 std::strcpy (which,
"SR");
592 case largest_imaginary_part:
593 std::strcpy (which,
"LI");
595 case smallest_imaginary_part:
596 std::strcpy (which,
"SI");
599 std::strcpy (which,
"BE");
604 double tol = control().tolerance();
607 std::vector<int> iparam (11, 0);
613 iparam[2] = control().max_steps();
626 std::vector<int> ipntr (14, 0);
637 int nev = n_eigenvalues;
638 int n_inside_arpack = nloc;
643 if (additional_data.symmetric)
644 pdsaupd_(&mpi_communicator_fortran,&ido, bmat, &n_inside_arpack, which, &nev, &tol,
645 &resid[0], &ncv, &v[0], &ldv, &iparam[0], &ipntr[0],
646 &workd[0], &workl[0], &lworkl, &info);
648 pdnaupd_(&mpi_communicator_fortran,&ido, bmat, &n_inside_arpack, which, &nev, &tol,
649 &resid[0], &ncv, &v[0], &ldv, &iparam[0], &ipntr[0],
650 &workd[0], &workl[0], &lworkl, &info);
667 const int shift_x = ipntr[0]-1;
668 const int shift_y = ipntr[1]-1;
669 Assert (shift_x>=0, ::ExcInternalError() );
670 Assert (shift_x+nloc <= workd.size(), ::ExcInternalError() );
671 Assert (shift_y>=0, ::ExcInternalError() );
672 Assert (shift_y+nloc <= workd.size(), ::ExcInternalError() );
678 src.compress (VectorOperation::add);
681 mass_matrix.vmult(tmp, src);
683 inverse.vmult(dst,tmp);
686 dst.extract_subvector_to (local_indices.begin(),
700 const int shift_x = ipntr[0]-1;
701 const int shift_y = ipntr[1]-1;
702 const int shift_b_x = ipntr[2]-1;
704 Assert (shift_x>=0, ::ExcInternalError() );
705 Assert (shift_x+nloc <= workd.size(), ::ExcInternalError() );
706 Assert (shift_y>=0, ::ExcInternalError() );
707 Assert (shift_y+nloc <= workd.size(), ::ExcInternalError() );
708 Assert (shift_b_x>=0, ::ExcInternalError() );
709 Assert (shift_b_x+nloc <= workd.size(), ::ExcInternalError() );
710 Assert (shift_y>=0, ::ExcInternalError() );
711 Assert (shift_y+nloc <= workd.size(), ::ExcInternalError() );
716 &workd[0]+shift_b_x );
723 src.compress (VectorOperation::add);
724 tmp.compress (VectorOperation::add);
727 inverse.vmult(dst,src);
730 dst.extract_subvector_to (local_indices.begin(),
743 const int shift_x = ipntr[0]-1;
744 const int shift_y = ipntr[1]-1;
745 Assert (shift_x>=0, ::ExcInternalError() );
746 Assert (shift_x+nloc <= workd.size(), ::ExcInternalError() );
747 Assert (shift_y>=0, ::ExcInternalError() );
748 Assert (shift_y+nloc <= workd.size(), ::ExcInternalError() );
754 src.compress (VectorOperation::add);
757 mass_matrix.vmult(dst, src);
760 dst.extract_subvector_to (local_indices.begin(),
768 Assert (
false, PArpackExcIdo(ido));
774 Assert (
false, PArpackExcMode(mode));
781 Assert (
false, PArpackExcInfoPdnaupd(info));
790 char howmany[4] =
"All";
792 double sigmar = shift_value;
795 std::vector<double> eigenvalues_real (n_eigenvalues, 0.);
796 std::vector<double> eigenvalues_im (n_eigenvalues, 0.);
799 if (additional_data.symmetric)
800 pdseupd_(&mpi_communicator_fortran, &rvec, howmany, &select[0], &eigenvalues_real[0],
801 &z[0], &ldz, &sigmar,
802 bmat, &n_inside_arpack, which, &nev, &tol,
803 &resid[0], &ncv, &v[0], &ldv,
804 &iparam[0], &ipntr[0], &workd[0], &workl[0], &lworkl, &info);
806 pdneupd_(&mpi_communicator_fortran, &rvec, howmany, &select[0], &eigenvalues_real[0],
807 &eigenvalues_im[0], &z[0], &ldz, &sigmar, &sigmai,
808 &workev[0], bmat, &n_inside_arpack, which, &nev, &tol,
809 &resid[0], &ncv, &v[0], &ldv,
810 &iparam[0], &ipntr[0], &workd[0], &workl[0], &lworkl, &info);
814 Assert (
false, PArpackExcInfoMaxIt(control().max_steps()));
818 Assert (
false, PArpackExcNoShifts(1));
822 Assert (
false, PArpackExcInfoPdneupd(info));
825 for (size_type i=0; i<n_eigenvalues; ++i)
827 eigenvectors[i] = 0.0;
828 Assert (i*nloc + nloc <= v.size(), ::ExcInternalError() );
830 eigenvectors[i].add (nloc,
833 eigenvectors[i].compress (VectorOperation::add);
836 for (size_type i=0; i<n_eigenvalues; ++i)
837 eigenvalues[i] = std::complex<double> (eigenvalues_real[i],
841 Assert (iparam[4] == n_eigenvalues,
842 PArpackExcConvergedEigenvectors(iparam[4], n_eigenvalues));
854 solver_control.check ( iparam[2], tmp.l2_norm() );
860 template <
typename VectorType>
863 return solver_control;
866 DEAL_II_NAMESPACE_CLOSE
types::global_dof_index size_type
#define DeclException2(Exception2, type1, type2, outsequence)
#define DeclException1(Exception1, type1, outsequence)
unsigned int global_dof_index
#define Assert(cond, exc)
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)