FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_EIG_lanczos.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 !-------------------------------------------------------------------------------
7 contains
8 
10  subroutine fstr_solve_lanczos(hecMESH, hecMAT, fstrSOLID, fstrEIG, hecEBC)
11  use m_fstr
12  use hecmw_util
13  use m_eigen_lib
16  use hecmw_ebc_defer
18 
19  implicit none
20 
21  type(hecmwst_local_mesh) :: hecMESH
22  type(hecmwst_matrix) :: hecMAT
23  type(fstr_solid) :: fstrSOLID
24  type(fstr_eigen) :: fstrEIG
25  type(hecmwst_ebc) :: hecEBC
26  type(fstr_tri_diag) :: Tri
27  type(fstr_eigen_vec), pointer :: Q(:)
28  integer(kind=kint) :: N, NP, NDOF, NNDOF, NPNDOF
29  integer(kind=kint) :: iter, maxiter, nget, ierr
30  integer(kind=kint) :: i, j, k, in, jn, kn, ik
31  integer(kind=kint) :: ig, ig0, is0, ie0
32  real(kind=kreal) :: t1, t2, tolerance
33  real(kind=kreal) :: alpha, beta, beta0, resid
34  real(kind=kreal), allocatable :: s(:), t(:), p(:)
35  integer(kind=kint), allocatable :: mark(:)
36  character(len=HECMW_MSG_LEN) :: msg(2), noconv
37  logical :: is_converge, unusable
38  ! a linear solution whose relative residual reaches this carries an error of about one percent, and
39  ! the eigenvalues computed from it inherit that error; falling short of the tolerance by less than
40  ! this is common and leaves the eigenvalues usable
41  real(kind=kreal), parameter :: resid_unusable = 1.0d-2
42 
43  n = hecmat%N
44  np = hecmat%NP
45  ndof = hecmesh%n_dof
46  nndof = n *ndof
47  npndof = np*ndof
48 
49  allocate(fstreig%filter(npndof))
50  fstreig%filter = 1.0d0
51  !fstrEIG%sigma = 0.01d0
52 
53  jn = 0
54  do i = 1, npndof
55  if(hecebc%mark(i) == 0) cycle
56  jn = jn + 1
57  fstreig%filter(i) = 0.0d0
58  enddo
59 
60  if(hecmw_mat_get_mpc_method(hecmat) == 3)then
61  allocate(mark(npndof))
62  call hecmw_mpc_mark_slave(hecmesh, hecmat, mark)
63  do i = 1, npndof
64  if(mark(i) == 1) fstreig%filter(i) = 0.0d0
65  enddo
66  deallocate(mark)
67  endif
68 
69  do ig0 = 1, fstrsolid%SPRING_ngrp_tot
70  ig = fstrsolid%SPRING_ngrp_ID(ig0)
71  is0 = hecmesh%node_group%grp_index(ig-1) + 1
72  ie0 = hecmesh%node_group%grp_index(ig )
73  do ik = is0, ie0
74  jn = jn + 1
75  enddo
76  enddo
77 
78  call hecmw_allreduce_i1(hecmesh, jn, hecmw_sum)
79  if(jn == 0)then
80  fstreig%is_free = .true.
81  if(myrank == 0)then
82  write(*,"(a,1pe12.4)") '** free modal analysis: shift factor =', fstreig%sigma
83  endif
84  endif
85 
86  call hecmw_update_r(hecmesh, fstreig%filter, np, ndof)
87 
88  in = 0
89  do i = 1, nndof
90  if(fstreig%filter(i) == 1.0d0) in = in + 1
91  enddo
92  call hecmw_allreduce_i1(hecmesh, in, hecmw_sum)
93 
94  fstreig%maxiter = fstreig%maxiter + 1
95  if(in < fstreig%maxiter)then
96  if(myrank == 0)then
97  write(imsg,*) '** changed maxiter to system matrix size.'
98  endif
99  fstreig%maxiter = in + 1
100  endif
101 
102  if(in < fstreig%nget)then
103  fstreig%nget = in
104  endif
105 
106  maxiter = fstreig%maxiter
107 
108  allocate(q(0:maxiter))
109  allocate(q(0)%q(npndof))
110  allocate(q(1)%q(npndof))
111  allocate(fstreig%eigval(maxiter))
112  allocate(fstreig%eigvec(npndof, maxiter))
113  allocate(tri%alpha(maxiter))
114  allocate(tri%beta(maxiter))
115  allocate(t(npndof))
116  allocate(s(npndof))
117  allocate(p(npndof))
118 
119  fstreig%eigval = 0.0d0
120  fstreig%eigvec = 0.0d0
121  t = 0.0d0
122  p = 0.0d0
123  s = 0.0d0
124  q(0)%q = 0.0d0
125  q(1)%q = 0.0d0
126  tri%alpha = 0.0d0
127  tri%beta = 0.0d0
128  hecmat%X = 0.0d0
129 
130  call lanczos_set_initial_value(hecmesh, hecmat, fstreig, fstreig%eigvec, p, q(1)%q, tri%beta(1))
131 
132  hecmat%Iarray(98) = 1 !Assembly complete
133  hecmat%Iarray(97) = 1 !Need numerical factorization
134 
135  if(myrank == 0)then
136  write(imsg,*)
137  write(imsg,*) ' ***** STAGE Begin Lanczos loop **'
138  endif
139 
140  do iter = 1, maxiter-1
142  do i = 1, npndof
143  hecmat%B(i) = p(i)
144  enddo
145 
146  call solve_lineq(hecmesh, hecmat)
147 
148  ! the Lanczos vectors are built from this solution, so a solver that fell short of its tolerance is
149  ! tolerated only while the solution stays usable
150  if(hecmw_mat_get_flag_diverged(hecmat) /= kno .or. hecmw_mat_get_flag_converged(hecmat) == kno)then
151  resid = hecmw_rel_resid_l2(hecmesh, hecmat)
152  unusable = (resid >= resid_unusable .or. resid /= resid) ! the second test catches NaN
153  write(noconv,'(a,i0,a,1pe12.5)') ' the linear solver did not converge at Lanczos iteration ', &
154  & iter, '; relative residual =', resid
155  if(unusable)then
156  msg(1) = '### ERROR:'//trim(noconv)
157  msg(2) = ' the eigenvalues cannot be computed from it; loosen the residual tolerance given in !SOLVER'
158  else
159  msg(1) = '### WARNING:'//trim(noconv)
160  msg(2) = ' the eigenvalues may carry an error of a comparable order'
161  endif
162  if(myrank == 0)then
163  write(*,'(a/a)') trim(msg(1)), trim(msg(2))
164  write(ilog,'(a/a)') trim(msg(1)), trim(msg(2))
165  endif
166  if(unusable) call fstr_abort( hecmw_exit_noconv )
167  endif
168 
169  allocate(q(iter+1)%q(npndof))
170 
171  do i = 1, npndof
172  t(i) = hecmat%X(i) * fstreig%filter(i)
173  enddo
174 
177  do i = 1, npndof
178  t(i) = t(i) - tri%beta(iter) * q(iter-1)%q(i)
179  enddo
180 
181  alpha = 0.0d0
182  do i = 1, nndof
183  alpha = alpha + p(i) * t(i)
184  enddo
185  call hecmw_allreduce_r1(hecmesh, alpha, hecmw_sum)
186  tri%alpha(iter) = alpha
187 
189  do i = 1, npndof
190  t(i) = t(i) - tri%alpha(iter) * q(iter)%q(i)
191  enddo
192 
194  s = 0.0d0
195 
196  do i = 1, npndof
197  s(i) = fstreig%mass(i) * t(i)
198  enddo
199 
200  do j = 0, iter
201  t1 = 0.0d0
202  do i = 1, nndof
203  t1 = t1 + q(j)%q(i) * s(i)
204  enddo
205  call hecmw_allreduce_r1(hecmesh, t1, hecmw_sum)
206  do i = 1, npndof
207  t(i) = t(i) - t1 * q(j)%q(i)
208  enddo
209  enddo
210 
212  do i = 1, npndof
213  s(i) = fstreig%mass(i) * t(i)
214  enddo
215 
216  beta = 0.0d0
217  do i = 1, nndof
218  beta = beta + s(i) * t(i)
219  enddo
220  call hecmw_allreduce_r1(hecmesh, beta, hecmw_sum)
221  tri%beta(iter+1) = dsqrt(beta)
222 
225  beta = 1.0d0/tri%beta(iter+1)
226  do i = 1, npndof
227  p(i) = s(i) * beta
228  q(iter+1)%q(i) = t(i) * beta
229  enddo
230 
231  fstreig%iter = iter
232  if(iter == 1) beta0 = tri%beta(iter+1)
233 
234  call tridiag(hecmesh, hecmat, fstreig, q, tri, iter, is_converge)
235 
236  if(is_converge) exit
237  enddo
238 
239  do i = 0, iter
240  if(associated(q(i)%q)) deallocate(q(i)%q)
241  enddo
242  deallocate(tri%alpha)
243  deallocate(tri%beta)
244  deallocate(t)
245  deallocate(s)
246  deallocate(p)
247 
248  t2 = hecmw_wtime()
249 
250  if(myrank == 0)then
251  write(imsg,*)
252  write(imsg,*) ' * STAGE Output and postprocessing **'
253  write(idbg,'(a,f10.2)') 'Lanczos loop (sec) :', t2 - t1
254  endif
255 
256  end subroutine fstr_solve_lanczos
257 
258 end module m_fstr_eig_lanczos
Essential boundary conditions kept as per-DOF marks and values so that they can be imposed on the mat...
real(kind=kreal) function, public hecmw_rel_resid_l2(hecMESH, hecMAT, COMMtime)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
integer(kind=4), parameter kreal
real(kind=kreal) function hecmw_wtime()
integer(kind=kint), parameter hecmw_exit_noconv
This modules just summarizes all modules used in eigen analysis.
Definition: eigen_LIB.f90:6
subroutine lanczos_set_initial_value(hecMESH, hecMAT, fstrEIG, eigvec, p, q, beta)
Initialize Lanczos iterations.
Lanczos iteration calculation.
subroutine fstr_solve_lanczos(hecMESH, hecMAT, fstrSOLID, fstrEIG, hecEBC)
SOLVE EIGENVALUE PROBLEM.
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)
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:103
integer(kind=kint), parameter imsg
Definition: m_fstr.F90:117
integer(kind=kint), parameter idbg
Definition: m_fstr.F90:118
subroutine fstr_abort(code)
Terminate the analysis with a classified exit status. MPI_ABORT does not perform the Fortran I/O fina...
Definition: m_fstr.F90:701
integer(kind=kint), parameter ilog
FILE HANDLER.
Definition: m_fstr.F90:114
integer(kind=kint), parameter kno
Definition: m_fstr.F90:32
Package of data used by Lanczos eigenvalue solver.
Definition: m_fstr.F90:632