This repository was archived by the owner on Jan 15, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprgm_03_03.f03
More file actions
172 lines (166 loc) · 5.07 KB
/
Copy pathprgm_03_03.f03
File metadata and controls
172 lines (166 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
Program prgm_03_03
!
! This program reads a file name from the command line, opens that
! file, and loads a packed form of a symmetric matrix. Then, the packed
! matrix is expanded assuming a column-wise lower-triangle form and
! printed. Finally, the matrix is diagonalized using the LAPack routine
! SSPEV. The eigenvalues and eigenvectors are printed.
!
! The input file is expected to have the leading dimension (an integer
! NDim) of the matrix on the first line. The next (NDim*(NDim+1))/2
! lines each have one real number each given.
!
#ifdef FORHOMEWORK
#else
!
! H. P. Hratchian, 2019.
!
#endif
!
Implicit None
Integer::IIn,IError,NDim,i,j
Real,Dimension(:),Allocatable::Array_Input,EVals,Temp_Vector
Real,Dimension(:,:),Allocatable::Matrix,EVecs,Temp_Matrix
Character(Len=256)::FileName
!
! Begin by reading the input file name from the command line. Then,
! open the file and read the input array, Array_Input.
!
Call Get_Command_Argument(1,FileName)
Open(Unit=IIn,File=TRIM(FileName),Status='OLD',IOStat=IError)
If(IError.ne.0) then
Write(*,*)' Error opening input file.'
STOP
endIf
Read(IIn,*) NDim
Allocate(Array_Input((NDim*(NDim+1))/2),Matrix(NDim,NDim))
Allocate(EVals(NDim),EVecs(NDim,NDim),Temp_Vector(3*NDim))
Allocate(Temp_Matrix(NDim,NDim))
#ifdef FORHOMEWORK
!
! *************************************************************************
! WRITE CODE HERE TO READ THE ARRAY ELEMENTS FROM THE INPUT FILE.
! *************************************************************************
!
#else
Do i = 1,(NDim*(NDim+1))/2
Read(IIn,*) Array_Input(i)
endDo
#endif
Close(Unit=IIn)
!
! Convert Array_Input to Matrix and print the matrix.
!
Write(*,*)' The matrix loaded (column) lower-triangle packed:'
Call SymmetricPacked2Matrix_LowerPacked(NDim,Array_Input,Matrix)
Call Print_Matrix_Full_Real(Matrix,NDim,NDim)
#ifdef FORHOMEWORK
Call SSPEV('***','***',NDim,Array_Input,EVals,EVecs,NDim, &
Temp_Vector,IError)
#else
Call SSPEV('V','L',NDim,Array_Input,EVals,EVecs,NDim, &
Temp_Vector,IError)
#endif
If(IError.ne.0) then
Write(*,*)' Failure in DSPEV.'
STOP
endIf
Write(*,*)' EVals:'
Call Print_Matrix_Full_Real(RESHAPE(EVals,(/1,NDim/)),1,NDim)
Write(*,*)' EVecs:'
Call Print_Matrix_Full_Real(EVecs,NDim,NDim)
!
End Program prgm_03_03
#ifdef FORHOMEWORK
#else
Subroutine SymmetricPacked2Matrix_LowerPacked(N,ArrayIn,AMatOut)
!
! This subroutine accepts an array, ArrayIn, that is (N*(N+1))/2 long.
! It then converts that form to the N-by-N matrix AMatOut taking
! ArrayIn to be in lower-packed storage form. Note: The storage mode
! also assumes the lower-packed storage is packed by columns.
!
Implicit None
Integer,Intent(In)::N
Real,Dimension((N*(N+1))/2),Intent(In)::ArrayIn
Real,Dimension(N,N),Intent(Out)::AMatOut
!
Integer::i,j,k
!
! Loop through the elements of AMatOut and fill them appropriately from
! Array_Input.
!
k = 0
Do j = 1,N
Do i = j,N
k = k+1
AMatOut(i,j) = ArrayIn(k)
AMatOut(j,i) = ArrayIn(k)
endDo
endDo
!
Return
End Subroutine SymmetricPacked2Matrix_LowerPacked
Subroutine SymmetricPacked2Matrix_UpperPacked(N,ArrayIn,AMatOut)
!
! This subroutine accepts an array, ArrayIn, that is (N*(N+1))/2 long.
! It then converts that form to the N-by-N matrix AMatOut taking
! ArrayIn to be in upper-packed storage form. Note: The storage mode
! also assumes the upper-packed storage is packed by columns.
!
Implicit None
Integer,Intent(In)::N
Real,Dimension((N*(N+1))/2),Intent(In)::ArrayIn
Real,Dimension(N,N),Intent(Out)::AMatOut
!
Integer::i,j,k
!
! Loop through the elements of AMatOut and fill them appropriately from
! Array_Input.
!
k = 0
Do j = 1,N
Do i = 1,j
k = k+1
AMatOut(i,j) = ArrayIn(k)
AMatOut(j,i) = ArrayIn(k)
endDo
endDo
!
Return
End Subroutine SymmetricPacked2Matrix_UpperPacked
Subroutine Print_Matrix_Full_Real(AMat,M,N)
!
! This subroutine prints a real matrix that is fully dimension - i.e.,
! not stored in packed form. AMat is the matrix, which is dimensioned
! (M,N).
!
! The output of this routine is sent to unit number 6 (set by the local
! parameter integer IOut).
!
!
! Variable Declarations
!
implicit none
integer,intent(in)::M,N
real,dimension(M,N),intent(in)::AMat
!
! Local variables
integer,parameter::IOut=6,NColumns=5
integer::i,j,IFirst,ILast
!
1000 Format(1x,A)
2000 Format(5x,5(7x,I7))
2010 Format(1x,I7,5F14.6)
!
Do IFirst = 1,N,NColumns
ILast = Min(IFirst+NColumns-1,N)
write(IOut,2000) (i,i=IFirst,ILast)
Do i = 1,M
write(IOut,2010) i,(AMat(i,j),j=IFirst,ILast)
endDo
endDo
!
Return
End Subroutine Print_Matrix_Full_Real
#endif