FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_EIG_tridiag.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
8  use hecmw
9 
10  implicit none
11 
12  public
13 
15  real(kind=kreal), pointer :: q(:) => null()
16  end type fstr_eigen_vec
17 
19  real(kind=kreal), allocatable :: alpha(:)
20  real(kind=kreal), allocatable :: beta(:)
21  end type fstr_tri_diag
22 
23 contains
24 
25  subroutine tridiag(hecMESH, hecMAT, fstrEIG, Q, Tri, iter, is_converge)
26  use hecmw
27  use m_fstr
29  implicit none
30  type(hecmwst_local_mesh) :: hecmesh
31  type(hecmwst_matrix) :: hecMAT
32  type(fstr_eigen) :: fstrEIG
33  type(fstr_tri_diag) :: Tri
34  type(fstr_eigen_vec), pointer :: Q(:)
35 
36  integer(kind=kint), intent(in) :: iter
37  integer(kind=kint) :: N, NP, NDOF, NNDOF, NPNDOF
38  integer(kind=kint) :: i, j, k, in, jn, kn, nget
39  integer(kind=kint) :: iter2, ierr, maxiter
40  real(kind=kreal) :: resid, chk, sigma, tolerance, max_eigval
41  real(kind=kreal), allocatable :: alpha(:), beta(:), temp(:)
42  real(kind=kreal), allocatable :: l(:,:)
43 
44  integer(kind=kint), allocatable :: iparm(:)
45  real(kind=kreal), pointer :: eigvec(:,:)
46  real(kind=kreal), pointer :: eigval(:)
47  logical :: is_converge
48 
49  n = hecmat%N
50  np = hecmat%NP
51  ndof = hecmesh%n_dof
52  nndof = n *ndof
53  npndof = np*ndof
54  eigval => fstreig%eigval
55  eigvec => fstreig%eigvec
56  nget = fstreig%nget
57  maxiter = fstreig%maxiter
58  tolerance = fstreig%tolerance
59 
60  allocate( iparm(maxiter) )
61  allocate( temp(maxiter) )
62  allocate( alpha(iter) )
63  allocate( beta(iter) )
64  allocate( l(iter, iter) )
65 
66  do j=1, iter
67  do i = 1,iter
68  l(i,j) = 0.0d0
69  enddo
70  enddo
71 
72  do i=1, iter
73  alpha(i) = tri%alpha(i)
74  l(i,i) = 1.0d0
75  enddo
76 
77  beta(1) = 0.0d0
78  do i=2, iter
79  beta(i) = tri%beta(i)
80  enddo
81 
82  call ql_decomposition(iter, iter, alpha, beta, l, ierr)
83 
84  is_converge = .true.
85  chk = 0.0d0
86  max_eigval = maxval(alpha)
87  do i = 1, min(nget, iter)
88  if (dabs(alpha(i)) > 0.0d0) then
89  ! Divide by the eigenvalue of the mode itself.
90  resid = dabs(tri%beta(iter+1)*l(iter,i))/dabs(alpha(i))
91  else
92  ! An eigenvalue of zero indicates a numerical crash and the system stops.
93  call hecmw_abort( hecmw_comm_get_comm() )
94  endif
95  chk = max(chk, resid)
96  if(tolerance < resid) is_converge = .false.
97  enddo
98  if(myrank == 0) write(*,"(i8,1pe12.5)")iter, chk
99 
100  if(iter < nget) is_converge = .false.
101  if(iter == maxiter-1) is_converge = .true.
102 
103  if(is_converge)then
104  sigma = 0.0d0
105  if(fstreig%is_free) sigma = fstreig%sigma
106  do i = 1, iter
107  if(alpha(i) /= 0.0d0)then
108  eigval(i) = 1.0d0/alpha(i) - sigma
109  endif
110  enddo
111 
112  call evsort(eigval, iparm, iter)
113 
114  temp = eigval
115 
116  eigvec = 0.0d0
117  do k=1, iter
118  in = iparm(k)
119  eigval(k) = temp(in)
120  do j=1, iter
121  do i=1, npndof
122  eigvec(i, k) = eigvec(i, k) + q(j)%q(i) * l(j, in)
123  enddo
124  enddo
125  enddo
126 
127  do j=1, iter
128  chk = maxval(eigvec(:,j))
129  call hecmw_allreduce_r1(hecmesh, chk, hecmw_max)
130  if(chk /= 0.0d0)then
131  chk = 1.0d0/chk
132  do i = 1, nndof
133  eigvec(i,j) = eigvec(i,j) * chk
134  enddo
135  endif
136  enddo
137  endif
138 
139  deallocate(iparm)
140  deallocate(temp)
141  deallocate(alpha)
142  deallocate(beta)
143  deallocate(l)
144  end subroutine tridiag
145 
146  !======================================================================!
147  ! Description !
148  !======================================================================!
158  !
159  !on input
160  !
161  !nm must be set to the row dimension of two-dimensional
162  !array parameters as declared in the calling program
163  !dimension statement.
164  !
165  !is the order of the matrix.
166  !
167  !contains the diagonal elements of the input matrix.
168  !
169  !contains the subdiagonal elements of the input matrix
170  !in its last n-1 positions. e(1) is arbitrary.
171  !
172  !contains the transformation matrix produced in the
173  !reduction by tred2, if performed. if the eigenvectors
174  !of the tridiagonal matrix are desired, z must contain
175  !the identity matrix.
176  !
177  !on output
178  !
179  !d
180  !contains the eigenvalues in ascending order. if an
181  !error exit is made, the eigenvalues are correct but
182  !unordered for indices 1,2,...,ierror-1.
183  !-----------------------------------------------------
184  !GP
185  !du
186  !contains the unordered eigenvalues. if an
187  !error exit is made, the eigenvalues are correct and
188  !unordered for indices 1,2,...,ierror-1.
189  !-----------------------------------------------------
190  !e
191  !has been destroyed.
192  !
193  !z
194  !contains orthonormal eigenvectors of the symmetric
195  !tridiagonal (or full) matrix. if an error exit is made,
196  !z contains the eigenvectors associated with the stored
197  !eigenvalues.
198  !-----------------------------------------------------
199  !zu
200  !contains unordered eigenvectors of the symm. tridiag. matrix
201  !-----------------------------------------------------
202  !ierror is set to
203  ! zero for normal return,
204  ! j if the j-th eigenvalue has not been
205  ! determined after 30 iterations.
206  !
207  !calls a2b2 for dsqrt(a*a + b*b) .
208  !=======================================================================
209 
210  !call QL_decomposition(iter, iter, alpha, beta, L, ierr)
211  subroutine ql_decomposition(nm, n, d, e, z, ierror)
212  use hecmw
213  implicit none
214  integer(kind=kint) :: i, j, k, l, m, n, ii, l1, l2, nm, mml, ierror
215  real(kind=kreal) :: d(n), e(n), z(nm, n)
216  real(kind=kreal) :: c, c2, c3, dl1, el1, f, g, h, p, r, s, s2, tst1, tst2
217 
218  ierror = 0
219  if (n .eq. 1) go to 1001
220 
221  do i = 2, n
222  e(i-1) = e(i)
223  enddo
224 
225  f = 0.0d0
226  tst1 = 0.0d0
227  e(n) = 0.0d0
228 
229  do 240 l = 1, n
230  j = 0
231  h = dabs(d(l)) + dabs(e(l))
232  if (tst1 .lt. h) tst1 = h
233  ! .......... look for small sub-diagonal element ..........
234  bb:do m = l, n
235  tst2 = tst1 + dabs(e(m))
236  if (tst2 .eq. tst1) exit bb
237  ! .......... e(n) is always zero, so there is no exit
238  ! through the bottom of the loop ..........
239  enddo bb
240 
241  if (m .eq. l) go to 220
242 
243  130 if (j .eq. 30) go to 1000
244  j = j + 1
245  ! .......... form shift ..........
246  l1 = l + 1
247  l2 = l1 + 1
248  g = d(l)
249  p = (d(l1) - g) / (2.0d0 * e(l))
250  r = a2b2(p,1.0d0)
251  d(l) = e(l) / (p + dsign(r,p))
252  d(l1) = e(l) * (p + dsign(r,p))
253  dl1 = d(l1)
254  h = g - d(l)
255  if (l2 .gt. n) go to 145
256 
257  do i = l2, n
258  d(i) = d(i) - h
259  enddo
260 
261  145 f = f + h
262  ! .......... ql transformation ..........
263  p = d(m)
264  c = 1.0d0
265  c2 = c
266  el1 = e(l1)
267  s = 0.0d0
268  s2 = 0.0d0
269  c3 = 0.0d0
270  mml = m - l
271  ! .......... for i=m-1 step -1 until l do -- ..........
272  do ii = 1, mml
273  c3 = c2
274  c2 = c
275  s2 = s
276  i = m - ii
277  g = c * e(i)
278  h = c * p
279  r = a2b2(p,e(i))
280  e(i+1) = s * r
281  s = e(i) / r
282  c = p / r
283  p = c * d(i) - s * g
284  d(i+1) = h + s * (c * g + s * d(i))
285  ! .......... form vector ..........
286  do k = 1, n
287  h = z(k,i+1)
288  z(k,i+1) = s * z(k,i) + c * h
289  z(k,i) = c * z(k,i) - s * h
290  enddo
291  enddo
292 
293  p = -s * s2 * c3 * el1 * e(l) / dl1
294  e(l) = s * p
295  d(l) = c * p
296  tst2 = tst1 + dabs(e(l))
297  if (tst2 .gt. tst1) go to 130
298  220 d(l) = d(l) + f
299  240 continue
300 
301  ! .......... order eigenvalues and eigenvectors ..........
302  !GP: Get unordered eigenvalues and eigenvectors----------------
303 
304  do 300 ii = 2, n
305  i = ii - 1
306  k = i
307  p = d(i)
308 
309  aa:do j = ii, n
310  if (d(j) .ge. p) exit aa
311  k = j
312  p = d(j)
313  enddo aa
314 
315  if (k .eq. i) go to 300
316  d(k) = d(i)
317  d(i) = p
318 
319  do j = 1, n
320  p = z(j,i)
321  z(j,i) = z(j,k)
322  z(j,k) = p
323  enddo
324 
325  300 continue
326 
327  go to 1001
328  ! .......... set error -- no convergence to an
329  ! eigenvalue after 30 iterations ..........
330  1000 ierror = l
331  1001 return
332  end subroutine ql_decomposition
333 
334  function a2b2(a,b)
335  use hecmw
336  implicit none
337 
338  real(kind=kreal) :: a2b2
339  real(kind=kreal) :: a, b
340  real(kind=kreal) :: p, q, r, s, t, u
341 
342  p = dmax1(dabs(a), dabs(b))
343  if (p /= 0.0d0) then
344  r = (dmin1(dabs(a),dabs(b))/p) ** 2
345  do
346  t = 4.0d0 + r
347  if (t == 4.0d0) exit
348  s = r/t
349  u = 1.0d0 + 2.0d0*s
350  p = u * p
351  q = s/u
352  r = q * q * r
353  end do
354  end if
355  a2b2 = p
356  return
357 
358  end function a2b2
359 
360 end module m_fstr_eig_tridiag
Definition: hecmw.f90:6
subroutine evsort(EIG, NEW, NEIG)
Sort eigenvalues.
This module provides a subroutine to find the eigenvalues and eigenvectors of a symmetric tridiagonal...
subroutine tridiag(hecMESH, hecMAT, fstrEIG, Q, Tri, iter, is_converge)
subroutine ql_decomposition(nm, n, d, e, z, ierror)
This subroutine has been adapted from the eispack routine tql2, which is a translation of the algol p...
real(kind=kreal) function a2b2(a, b)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.F90:99
Package of data used by Lanczos eigenvalue solver.
Definition: m_fstr.F90:623