Skip to content

Commit 70ff3b6

Browse files
author
svaradh
committed
Paolo's codes for hartree-fock and linear variation
1 parent 0d6a797 commit 70ff3b6

File tree

4 files changed

+1150
-0
lines changed

4 files changed

+1150
-0
lines changed

Day1/Codes/dysev.f

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
*> \brief <b> DSYEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for SY matrices</b>
2+
*
3+
* =========== DOCUMENTATION ===========
4+
*
5+
* Online html documentation available at
6+
* http://www.netlib.org/lapack/explore-html/
7+
*
8+
*> Download DSYEV + dependencies
9+
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsyev.f">
10+
*> [TGZ]</a>
11+
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsyev.f">
12+
*> [ZIP]</a>
13+
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyev.f">
14+
*> [TXT]</a>
15+
*
16+
* Definition:
17+
* ===========
18+
*
19+
* SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
20+
*
21+
* .. Scalar Arguments ..
22+
* CHARACTER JOBZ, UPLO
23+
* INTEGER INFO, LDA, LWORK, N
24+
* ..
25+
* .. Array Arguments ..
26+
* DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * )
27+
* ..
28+
*
29+
*
30+
*> \par Purpose:
31+
* =============
32+
*>
33+
*> \verbatim
34+
*>
35+
*> DSYEV computes all eigenvalues and, optionally, eigenvectors of a
36+
*> real symmetric matrix A.
37+
*> \endverbatim
38+
*
39+
* Arguments:
40+
* ==========
41+
*
42+
*> \param[in] JOBZ
43+
*> \verbatim
44+
*> JOBZ is CHARACTER*1
45+
*> = 'N': Compute eigenvalues only;
46+
*> = 'V': Compute eigenvalues and eigenvectors.
47+
*> \endverbatim
48+
*>
49+
*> \param[in] UPLO
50+
*> \verbatim
51+
*> UPLO is CHARACTER*1
52+
*> = 'U': Upper triangle of A is stored;
53+
*> = 'L': Lower triangle of A is stored.
54+
*> \endverbatim
55+
*>
56+
*> \param[in] N
57+
*> \verbatim
58+
*> N is INTEGER
59+
*> The order of the matrix A. N >= 0.
60+
*> \endverbatim
61+
*>
62+
*> \param[in,out] A
63+
*> \verbatim
64+
*> A is DOUBLE PRECISION array, dimension (LDA, N)
65+
*> On entry, the symmetric matrix A. If UPLO = 'U', the
66+
*> leading N-by-N upper triangular part of A contains the
67+
*> upper triangular part of the matrix A. If UPLO = 'L',
68+
*> the leading N-by-N lower triangular part of A contains
69+
*> the lower triangular part of the matrix A.
70+
*> On exit, if JOBZ = 'V', then if INFO = 0, A contains the
71+
*> orthonormal eigenvectors of the matrix A.
72+
*> If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
73+
*> or the upper triangle (if UPLO='U') of A, including the
74+
*> diagonal, is destroyed.
75+
*> \endverbatim
76+
*>
77+
*> \param[in] LDA
78+
*> \verbatim
79+
*> LDA is INTEGER
80+
*> The leading dimension of the array A. LDA >= max(1,N).
81+
*> \endverbatim
82+
*>
83+
*> \param[out] W
84+
*> \verbatim
85+
*> W is DOUBLE PRECISION array, dimension (N)
86+
*> If INFO = 0, the eigenvalues in ascending order.
87+
*> \endverbatim
88+
*>
89+
*> \param[out] WORK
90+
*> \verbatim
91+
*> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
92+
*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
93+
*> \endverbatim
94+
*>
95+
*> \param[in] LWORK
96+
*> \verbatim
97+
*> LWORK is INTEGER
98+
*> The length of the array WORK. LWORK >= max(1,3*N-1).
99+
*> For optimal efficiency, LWORK >= (NB+2)*N,
100+
*> where NB is the blocksize for DSYTRD returned by ILAENV.
101+
*>
102+
*> If LWORK = -1, then a workspace query is assumed; the routine
103+
*> only calculates the optimal size of the WORK array, returns
104+
*> this value as the first entry of the WORK array, and no error
105+
*> message related to LWORK is issued by XERBLA.
106+
*> \endverbatim
107+
*>
108+
*> \param[out] INFO
109+
*> \verbatim
110+
*> INFO is INTEGER
111+
*> = 0: successful exit
112+
*> < 0: if INFO = -i, the i-th argument had an illegal value
113+
*> > 0: if INFO = i, the algorithm failed to converge; i
114+
*> off-diagonal elements of an intermediate tridiagonal
115+
*> form did not converge to zero.
116+
*> \endverbatim
117+
*
118+
* Authors:
119+
* ========
120+
*
121+
*> \author Univ. of Tennessee
122+
*> \author Univ. of California Berkeley
123+
*> \author Univ. of Colorado Denver
124+
*> \author NAG Ltd.
125+
*
126+
*> \ingroup heev
127+
*
128+
* =====================================================================
129+
130+
SUBROUTINE dsyev( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
131+
*
132+
* -- LAPACK driver routine --
133+
* -- LAPACK is a software package provided by Univ. of Tennessee, --
134+
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
135+
*
136+
* .. Scalar Arguments ..
137+
CHARACTER JOBZ, UPLO
138+
INTEGER INFO, LDA, LWORK, N
139+
* ..
140+
* .. Array Arguments ..
141+
DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * )
142+
* ..
143+
*
144+
* =====================================================================
145+
*
146+
* .. Parameters ..
147+
DOUBLE PRECISION ZERO, ONE
148+
parameter( zero = 0.0d0, one = 1.0d0 )
149+
* ..
150+
* .. Local Scalars ..
151+
LOGICAL LOWER, LQUERY, WANTZ
152+
INTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE,
153+
$ LLWORK, LWKOPT, NB
154+
DOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,
155+
$ SMLNUM
156+
* ..
157+
* .. External Functions ..
158+
LOGICAL LSAME
159+
INTEGER ILAENV
160+
DOUBLE PRECISION DLAMCH, DLANSY
161+
EXTERNAL lsame, ilaenv, dlamch, dlansy
162+
* ..
163+
* .. External Subroutines ..
164+
EXTERNAL dlascl, dorgtr, dscal, dsteqr, dsterf,
165+
$ dsytrd,
166+
$ xerbla
167+
* ..
168+
* .. Intrinsic Functions ..
169+
INTRINSIC max, sqrt
170+
* ..
171+
* .. Executable Statements ..
172+
*
173+
* Test the input parameters.
174+
*
175+
wantz = lsame( jobz, 'V' )
176+
lower = lsame( uplo, 'L' )
177+
lquery = ( lwork.EQ.-1 )
178+
*
179+
info = 0
180+
IF( .NOT.( wantz .OR. lsame( jobz, 'N' ) ) ) THEN
181+
info = -1
182+
ELSE IF( .NOT.( lower .OR. lsame( uplo, 'U' ) ) ) THEN
183+
info = -2
184+
ELSE IF( n.LT.0 ) THEN
185+
info = -3
186+
ELSE IF( lda.LT.max( 1, n ) ) THEN
187+
info = -5
188+
END IF
189+
*
190+
IF( info.EQ.0 ) THEN
191+
nb = ilaenv( 1, 'DSYTRD', uplo, n, -1, -1, -1 )
192+
lwkopt = max( 1, ( nb+2 )*n )
193+
work( 1 ) = lwkopt
194+
*
195+
IF( lwork.LT.max( 1, 3*n-1 ) .AND. .NOT.lquery )
196+
$ info = -8
197+
END IF
198+
*
199+
IF( info.NE.0 ) THEN
200+
CALL xerbla( 'DSYEV ', -info )
201+
RETURN
202+
ELSE IF( lquery ) THEN
203+
RETURN
204+
END IF
205+
*
206+
* Quick return if possible
207+
*
208+
IF( n.EQ.0 ) THEN
209+
RETURN
210+
END IF
211+
*
212+
IF( n.EQ.1 ) THEN
213+
w( 1 ) = a( 1, 1 )
214+
work( 1 ) = 2
215+
IF( wantz )
216+
$ a( 1, 1 ) = one
217+
RETURN
218+
END IF
219+
*
220+
* Get machine constants.
221+
*
222+
safmin = dlamch( 'Safe minimum' )
223+
eps = dlamch( 'Precision' )
224+
smlnum = safmin / eps
225+
bignum = one / smlnum
226+
rmin = sqrt( smlnum )
227+
rmax = sqrt( bignum )
228+
*
229+
* Scale matrix to allowable range, if necessary.
230+
*
231+
anrm = dlansy( 'M', uplo, n, a, lda, work )
232+
iscale = 0
233+
IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
234+
iscale = 1
235+
sigma = rmin / anrm
236+
ELSE IF( anrm.GT.rmax ) THEN
237+
iscale = 1
238+
sigma = rmax / anrm
239+
END IF
240+
IF( iscale.EQ.1 )
241+
$ CALL dlascl( uplo, 0, 0, one, sigma, n, n, a, lda, info )
242+
*
243+
* Call DSYTRD to reduce symmetric matrix to tridiagonal form.
244+
*
245+
inde = 1
246+
indtau = inde + n
247+
indwrk = indtau + n
248+
llwork = lwork - indwrk + 1
249+
CALL dsytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),
250+
$ work( indwrk ), llwork, iinfo )
251+
*
252+
* For eigenvalues only, call DSTERF. For eigenvectors, first call
253+
* DORGTR to generate the orthogonal matrix, then call DSTEQR.
254+
*
255+
IF( .NOT.wantz ) THEN
256+
CALL dsterf( n, w, work( inde ), info )
257+
ELSE
258+
CALL dorgtr( uplo, n, a, lda, work( indtau ),
259+
$ work( indwrk ),
260+
$ llwork, iinfo )
261+
CALL dsteqr( jobz, n, w, work( inde ), a, lda,
262+
$ work( indtau ),
263+
$ info )
264+
END IF
265+
*
266+
* If matrix was scaled, then rescale eigenvalues appropriately.
267+
*
268+
IF( iscale.EQ.1 ) THEN
269+
IF( info.EQ.0 ) THEN
270+
imax = n
271+
ELSE
272+
imax = info - 1
273+
END IF
274+
CALL dscal( imax, one / sigma, w, 1 )
275+
END IF
276+
*
277+
* Set WORK(1) to optimal workspace size.
278+
*
279+
work( 1 ) = lwkopt
280+
*
281+
RETURN
282+
*
283+
* End of DSYEV
284+
*
285+
286+
END

0 commit comments

Comments
 (0)