Eigenvalue SoLvers for Petaflop-Applications (ELPA) 2024.03.001
Loading...
Searching...
No Matches
solve_secular_equation_template.F90
Go to the documentation of this file.
1#if 0
2! This file is part of ELPA.
3!
4! The ELPA library was originally created by the ELPA consortium,
5! consisting of the following organizations:
6!
7! - Max Planck Computing and Data Facility (MPCDF), formerly known as
8! Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
9! - Bergische Universität Wuppertal, Lehrstuhl für angewandte
10! Informatik,
11! - Technische Universität München, Lehrstuhl für Informatik mit
12! Schwerpunkt Wissenschaftliches Rechnen ,
13! - Fritz-Haber-Institut, Berlin, Abt. Theorie,
14! - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
15! Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
16! and
17! - IBM Deutschland GmbH
18!
19! This particular source code file contains additions, changes and
20! enhancements authored by Intel Corporation which is not part of
21! the ELPA consortium.
22!
23! More information can be found here:
24! http://elpa.mpcdf.mpg.de/
25!
26! ELPA is free software: you can redistribute it and/or modify
27! it under the terms of the version 3 of the license of the
28! GNU Lesser General Public License as published by the Free
29! Software Foundation.
30!
31! ELPA is distributed in the hope that it will be useful,
32! but WITHOUT ANY WARRANTY; without even the implied warranty of
33! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34! GNU Lesser General Public License for more details.
35!
36! You should have received a copy of the GNU Lesser General Public License
37! along with ELPA. If not, see <http://www.gnu.org/licenses/>
38!
39! ELPA reflects a substantial effort on the part of the original
40! ELPA consortium, and we ask you to respect the spirit of the
41! license that we chose: i.e., please contribute any changes you
42! may have back to the original ELPA library distribution, and keep
43! any derivatives of ELPA under the same license that we chose for
44! the original distribution, the GNU Lesser General Public License.
45!
46! Copyright of the original code rests with the authors inside the ELPA
47! consortium. The copyright of any additional modifications shall rest
48! with their original authors, but shall adhere to the licensing terms
49! distributed along with the original code in the file "COPYING".
50!
51#endif
52
53subroutine solve_secular_equation_&
54&precision&
55&(obj, n, i, d, z, delta, rho, dlam)
56!-------------------------------------------------------------------------------
57! This routine solves the secular equation of a symmetric rank 1 modified
58! diagonal matrix:
59!
60! 1. + rho*SUM(z(:)**2/(d(:)-x)) = 0
61!
62! It does the same as the LAPACK routine DLAED4 but it uses a bisection technique
63! which is more robust (it always yields a solution) but also slower
64! than the algorithm used in DLAED4.
65!
66! The same restictions than in DLAED4 hold, namely:
67!
68! rho > 0 and d(i+1) > d(i)
69!
70! but this routine will not terminate with error if these are not satisfied
71! (it will normally converge to a pole in this case).
72!
73! The output in DELTA(j) is always (D(j) - lambda_I), even for the cases
74! N=1 and N=2 which is not compatible with DLAED4.
75! Thus this routine shouldn't be used for these cases as a simple replacement
76! of DLAED4.
77!
78! The arguments are the same as in DLAED4 (with the exception of the INFO argument):
79!
80!
81! N (input) INTEGER
82! The length of all arrays.
83!
84! I (input) INTEGER
85! The index of the eigenvalue to be computed. 1 <= I <= N.
86!
87! D (input) DOUBLE PRECISION array, dimension (N)
88! The original eigenvalues. It is assumed that they are in
89! order, D(I) < D(J) for I < J.
90!
91! Z (input) DOUBLE PRECISION array, dimension (N)
92! The components of the updating Vector.
93!
94! DELTA (output) DOUBLE PRECISION array, dimension (N)
95! DELTA contains (D(j) - lambda_I) in its j-th component.
96! See remark above about DLAED4 compatibility!
97!
98! RHO (input) DOUBLE PRECISION
99! The scalar in the symmetric updating formula.
100!
101! DLAM (output) DOUBLE PRECISION
102! The computed lambda_I, the I-th updated eigenvalue.
103!-------------------------------------------------------------------------------
104
105 use precision
107 implicit none
108#include "../../src/general/precision_kinds.F90"
109 class(elpa_abstract_impl_t), intent(inout) :: obj
110 integer(kind=ik) :: n, i
111 real(kind=rk) :: d(n), z(n), delta(n), rho, dlam
112
113 integer(kind=ik) :: iter
114 real(kind=rk) :: a, b, x, y, dshift
115
116 ! In order to obtain sufficient numerical accuracy we have to shift the problem
117 ! either by d(i) or d(i+1), whichever is closer to the solution
118
119 ! Upper and lower bound of the shifted solution interval are a and b
120
121 call obj%timer%start("solve_secular_equation" // precision_suffix)
122 if (i==n) then
123
124 ! Special case: Last eigenvalue
125 ! We shift always by d(n), lower bound is d(n),
126 ! upper bound is determined by a guess:
127
128 dshift = d(n)
129 delta(:) = d(:) - dshift
130
131 a = 0.0_rk ! delta(n)
132 b = rho*sum(z(:)**2) + 1.0_rk ! rho*SUM(z(:)**2) is the lower bound for the guess
133 else
134
135 ! Other eigenvalues: lower bound is d(i), upper bound is d(i+1)
136 ! We check the sign of the function in the midpoint of the interval
137 ! in order to determine if eigenvalue is more close to d(i) or d(i+1)
138 x = 0.5_rk*(d(i)+d(i+1))
139 y = 1.0_rk + rho*sum(z(:)**2/(d(:)-x))
140 if (y>0) then
141 ! solution is next to d(i)
142 dshift = d(i)
143 else
144 ! solution is next to d(i+1)
145 dshift = d(i+1)
146 endif
147
148 delta(:) = d(:) - dshift
149 a = delta(i)
150 b = delta(i+1)
151
152 endif
153
154 ! Bisection:
155
156 do iter=1,200
157
158 ! Interval subdivision
159 x = 0.5_rk*(a+b)
160 if (x==a .or. x==b) exit ! No further interval subdivisions possible
161#ifdef DOUBLE_PRECISION_REAL
162 if (abs(x) < 1.e-200_rk8) exit ! x next to pole
163#else
164 if (abs(x) < 1.e-20_rk4) exit ! x next to pole
165#endif
166 ! evaluate value at x
167
168 y = 1. + rho*sum(z(:)**2/(delta(:)-x))
169
170 if (y==0) then
171 ! found exact solution
172 exit
173 elseif (y>0) then
174 b = x
175 else
176 a = x
177 endif
178
179 enddo
180
181 ! Solution:
182
183 dlam = x + dshift
184 delta(:) = delta(:) - x
185 call obj%timer%stop("solve_secular_equation" // precision_suffix)
186
187end subroutine solve_secular_equation_&
188 &precision
189
Fortran module to provide an abstract definition of the implementation. Do not use directly....
Definition elpa_abstract_impl.F90:50
Definition elpa_abstract_impl.F90:73