deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
parpack_solver.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2015 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_parpack_solver_h
14#define dealii_parpack_solver_h
15
16#include <deal.II/base/config.h>
17
21
24
25#include <complex>
26#include <cstring>
27
28
30
31#ifdef DEAL_II_ARPACK_WITH_PARPACK
32extern "C"
33{
34 // http://www.mathkeisan.com/usersguide/man/pdnaupd.html
35 void
36 pdnaupd_(MPI_Fint *comm,
37 int *ido,
38 char *bmat,
39 int *n,
40 char *which,
41 int *nev,
42 double *tol,
43 double *resid,
44 int *ncv,
45 double *v,
46 int *nloc,
47 int *iparam,
48 int *ipntr,
49 double *workd,
50 double *workl,
51 int *lworkl,
52 int *info);
53
54 // http://www.mathkeisan.com/usersguide/man/pdsaupd.html
55 void
56 pdsaupd_(MPI_Fint *comm,
57 int *ido,
58 char *bmat,
59 int *n,
60 char *which,
61 int *nev,
62 double *tol,
63 double *resid,
64 int *ncv,
65 double *v,
66 int *nloc,
67 int *iparam,
68 int *ipntr,
69 double *workd,
70 double *workl,
71 int *lworkl,
72 int *info);
73
74 // http://www.mathkeisan.com/usersguide/man/pdneupd.html
75 void
76 pdneupd_(MPI_Fint *comm,
77 int *rvec,
78 char *howmany,
79 int *select,
80 double *d,
81 double *di,
82 double *z,
83 int *ldz,
84 double *sigmar,
85 double *sigmai,
86 double *workev,
87 char *bmat,
88 int *n,
89 char *which,
90 int *nev,
91 double *tol,
92 double *resid,
93 int *ncv,
94 double *v,
95 int *nloc,
96 int *iparam,
97 int *ipntr,
98 double *workd,
99 double *workl,
100 int *lworkl,
101 int *info);
102
103 // http://www.mathkeisan.com/usersguide/man/pdseupd.html
104 void
105 pdseupd_(MPI_Fint *comm,
106 int *rvec,
107 char *howmany,
108 int *select,
109 double *d,
110 double *z,
111 int *ldz,
112 double *sigmar,
113 char *bmat,
114 int *n,
115 char *which,
116 int *nev,
117 double *tol,
118 double *resid,
119 int *ncv,
120 double *v,
121 int *nloc,
122 int *iparam,
123 int *ipntr,
124 double *workd,
125 double *workl,
126 int *lworkl,
127 int *info);
128
129 // other resources:
130 // http://acts.nersc.gov/superlu/example5/pnslac.c.html
131 // https://github.com/phpisciuneri/tijo/blob/master/dvr_parpack.cpp
132}
133
207template <typename VectorType>
209{
210public:
215
267
273 {
274 const unsigned int number_of_arnoldi_vectors;
276 const bool symmetric;
277 const int mode;
279 const unsigned int number_of_arnoldi_vectors = 15,
281 const bool symmetric = false,
282 const int mode = 3);
283 };
284
289 control() const;
290
297
301 void
302 reinit(const IndexSet &locally_owned_dofs);
303
310 void
311 reinit(const IndexSet &locally_owned_dofs,
312 const std::vector<IndexSet> &partitioning);
313
317 void
318 reinit(const VectorType &distributed_vector);
319
323 void
324 set_initial_vector(const VectorType &vec);
325
334 void
335 set_shift(const std::complex<double> sigma);
336
346 template <typename MatrixType1, typename MatrixType2, typename INVERSE>
347 void
348 solve(const MatrixType1 &A,
349 const MatrixType2 &B,
350 const INVERSE &inverse,
351 std::vector<std::complex<double>> &eigenvalues,
352 std::vector<VectorType> &eigenvectors,
353 const unsigned int n_eigenvalues);
354
358 template <typename MatrixType1, typename MatrixType2, typename INVERSE>
359 void
360 solve(const MatrixType1 &A,
361 const MatrixType2 &B,
362 const INVERSE &inverse,
363 std::vector<std::complex<double>> &eigenvalues,
364 std::vector<VectorType *> &eigenvectors,
365 const unsigned int n_eigenvalues);
366
370 std::size_t
371 memory_consumption() const;
372
373protected:
379
384
385 // keep MPI communicator non-const as Arpack functions are not const either:
386
391
396
397 // C++98 guarantees that the elements of a vector are stored contiguously
398
403
407 std::vector<double> workl;
408
412 std::vector<double> workd;
413
417 int nloc;
418
422 int ncv;
423
424
428 int ldv;
429
434 std::vector<double> v;
435
440
445 std::vector<double> resid;
446
450 int ldz;
451
457 std::vector<double> z;
458
463
467 std::vector<double> workev;
468
472 std::vector<int> select;
473
477 VectorType src, dst, tmp;
478
482 std::vector<types::global_dof_index> local_indices;
483
487 double sigmar;
488
492 double sigmai;
493
494private:
501 void
502 internal_reinit(const IndexSet &locally_owned_dofs);
503
508 int,
509 int,
510 << arg1 << " eigenpairs were requested, but only " << arg2
511 << " converged");
512
514 int,
515 int,
516 << "Number of wanted eigenvalues " << arg1
517 << " is larger that the size of the matrix " << arg2);
518
520 int,
521 int,
522 << "Number of wanted eigenvalues " << arg1
523 << " is larger that the size of eigenvectors " << arg2);
524
527 int,
528 int,
529 << "To store the real and complex parts of " << arg1
530 << " eigenvectors in real-valued vectors, their size (currently set to "
531 << arg2 << ") should be greater than or equal to " << arg1 + 1);
532
534 int,
535 int,
536 << "Number of wanted eigenvalues " << arg1
537 << " is larger that the size of eigenvalues " << arg2);
538
540 int,
541 int,
542 << "Number of Arnoldi vectors " << arg1
543 << " is larger that the size of the matrix " << arg2);
544
546 int,
547 int,
548 << "Number of Arnoldi vectors " << arg1
549 << " is too small to obtain " << arg2 << " eigenvalues");
550
552 int,
553 << "This ido " << arg1
554 << " is not supported. Check documentation of ARPACK");
555
557 int,
558 << "This mode " << arg1
559 << " is not supported. Check documentation of ARPACK");
560
562 int,
563 << "Error with Pdnaupd, info " << arg1
564 << ". Check documentation of ARPACK");
565
567 int,
568 << "Error with Pdneupd, info " << arg1
569 << ". Check documentation of ARPACK");
570
572 int,
573 << "Maximum number " << arg1 << " of iterations reached.");
574
576 int,
577 << "No shifts could be applied during implicit"
578 << " Arnoldi update, try increasing the number of"
579 << " Arnoldi vectors.");
580};
581
582
583
584template <typename VectorType>
585std::size_t
587{
589 (workl.size() + workd.size() + v.size() + resid.size() + z.size() +
590 workev.size()) +
591 src.memory_consumption() + dst.memory_consumption() +
592 tmp.memory_consumption() +
594 local_indices.size();
595}
596
597
598
599template <typename VectorType>
601 const unsigned int number_of_arnoldi_vectors,
602 const WhichEigenvalues eigenvalue_of_interest,
603 const bool symmetric,
604 const int mode)
605 : number_of_arnoldi_vectors(number_of_arnoldi_vectors)
606 , eigenvalue_of_interest(eigenvalue_of_interest)
607 , symmetric(symmetric)
608 , mode(mode)
609{
610 // Check for possible options for symmetric problems
611 if (symmetric)
612 {
613 Assert(
616 "'largest real part' can only be used for non-symmetric problems!"));
617 Assert(
620 "'smallest real part' can only be used for non-symmetric problems!"));
621 Assert(
624 "'largest imaginary part' can only be used for non-symmetric problems!"));
625 Assert(
628 "'smallest imaginary part' can only be used for non-symmetric problems!"));
629 }
630 Assert(mode >= 1 && mode <= 3,
631 ExcMessage("Currently, only modes 1, 2 and 3 are supported."));
632}
633
634
635
636template <typename VectorType>
639 const AdditionalData &data)
644 , lworkl(0)
645 , nloc(0)
646 , ncv(0)
647 , ldv(0)
649 , ldz(0)
650 , lworkev(0)
651 , sigmar(0.0)
652 , sigmai(0.0)
653{}
654
655
656
657template <typename VectorType>
658void
659PArpackSolver<VectorType>::set_shift(const std::complex<double> sigma)
660{
661 sigmar = sigma.real();
662 sigmai = sigma.imag();
663}
664
665
666
667template <typename VectorType>
668void
670{
671 initial_vector_provided = true;
672 Assert(resid.size() == local_indices.size(),
673 ExcDimensionMismatch(resid.size(), local_indices.size()));
674 vec.extract_subvector_to(local_indices.begin(),
675 local_indices.end(),
676 resid.data());
677}
678
679
680
681template <typename VectorType>
682void
684{
685 // store local indices to write to vectors
686 local_indices = locally_owned_dofs.get_index_vector();
687
688 // scalars
689 nloc = locally_owned_dofs.n_elements();
690 ncv = additional_data.number_of_arnoldi_vectors;
691
692 AssertDimension(local_indices.size(), nloc);
693
694 // vectors
695 ldv = nloc;
696 v.resize(ldv * ncv, 0.0);
697
698 resid.resize(nloc, 1.0);
699
700 // work arrays for ARPACK
701 workd.resize(3 * nloc, 0.0);
702
703 lworkl =
704 additional_data.symmetric ? ncv * ncv + 8 * ncv : 3 * ncv * ncv + 6 * ncv;
705 workl.resize(lworkl, 0.);
706
707 ldz = nloc;
708 z.resize(ldz * ncv, 0.); // TODO we actually need only ldz*nev
709
710 // WORKEV Double precision work array of dimension 3*NCV.
711 lworkev = additional_data.symmetric ? 0 /*not used in symmetric case*/
712 :
713 3 * ncv;
714 workev.resize(lworkev, 0.);
715
716 select.resize(ncv, 0);
717}
718
719
720
721template <typename VectorType>
722void
724{
725 internal_reinit(locally_owned_dofs);
726
727 // deal.II vectors:
728 src.reinit(locally_owned_dofs, mpi_communicator);
729 dst.reinit(locally_owned_dofs, mpi_communicator);
730 tmp.reinit(locally_owned_dofs, mpi_communicator);
731}
732
733
734
735template <typename VectorType>
736void
737PArpackSolver<VectorType>::reinit(const VectorType &distributed_vector)
738{
739 internal_reinit(distributed_vector.locally_owned_elements());
740
741 // deal.II vectors:
742 src.reinit(distributed_vector);
743 dst.reinit(distributed_vector);
744 tmp.reinit(distributed_vector);
745}
746
747
748
749template <typename VectorType>
750void
752 const std::vector<IndexSet> &partitioning)
753{
754 internal_reinit(locally_owned_dofs);
755
756 // deal.II vectors:
757 src.reinit(partitioning, mpi_communicator);
758 dst.reinit(partitioning, mpi_communicator);
759 tmp.reinit(partitioning, mpi_communicator);
760}
761
762
763
764template <typename VectorType>
765template <typename MatrixType1, typename MatrixType2, typename INVERSE>
766void
768 const MatrixType2 &B,
769 const INVERSE &inverse,
770 std::vector<std::complex<double>> &eigenvalues,
771 std::vector<VectorType> &eigenvectors,
772 const unsigned int n_eigenvalues)
773{
774 std::vector<VectorType *> eigenvectors_ptr(eigenvectors.size());
775 for (unsigned int i = 0; i < eigenvectors.size(); ++i)
776 eigenvectors_ptr[i] = &eigenvectors[i];
777 solve(A, B, inverse, eigenvalues, eigenvectors_ptr, n_eigenvalues);
778}
779
780
781
782template <typename VectorType>
783template <typename MatrixType1, typename MatrixType2, typename INVERSE>
784void
785PArpackSolver<VectorType>::solve(const MatrixType1 &system_matrix,
786 const MatrixType2 &mass_matrix,
787 const INVERSE &inverse,
788 std::vector<std::complex<double>> &eigenvalues,
789 std::vector<VectorType *> &eigenvectors,
790 const unsigned int n_eigenvalues)
791{
792 if (additional_data.symmetric)
793 {
794 Assert(n_eigenvalues <= eigenvectors.size(),
795 PArpackExcInvalidEigenvectorSize(n_eigenvalues,
796 eigenvectors.size()));
797 }
798 else
799 Assert(n_eigenvalues + 1 <= eigenvectors.size(),
800 PArpackExcInvalidEigenvectorSizeNonsymmetric(n_eigenvalues,
801 eigenvectors.size()));
802
803 Assert(n_eigenvalues <= eigenvalues.size(),
804 PArpackExcInvalidEigenvalueSize(n_eigenvalues, eigenvalues.size()));
805
806
807 // use eigenvectors to get the problem size so that it is possible to
808 // employ LinearOperator for mass_matrix.
809 Assert(n_eigenvalues < eigenvectors[0]->size(),
810 PArpackExcInvalidNumberofEigenvalues(n_eigenvalues,
811 eigenvectors[0]->size()));
812
813 Assert(additional_data.number_of_arnoldi_vectors < eigenvectors[0]->size(),
814 PArpackExcInvalidNumberofArnoldiVectors(
815 additional_data.number_of_arnoldi_vectors, eigenvectors[0]->size()));
816
817 Assert(additional_data.number_of_arnoldi_vectors > 2 * n_eigenvalues + 1,
818 PArpackExcSmallNumberofArnoldiVectors(
819 additional_data.number_of_arnoldi_vectors, n_eigenvalues));
820
821 int mode = additional_data.mode;
822
823 // reverse communication parameter
824 // must be zero on the first call to pdnaupd
825 int ido = 0;
826
827 // 'G' generalized eigenvalue problem
828 // 'I' standard eigenvalue problem
829 char bmat[2];
830 bmat[0] = (mode == 1) ? 'I' : 'G';
831 bmat[1] = '\0';
832
833 // Specify the eigenvalues of interest, possible parameters:
834 // "LA" algebraically largest
835 // "SA" algebraically smallest
836 // "LM" largest magnitude
837 // "SM" smallest magnitude
838 // "LR" largest real part
839 // "SR" smallest real part
840 // "LI" largest imaginary part
841 // "SI" smallest imaginary part
842 // "BE" both ends of spectrum simultaneous
843 char which[3];
844 switch (additional_data.eigenvalue_of_interest)
845 {
846 case algebraically_largest:
847 std::strcpy(which, "LA");
848 break;
849 case algebraically_smallest:
850 std::strcpy(which, "SA");
851 break;
852 case largest_magnitude:
853 std::strcpy(which, "LM");
854 break;
855 case smallest_magnitude:
856 std::strcpy(which, "SM");
857 break;
858 case largest_real_part:
859 std::strcpy(which, "LR");
860 break;
861 case smallest_real_part:
862 std::strcpy(which, "SR");
863 break;
864 case largest_imaginary_part:
865 std::strcpy(which, "LI");
866 break;
867 case smallest_imaginary_part:
868 std::strcpy(which, "SI");
869 break;
870 case both_ends:
871 std::strcpy(which, "BE");
872 break;
873 }
874
875 // tolerance for ARPACK
876 double tol = control().tolerance();
877
878 // information to the routines
879 std::vector<int> iparam(11, 0);
880
881 iparam[0] = 1;
882 // shift strategy: exact shifts with respect to the current Hessenberg matrix
883 // H.
884
885 // maximum number of iterations
886 iparam[2] = control().max_steps();
887
888 // Parpack currently works only for NB = 1
889 iparam[3] = 1;
890
891 // Sets the mode of dsaupd:
892 // 1 is A*x=lambda*x, OP = A, B = I
893 // 2 is A*x = lambda*M*x, OP = inv[M]*A, B = M
894 // 3 is shift-invert mode, OP = inv[A-sigma*M]*M, B = M
895 // 4 is buckling mode,
896 // 5 is Cayley mode.
897
898 iparam[6] = mode;
899 std::vector<int> ipntr(14, 0);
900
901 // information out of the iteration
902 // If INFO .EQ. 0, a random initial residual vector is used.
903 // If INFO .NE. 0, RESID contains the initial residual vector,
904 // possibly from a previous run.
905 // Typical choices in this situation might be to use the final value
906 // of the starting vector from the previous eigenvalue calculation
907 int info = initial_vector_provided ? 1 : 0;
908
909 // Number of eigenvalues of OP to be computed. 0 < NEV < N.
910 int nev = n_eigenvalues;
911 int n_inside_arpack = nloc;
912
913 // IDO = 99: done
914 while (ido != 99)
915 {
916 // call of ARPACK pdnaupd routine
917 if (additional_data.symmetric)
918 pdsaupd_(&mpi_communicator_fortran,
919 &ido,
920 bmat,
921 &n_inside_arpack,
922 which,
923 &nev,
924 &tol,
925 resid.data(),
926 &ncv,
927 v.data(),
928 &ldv,
929 iparam.data(),
930 ipntr.data(),
931 workd.data(),
932 workl.data(),
933 &lworkl,
934 &info);
935 else
936 pdnaupd_(&mpi_communicator_fortran,
937 &ido,
938 bmat,
939 &n_inside_arpack,
940 which,
941 &nev,
942 &tol,
943 resid.data(),
944 &ncv,
945 v.data(),
946 &ldv,
947 iparam.data(),
948 ipntr.data(),
949 workd.data(),
950 workl.data(),
951 &lworkl,
952 &info);
953
954 AssertThrow(info == 0, PArpackExcInfoPdnaupd(info));
955
956 // if we converge, we shall not modify anything in work arrays!
957 if (ido == 99)
958 break;
959
960 // IPNTR(1) is the pointer into WORKD for X,
961 // IPNTR(2) is the pointer into WORKD for Y.
962 const int shift_x = ipntr[0] - 1;
963 const int shift_y = ipntr[1] - 1;
964 Assert(shift_x >= 0, ::ExcInternalError());
965 Assert(shift_x + nloc <= static_cast<int>(workd.size()),
967 Assert(shift_y >= 0, ::ExcInternalError());
968 Assert(shift_y + nloc <= static_cast<int>(workd.size()),
970
971 src = 0.;
972
973 // switch based on both ido and mode
974 if ((ido == -1) || (ido == 1 && mode < 3))
975 // compute Y = OP * X
976 {
977 src.add(nloc, local_indices.data(), workd.data() + shift_x);
978 src.compress(VectorOperation::add);
979
980 if (mode == 3)
981 // OP = inv[K - sigma*M]*M
982 {
983 mass_matrix.vmult(tmp, src);
984 inverse.vmult(dst, tmp);
985 }
986 else if (mode == 2)
987 // OP = inv[M]*K
988 {
989 system_matrix.vmult(tmp, src);
990 // store M*X in X
991 tmp.extract_subvector_to(local_indices.begin(),
992 local_indices.end(),
993 workd.data() + shift_x);
994 inverse.vmult(dst, tmp);
995 }
996 else if (mode == 1)
997 {
998 system_matrix.vmult(dst, src);
999 }
1000 else
1001 AssertThrow(false, PArpackExcMode(mode));
1002 }
1003 else if (ido == 1 && mode >= 3)
1004 // compute Y = OP * X for mode 3, 4 and 5, where
1005 // the vector B * X is already available in WORKD(ipntr(3)).
1006 {
1007 const int shift_b_x = ipntr[2] - 1;
1008 Assert(shift_b_x >= 0, ::ExcInternalError());
1009 Assert(shift_b_x + nloc <= static_cast<int>(workd.size()),
1011
1012 // B*X
1013 src.add(nloc, local_indices.data(), workd.data() + shift_b_x);
1014 src.compress(VectorOperation::add);
1015
1016 // solving linear system
1017 Assert(mode == 3, ExcNotImplemented());
1018 inverse.vmult(dst, src);
1019 }
1020 else if (ido == 2)
1021 // compute Y = B * X
1022 {
1023 src.add(nloc, local_indices.data(), workd.data() + shift_x);
1024 src.compress(VectorOperation::add);
1025
1026 // Multiplication with mass matrix M
1027 if (mode == 1)
1028 {
1029 dst = src;
1030 }
1031 else
1032 // mode 2,3 and 5 have B=M
1033 {
1034 mass_matrix.vmult(dst, src);
1035 }
1036 }
1037 else
1038 AssertThrow(false, PArpackExcIdo(ido));
1039 // Note: IDO = 3 does not appear to be required for currently
1040 // implemented modes
1041
1042 // store the result
1043 dst.extract_subvector_to(local_indices.begin(),
1044 local_indices.end(),
1045 workd.data() + shift_y);
1046 } // end of pd*aupd_ loop
1047
1048 // 1 - compute eigenvectors,
1049 // 0 - only eigenvalues
1050 int rvec = 1;
1051
1052 // which eigenvectors
1053 char howmany[4] = "All";
1054
1055 std::vector<double> eigenvalues_real(n_eigenvalues + 1, 0.);
1056 std::vector<double> eigenvalues_im(n_eigenvalues + 1, 0.);
1057
1058 // call of ARPACK pdneupd routine
1059 if (additional_data.symmetric)
1060 pdseupd_(&mpi_communicator_fortran,
1061 &rvec,
1062 howmany,
1063 select.data(),
1064 eigenvalues_real.data(),
1065 z.data(),
1066 &ldz,
1067 &sigmar,
1068 bmat,
1069 &n_inside_arpack,
1070 which,
1071 &nev,
1072 &tol,
1073 resid.data(),
1074 &ncv,
1075 v.data(),
1076 &ldv,
1077 iparam.data(),
1078 ipntr.data(),
1079 workd.data(),
1080 workl.data(),
1081 &lworkl,
1082 &info);
1083 else
1084 pdneupd_(&mpi_communicator_fortran,
1085 &rvec,
1086 howmany,
1087 select.data(),
1088 eigenvalues_real.data(),
1089 eigenvalues_im.data(),
1090 v.data(),
1091 &ldz,
1092 &sigmar,
1093 &sigmai,
1094 workev.data(),
1095 bmat,
1096 &n_inside_arpack,
1097 which,
1098 &nev,
1099 &tol,
1100 resid.data(),
1101 &ncv,
1102 v.data(),
1103 &ldv,
1104 iparam.data(),
1105 ipntr.data(),
1106 workd.data(),
1107 workl.data(),
1108 &lworkl,
1109 &info);
1110
1111 if (info == 1)
1112 {
1113 AssertThrow(false, PArpackExcInfoMaxIt(control().max_steps()));
1114 }
1115 else if (info == 3)
1116 {
1117 AssertThrow(false, PArpackExcNoShifts(1));
1118 }
1119 else if (info != 0)
1120 {
1121 AssertThrow(false, PArpackExcInfoPdneupd(info));
1122 }
1123
1124 for (int i = 0; i < nev; ++i)
1125 {
1126 (*eigenvectors[i]) = 0.0;
1127 AssertIndexRange(i * nloc + nloc, v.size() + 1);
1128
1129 eigenvectors[i]->add(nloc, local_indices.data(), &v[i * nloc]);
1130 eigenvectors[i]->compress(VectorOperation::add);
1131 }
1132
1133 for (size_type i = 0; i < n_eigenvalues; ++i)
1134 eigenvalues[i] =
1135 std::complex<double>(eigenvalues_real[i], eigenvalues_im[i]);
1136
1137 // Throw an error if the solver did not converge.
1138 AssertThrow(iparam[4] >= static_cast<int>(n_eigenvalues),
1139 PArpackExcConvergedEigenvectors(n_eigenvalues, iparam[4]));
1140
1141 // both PDNAUPD and PDSAUPD compute eigenpairs of inv[A - sigma*M]*M
1142 // with respect to a semi-inner product defined by M.
1143
1144 // resid likely contains residual with respect to M-norm.
1145 {
1146 tmp = 0.0;
1147 tmp.add(nloc, local_indices.data(), resid.data());
1148 tmp.compress(VectorOperation::add);
1149 solver_control.check(iparam[2], tmp.l2_norm());
1150 }
1151}
1152
1153
1154
1155template <typename VectorType>
1158{
1159 return solver_control;
1160}
1161
1162#endif
1163
1165#endif
size_type n_elements() const
Definition index_set.h:1917
std::vector< size_type > get_index_vector() const
Definition index_set.cc:911
void set_initial_vector(const VectorType &vec)
SolverControl & solver_control
MPI_Comm mpi_communicator
std::vector< double > z
std::vector< double > v
SolverControl & control() const
void solve(const MatrixType1 &A, const MatrixType2 &B, const INVERSE &inverse, std::vector< std::complex< double > > &eigenvalues, std::vector< VectorType > &eigenvectors, const unsigned int n_eigenvalues)
PArpackSolver(SolverControl &control, const MPI_Comm mpi_communicator, const AdditionalData &data=AdditionalData())
std::vector< types::global_dof_index > local_indices
std::vector< double > workl
std::vector< int > select
std::size_t memory_consumption() const
MPI_Fint mpi_communicator_fortran
void set_shift(const std::complex< double > sigma)
void reinit(const IndexSet &locally_owned_dofs)
std::vector< double > workd
const AdditionalData additional_data
bool initial_vector_provided
void internal_reinit(const IndexSet &locally_owned_dofs)
std::vector< double > resid
std::vector< double > workev
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & PArpackExcInvalidNumberofEigenvalues(int arg1, int arg2)
static ::ExceptionBase & PArpackExcInvalidEigenvalueSize(int arg1, int arg2)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & PArpackExcNoShifts(int arg1)
static ::ExceptionBase & PArpackExcInvalidEigenvectorSize(int arg1, int arg2)
static ::ExceptionBase & PArpackExcSmallNumberofArnoldiVectors(int arg1, int arg2)
#define Assert(cond, exc)
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & PArpackExcInfoPdneupd(int arg1)
#define AssertIndexRange(index, range)
static ::ExceptionBase & PArpackExcIdo(int arg1)
static ::ExceptionBase & PArpackExcConvergedEigenvectors(int arg1, int arg2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & PArpackExcInfoMaxIt(int arg1)
static ::ExceptionBase & PArpackExcMode(int arg1)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & PArpackExcInfoPdnaupd(int arg1)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & PArpackExcInvalidEigenvectorSizeNonsymmetric(int arg1, int arg2)
static ::ExceptionBase & PArpackExcInvalidNumberofArnoldiVectors(int arg1, int arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
const MPI_Comm comm
Definition mpi.cc:912
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
unsigned int global_dof_index
Definition types.h:92
void pdneupd_(MPI_Fint *comm, int *rvec, char *howmany, int *select, double *d, double *di, double *z, int *ldz, double *sigmar, double *sigmai, double *workev, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *nloc, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
void pdsaupd_(MPI_Fint *comm, int *ido, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *nloc, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
void pdnaupd_(MPI_Fint *comm, int *ido, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *nloc, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
void pdseupd_(MPI_Fint *comm, int *rvec, char *howmany, int *select, double *d, double *z, int *ldz, double *sigmar, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *nloc, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
AdditionalData(const unsigned int number_of_arnoldi_vectors=15, const WhichEigenvalues eigenvalue_of_interest=largest_magnitude, const bool symmetric=false, const int mode=3)
const unsigned int number_of_arnoldi_vectors
const WhichEigenvalues eigenvalue_of_interest
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)