FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_solve_QuasiNewton.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 !-------------------------------------------------------------------------------
6 
8 
12  use hecmw_ebc_defer
13 
14  implicit none
15  ! parameters for line search
16  real(kind=kreal), parameter :: c_line_search=2.0, psi0_line_search=1.0d-2
17  real(kind=kreal), parameter :: delta_wolfe=0.2, sigma_wolfe=0.9, eps_wolfe=1.0d-3
18  real(kind=kreal), parameter :: omega_wolfe=0.001, delta_approx_wolfe=0.7
19  real(kind=kreal) :: c_wolfe, q_wolfe
20  integer, parameter :: n_mem_max=10
21  integer(kind=kint), parameter :: maxiter_ls = 10
22  integer(kind=kint), parameter :: pot_type=1
23 
24 contains
25 
28  subroutine fstr_quasi_newton( cstep, hecMESH, hecMAT, fstrSOLID, fstrPARAM, &
29  restrt_step_num, sub_step, ctime, dtime )
30  implicit none
31 
32  integer, intent(in) :: cstep
33  type (hecmwST_local_mesh) :: hecMESH
34  type (hecmwST_matrix) :: hecMAT
35  type (fstr_solid) :: fstrSOLID
36  integer, intent(in) :: sub_step
37  real(kind=kreal), intent(in) :: ctime
38  real(kind=kreal), intent(in) :: dtime
39  type (fstr_param) :: fstrPARAM
40  type (hecmwST_matrix_lagrange) :: hecLagMAT
41 
42  type (hecmwST_local_mesh), pointer :: hecMESHmpc
43  type (hecmwST_matrix), pointer :: hecMATmpc
44  type (hecmwST_ebc) :: hecEBC
45  integer(kind=kint) :: ndof
46  integer(kind=kint) :: i, iter
47  integer(kind=kint) :: stepcnt
48  integer(kind=kint) :: restrt_step_num
49  real(kind=kreal) :: tt0, tt, res, qnrm, rres, tincr, xnrm, dunrm, rxnrm
50  logical :: isLinear = .false.
51  integer(kind=kint) :: iterStatus
52 
53  real(kind=kreal), allocatable :: z_k(:), s_k(:,:), y_k(:,:), g_prev(:), rho_k(:)
54  real(kind=kreal) :: sdoty
55  integer :: n_mem
56  integer :: len_vector
57  integer(kind=kint) :: k
58 
59  integer :: u_debug
60  integer :: max_iter_bak
61  logical :: flag_approx_Wolfe
62 
63  max_iter_bak = fstrsolid%step_ctrl(cstep)%max_iter
64  fstrsolid%step_ctrl(cstep)%max_iter = 100*fstrsolid%step_ctrl(cstep)%max_iter
65 
66  call hecmw_mpc_mat_init(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
67 
68  if(.not. fstrpr%nlgeom)then
69  islinear = .true.
70  endif
71 
72  hecmat%NDOF = hecmesh%n_dof
73  ndof = hecmat%NDOF
74 
75  stepcnt = 0
76 
77  tincr = dtime
78  if( fstrsolid%step_ctrl(cstep)%solution == stepstatic ) tincr = 0.d0
79  call fstr_init_newton(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, heclagmat, ndof, 0, hecmat)
80  fstrsolid%GL0(:) = fstrsolid%GL(:) !store external load at du=0
81 
82  !! initialize du for non-zero Dirichlet condition
83  call hecmw_ebc_init(hecmat, hecebc)
84  call fstr_addbc(cstep, hecmesh, hecmat, fstrsolid, fstrparam, heclagmat, 1, hecebc, rhsvector=fstrsolid%dunode)
85  !! update residual vector
86  call fstr_calc_residual_vector(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam)
87 
88  len_vector = hecmesh%n_node*ndof
89  allocate(z_k(len_vector))
90  allocate(s_k(len_vector, n_mem_max))
91  allocate(y_k(len_vector, n_mem_max))
92  allocate(g_prev(len_vector))
93  allocate(rho_k(n_mem_max))
94  z_k(:) = 0.0d0
95  s_k(:,:) = 0.0d0
96  y_k(:,:) = 0.0d0
97  g_prev(:) = 0.0d0
98  rho_k(:) = 0.0d0
99  do i=1,len_vector
100  y_k(i,1) = -hecmat%B(i)
101  enddo
102 
103  ! parameter to judge Wolfe/approx Wolfe selection
104  c_wolfe = 0.0d0
105  q_wolfe = 0.0d0
106  flag_approx_wolfe = .false.
107  n_mem = 1
108  ! ----- Inner Iteration, lagrange multiplier constant
109  do iter=1,fstrsolid%step_ctrl(cstep)%max_iter
110  stepcnt = stepcnt+1
111 
112  ! ----- calculate search direction by limited BFGS method
113  do i=1,hecmesh%n_node*ndof
114  g_prev(i) = -hecmat%B(i)
115  enddo
116  call fstr_calc_direction_lbfgs(hecmesh, g_prev, s_k, y_k, rho_k, z_k, n_mem)
117 
118  ! ! ----- Set Boundary condition
119  do i = 1, len_vector
120  if( hecebc%mark(i) /= 0 ) z_k(i) = 0.0d0
121  enddo
122 
123  !----- line search of step length
124  call fstr_line_search_along_direction(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k)
125 
126  ! ----- update the small displacement and the displacement for 1step
127  ! \delta u^k => solver's solution
128  ! \Delta u_{n+1}^{k} = \Delta u_{n+1}^{k-1} + \delta u^k
129  call fstr_apply_solution_increment( hecmesh, fstrsolid, ndof, hecmat%X )
130 
131  !! set du for non-zero Dirichlet condition
132  ! call fstr_AddBC(cstep, hecMESH, hecMAT, fstrSOLID, fstrPARAM, hecLagMAT, 1, RHSvector=fstrSOLID%dunode)
133  call fstr_calc_residual_vector(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam)
134 
135  ! ----- check convergence
136  call fstr_check_convergence(hecmesh, hecmat, fstrsolid, fstrpr, ndof, iter, sub_step, cstep, &
137  hecmat%B, 0, res, res, 0, iterstatus)
138  if (iterstatus == kitrconverged) exit
139  if (iterstatus == kitrdiverged .or. iterstatus==kitrfloatingerror) then
140  call hecmw_ebc_finalize(hecebc)
141  call hecmw_mpc_mat_finalize(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
142  fstrsolid%step_ctrl(cstep)%max_iter = max_iter_bak
143  return
144  endif
145  ! if (iterStatus == kitrDiverged) exit
146  ! if (iterStatus==kitrFloatingError) return
147 
148  n_mem = min(n_mem+1, n_mem_max)
149  do k=n_mem, 2, -1
150  s_k(:,k) = s_k(:,k-1)
151  y_k(:,k) = y_k(:,k-1)
152  rho_k(k) = rho_k(k-1)
153  enddo
154 
155  do i = 1, hecmesh%n_node*ndof
156  s_k(i,1) = hecmat%X(i)
157  y_k(i,1) = -hecmat%B(i) - g_prev(i)
158  enddo
159  call hecmw_innerproduct_r(hecmesh,ndof,s_k(:,1), y_k(:,1), sdoty)
160  if (abs(sdoty) < 1.0d-10) then
161  rho_k(1) = 0.0d0
162  else
163  rho_k(1) = 1.0d0/sdoty
164  endif
165  enddo
166  ! ----- end of inner loop
167 
168  fstrsolid%NRstat_i(knstmaxit) = max(fstrsolid%NRstat_i(knstmaxit),iter) ! logging newton iteration(maxtier)
169  fstrsolid%NRstat_i(knstsumit) = fstrsolid%NRstat_i(knstsumit) + iter ! logging newton iteration(sum of iter)
170 
171  ! ----- update the total displacement
172  ! u_{n+1} = u_{n} + \Delta u_{n+1}
173  call fstr_commit_solution_increment( hecmesh, fstrsolid, ndof )
174 
175  call fstr_updatestate( hecmesh, fstrsolid, tincr )
176 
177  fstrsolid%CutBack_stat = 0
178  call hecmw_ebc_finalize(hecebc)
179  call hecmw_mpc_mat_finalize(hecmesh, hecmat, hecmeshmpc, hecmatmpc)
180 
181  fstrsolid%step_ctrl(cstep)%max_iter = max_iter_bak
182  end subroutine fstr_quasi_newton
183 
184  subroutine fstr_calc_direction_lbfgs(hecMESH, g_prev, s_k, y_k, rho_k, z_k, n_mem)
185  implicit none
186 
187  type (hecmwST_local_mesh) :: hecMESH
188  real(kind=kreal) :: z_k(:), s_k(:,:), y_k(:,:), g_prev(:), rho_k(:)
189  integer :: n_mem
190 
191  real(kind=kreal), allocatable :: q(:)
192  real(kind=kreal) :: alpha(n_mem), beta
193  real(kind=kreal) :: sdotq, ysq, gamma, ydotz, g_max
194 
195  integer :: len_vector, ndof
196  integer(kind=kint) :: k,i
197 
198  ndof = hecmesh%n_dof
199  len_vector = hecmesh%n_node*hecmesh%n_dof
200  allocate(q(len_vector))
201 
202  q(1:len_vector) = g_prev(1:len_vector)
203 
204  do k=1, n_mem
205  call hecmw_innerproduct_r(hecmesh,ndof,s_k(:,k), q, sdotq)
206  alpha(k) = rho_k(k) * sdotq
207  do i=1, len_vector
208  q(i) = q(i) - alpha(k)*y_k(i,k)
209  enddo
210  enddo
211  call hecmw_innerproduct_r(hecmesh,ndof,y_k(:,1), y_k(:,1), ysq)
212  if (n_mem==1) then
213  call hecmw_absmax_r(hecmesh, ndof, g_prev, g_max)
214  ! if (g_max==0.0d0) then
215  ! write(6,*) 'gradient of potential is zero-vector'
216  ! stop
217  ! endif
218  ! gamma = 1.0d0/g_max
219  gamma = 1.0d0
220  else if (abs(rho_k(1)) < 1.0d-10) then
221  gamma = 1.0d0
222  else
223  gamma = 1.0d0/(rho_k(1)*ysq)
224  endif
225 
226  do i=1, len_vector
227  z_k(i) = gamma*q(i)
228  enddo
229 
230  do k=n_mem, 1, -1
231  call hecmw_innerproduct_r(hecmesh,ndof,y_k(:,k), z_k, ydotz)
232  beta = rho_k(k)*ydotz
233  do i=1, len_vector
234  z_k(i)=z_k(i) + s_k(i,k)*(alpha(k)-beta)
235  enddo
236  enddo
237  deallocate(q)
238  end subroutine fstr_calc_direction_lbfgs
239 
240  subroutine fstr_apply_alpha0(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, h_prime, pot)
241  implicit none
242  type (hecmwST_local_mesh) :: hecMESH
243  type (hecmwST_matrix) :: hecMAT
244  type (fstr_solid) :: fstrSOLID
245  real(kind=kreal), intent(in) :: ctime
246  real(kind=kreal), intent(in) :: tincr
247  integer(kind=kint) :: iter
248  integer, intent(in) :: cstep
249  real(kind=kreal), intent(in) :: dtime
250  type (fstr_param) :: fstrPARAM
251  real(kind=kreal), intent(in) :: z_k(:)
252  real(kind=kreal) :: h_prime, pot
253 
254  hecmat%X(:) = 0.0d0
255  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, hecmat%B, z_k, h_prime)
256  pot = fstr_get_potential(cstep,hecmesh,hecmat,fstrsolid,pot_type)
257  end subroutine fstr_apply_alpha0
258 
259  subroutine fstr_apply_alpha(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, alpha, h_prime, pot)
260  implicit none
261  type (hecmwST_local_mesh) :: hecMESH
262  type (hecmwST_matrix) :: hecMAT
263  type (fstr_solid) :: fstrSOLID
264  real(kind=kreal), intent(in) :: ctime
265  real(kind=kreal), intent(in) :: tincr
266  integer(kind=kint) :: iter
267  integer, intent(in) :: cstep
268  real(kind=kreal), intent(in) :: dtime
269  type (fstr_param) :: fstrPARAM
270  real(kind=kreal), intent(in) :: z_k(:)
271  real(kind=kreal), intent(in) :: alpha
272  real(kind=kreal) :: h_prime, pot
273 
274  hecmat%X(:) = -alpha*z_k(:)
275  call fstr_calc_residual_vector_with_x(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam)
276  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, hecmat%B, z_k, h_prime)
277  pot = fstr_get_potential_with_x(cstep,hecmesh,hecmat,fstrsolid,pot_type)
278  end subroutine fstr_apply_alpha
279 
280  subroutine fstr_init_line_search_range(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, &
281  h_prime_0, pot_0, alpha_S, h_prime_S, pot_S, alpha_E, h_prime_E, pot_E)
282  implicit none
283  type (hecmwST_local_mesh) :: hecMESH
284  type (hecmwST_matrix) :: hecMAT
285  type (fstr_solid) :: fstrSOLID
286  real(kind=kreal), intent(in) :: ctime
287  real(kind=kreal), intent(in) :: tincr
288  integer(kind=kint) :: iter
289  integer, intent(in) :: cstep
290  real(kind=kreal), intent(in) :: dtime
291  type (fstr_param) :: fstrPARAM
292  real(kind=kreal), intent(in) :: z_k(:)
293  real(kind=kreal), intent(in) :: h_prime_0, pot_0
294  real(kind=kreal) :: alpha_s, h_prime_s, pot_s
295  real(kind=kreal) :: alpha_e, h_prime_e, pot_e
296 
297  real(kind=kreal) :: alpha_s_new, h_prime_s_new, pot_s_new
298  real(kind=kreal) :: alpha_e_new, h_prime_e_new, pot_e_new
299  real(kind=kreal) :: alpha_tmp, h_prime_tmp, pot_tmp
300  real(kind=kreal) :: z_max
301  real(kind=kreal) :: pot_eps
302  pot_eps = eps_wolfe*c_wolfe
303 
304  alpha_s = 0.0d0
305  h_prime_s = h_prime_0
306  pot_s = pot_0
307 
308  if (iter==1) then
309  call hecmw_absmax_r(hecmesh, hecmat%NDOF, z_k, z_max)
310  alpha_e = psi0_line_search/z_max
311  else
312  alpha_e = 1.0d0
313  end if
314  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, alpha_e, h_prime_e, pot_e)
315 
316  do while (h_prime_e < 0.0d0)
317  ! if (pot_E <= pot_0 + pot_eps) then
318  ! alpha_S = alpha_E
319  ! h_prime_S = h_prime_E ! so h_prime_S < 0
320  ! pot_S = h_prime_S
321 
322  alpha_e = alpha_e * c_line_search
323  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, &
324  & fstrparam, z_k, alpha_e, h_prime_e, pot_e)
325  ! else
326  ! alpha_tmp = 2.0d0*alpha_E
327  ! h_prime_tmp = 0.0d0 ! elemact value
328  ! pot_tmp = 0.0d0 ! elemact value
329  ! call fstr_get_new_range_with_potential(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, pot_0, &
330  ! alpha_S, h_prime_S, pot_S, alpha_tmp, h_prime_tmp, pot_tmp, alpha_E, h_prime_E, pot_E, &
331  ! alpha_S_new, h_prime_S_new, pot_S_new, alpha_E_new, h_prime_E_new, pot_E_new)
332 
333  ! alpha_S = alpha_S_new
334  ! h_prime_S = h_prime_S_new
335  ! pot_S = pot_S_new
336 
337  ! alpha_E = alpha_E_new
338  ! h_prime_E = h_prime_E_new
339  ! pot_E = pot_E_new
340  ! return
341  ! end if
342  enddo
343  end subroutine fstr_init_line_search_range
344 
345  subroutine fstr_update_range(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, &
346  alpha_S, h_prime_S, pot_S, alpha_E, h_prime_E, pot_E, alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
347  implicit none
348  type (hecmwST_local_mesh) :: hecMESH
349  type (hecmwST_matrix) :: hecMAT
350  type (fstr_solid) :: fstrSOLID
351  real(kind=kreal), intent(in) :: ctime
352  real(kind=kreal), intent(in) :: tincr
353  integer(kind=kint) :: iter
354  integer, intent(in) :: cstep
355  real(kind=kreal), intent(in) :: dtime
356  type (fstr_param) :: fstrPARAM
357  real(kind=kreal) :: z_k(:)
358  real(kind=kreal) :: alpha_s, h_prime_s, pot_s
359  real(kind=kreal) :: alpha_e, h_prime_e, pot_e
360  real(kind=kreal) :: alpha_c, h_prime_c, pot_c
361  real(kind=kreal) :: h_prime_0, pot_0
362 
363  real(kind=kreal) :: alpha_a, h_prime_a, pot_a
364  real(kind=kreal) :: alpha_b, h_prime_b, pot_b
365  real(kind=kreal) :: alpha_a_bar, h_prime_a_bar, pot_a_bar
366  real(kind=kreal) :: alpha_b_bar, h_prime_b_bar, pot_b_bar
367  real(kind=kreal) :: alpha_c_bar, h_prime_c_bar, pot_c_bar
368 
369  call fstr_get_new_range_with_potential(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, pot_0, &
370  alpha_s, h_prime_s, pot_s, alpha_e, h_prime_e, pot_e, alpha_c, h_prime_c, pot_c, &
371  alpha_a, h_prime_a, pot_a, alpha_b, h_prime_b, pot_b)
372 
373  if (alpha_c == alpha_a) then
374  call fstr_get_secant(alpha_s, h_prime_s, alpha_a, h_prime_a, alpha_c_bar)
375  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, &
376  alpha_c_bar, h_prime_c_bar, pot_c_bar)
377  end if
378  if (alpha_c == alpha_b) then
379  call fstr_get_secant(alpha_b, h_prime_b, alpha_e, h_prime_e, alpha_c_bar)
380  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, &
381  alpha_c_bar, h_prime_c_bar, pot_c_bar)
382  end if
383 
384  if ((alpha_c == alpha_a) .or. (alpha_c == alpha_b)) then
385  call fstr_get_new_range_with_potential(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, pot_0, &
386  alpha_a, h_prime_a, pot_a, alpha_b, h_prime_b, pot_b, alpha_c_bar, h_prime_c_bar, pot_c_bar, &
387  alpha_a_bar, h_prime_a_bar, pot_a_bar, alpha_b_bar, h_prime_b_bar, pot_b_bar)
388  else
389  alpha_a_bar = alpha_a
390  h_prime_a_bar = h_prime_a
391  pot_a_bar = pot_a
392 
393  alpha_b_bar = alpha_b
394  h_prime_b_bar = h_prime_b
395  pot_b_bar = pot_b
396  end if
397 
398 
399  if ((alpha_b_bar - alpha_a_bar) > 0.66*(alpha_e - alpha_s)) then
400  alpha_c_bar = 0.5*(alpha_a_bar+alpha_b_bar)
401  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, &
402  alpha_c_bar, h_prime_c_bar, pot_c_bar)
403  call fstr_get_new_range_with_potential(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, pot_0, &
404  alpha_a, h_prime_a, pot_a, alpha_b, h_prime_b, pot_b, alpha_c_bar, h_prime_c_bar, pot_c_bar, &
405  alpha_s, h_prime_s, pot_s, alpha_e, h_prime_e, pot_e)
406  else
407  alpha_s = alpha_a_bar
408  h_prime_s = h_prime_a_bar
409  pot_s = pot_a_bar
410 
411  alpha_e = alpha_b_bar
412  h_prime_e = h_prime_b_bar
413  pot_e = pot_b_bar
414  end if
415  end subroutine fstr_update_range
416 
417  subroutine fstr_get_new_range_with_potential(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, &
418  fstrPARAM, z_k, pot_0, alpha_a, h_prime_a, pot_a, alpha_b, h_prime_b, pot_b, alpha_c, h_prime_c, pot_c, &
419  alpha_a_bar, h_prime_a_bar, pot_a_bar, alpha_b_bar, h_prime_b_bar, pot_b_bar)
420  implicit none
421  type (hecmwST_local_mesh) :: hecMESH
422  type (hecmwST_matrix) :: hecMAT
423  type (fstr_solid) :: fstrSOLID
424  real(kind=kreal), intent(in) :: ctime
425  real(kind=kreal), intent(in) :: tincr
426  integer(kind=kint) :: iter
427  integer, intent(in) :: cstep
428  real(kind=kreal), intent(in) :: dtime
429  type (fstr_param) :: fstrPARAM
430  real(kind=kreal), intent(in) :: z_k(:)
431  real(kind=kreal), intent(in) :: pot_0
432  real(kind=kreal), intent(in) :: alpha_a, h_prime_a, pot_a
433  real(kind=kreal), intent(in) :: alpha_b, h_prime_b, pot_b
434  real(kind=kreal), intent(in) :: alpha_c, h_prime_c, pot_c
435  real(kind=kreal) :: alpha_a_bar, h_prime_a_bar, pot_a_bar
436  real(kind=kreal) :: alpha_b_bar, h_prime_b_bar, pot_b_bar
437 
438  integer, parameter :: count_max=100
439  integer :: count_while
440  real(kind=kreal) :: alpha_d, h_prime_d, pot_d
441  real(kind=kreal) :: theta_ls = 0.5d0
442  real(kind=kreal) :: pot_eps
443  pot_eps = eps_wolfe*c_wolfe
444 
445  ! case of NOT (a < c < b)
446  if (alpha_c <= alpha_a .or. alpha_b <= alpha_c) then
447  alpha_a_bar = alpha_a
448  h_prime_a_bar = h_prime_a
449  pot_a_bar = pot_a
450 
451  alpha_b_bar = alpha_b
452  h_prime_b_bar = h_prime_b
453  pot_b_bar = pot_b
454  return
455  end if
456 
457  if (h_prime_c >= 0.0d0) then
458  alpha_a_bar = alpha_a
459  h_prime_a_bar = h_prime_a
460  pot_a_bar = pot_a
461 
462  alpha_b_bar = alpha_c
463  h_prime_b_bar = h_prime_c
464  pot_b_bar = pot_c
465  return
466  end if
467  ! below here, it can be assumed that h_prime_c<0
468 
469  if(pot_c <= pot_0 + pot_eps) then
470  alpha_a_bar = alpha_c
471  h_prime_a_bar = h_prime_c
472  pot_a_bar = pot_c
473 
474  alpha_b_bar = alpha_b
475  h_prime_b_bar = h_prime_b
476  pot_b_bar = pot_b
477  return
478  end if
479 
480  alpha_a_bar = alpha_a
481  h_prime_a_bar = h_prime_a
482  pot_a_bar = pot_a
483 
484  alpha_b_bar = alpha_b
485  h_prime_b_bar = h_prime_b
486  pot_b_bar = pot_b
487 
488  count_while = 0
489  do while(count_while < count_max)
490  count_while = count_while + 1
491 
492  alpha_d = (1.0d0-theta_ls)*alpha_a_bar + theta_ls*alpha_b_bar
493  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, alpha_d, h_prime_d, pot_d)
494 
495  if (h_prime_d >= 0.0d0) then
496  alpha_b_bar = alpha_d
497  h_prime_b_bar = h_prime_d
498  pot_b_bar = pot_d
499  return
500  end if
501 
502  if(pot_d <= pot_0 + pot_eps) then
503  alpha_a_bar = alpha_d
504  h_prime_a_bar = h_prime_d
505  pot_a_bar = pot_d
506  else
507  alpha_b_bar = alpha_d
508  h_prime_b_bar = h_prime_d
509  pot_b_bar = pot_d
510  end if
511  end do
512  write(6,*) 'fstr_get_new_range_with_potential reached loop count max.', hecmesh%my_rank, alpha_a_bar, alpha_b_bar
513  end subroutine fstr_get_new_range_with_potential
514 
515 
516  subroutine fstr_line_search_along_direction(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k)
517  implicit none
518  type (hecmwST_local_mesh) :: hecMESH
519  type (hecmwST_matrix) :: hecMAT
520  type (fstr_solid) :: fstrSOLID
521  real(kind=kreal), intent(in) :: ctime
522  real(kind=kreal), intent(in) :: tincr
523  integer(kind=kint) :: iter
524  integer, intent(in) :: cstep
525  real(kind=kreal), intent(in) :: dtime
526  type (fstr_param) :: fstrPARAM
527  real(kind=kreal) :: z_k(:)
528 
529  real(kind=kreal) :: alpha_s, h_prime_s, pot_s
530  real(kind=kreal) :: alpha_e, h_prime_e, pot_e
531  real(kind=kreal) :: alpha_c, h_prime_c, pot_c
532  real(kind=kreal) :: h_prime_0, pot_0
533  logical :: flag_converged
534  integer :: ndof, len_vector
535  real(kind=kreal) :: res
536 
537  integer(kind=kint) :: i, ierr, iter_ls
538  real(kind=kreal) :: z_max
539  integer :: elemact
540 
541  ndof = hecmat%NDOF
542  len_vector = hecmesh%n_node*hecmesh%n_dof
543 
544  call fstr_apply_alpha0(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, h_prime_0, pot_0)
545  if (h_prime_0 > 0.0d0) then
546  write(6,*) 'residual vector is not directed to potential decretion.', h_prime_0
547  stop
548  endif
549 
550  call fstr_init_line_search_range(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, &
551  fstrparam, z_k, h_prime_0, pot_0, alpha_s, h_prime_s, pot_s, alpha_e, h_prime_e, pot_e)
552  if( hecmesh%my_rank == 0 ) then
553  write(6,'(a, 6es27.16e3)') 'range initialized: alpha_S, alpha_E, h_prime_S, h_prime_E, pot_S, pot_E', &
554  & alpha_s, alpha_e, h_prime_s, h_prime_e, pot_s, pot_e
555  endif
556 
558  c_wolfe = c_wolfe + (abs(pot_0)-c_wolfe) / q_wolfe
559 
560  flag_converged = .false.
561  iter_ls=0
562  do while (iter_ls<maxiter_ls)
563  call fstr_get_secant(alpha_s, h_prime_s, alpha_e, h_prime_e, alpha_c)
564  call fstr_apply_alpha(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, alpha_c, h_prime_c, pot_c)
565 
566  if (abs( pot_c - pot_0) <= (omega_wolfe * c_wolfe) ) then
567  flag_converged = fstr_approx_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
568  else
569  flag_converged = fstr_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
570  endif
571  if (flag_converged) exit
572 
573  call fstr_update_range(hecmesh, hecmat, fstrsolid, ctime, tincr, iter, cstep, dtime, fstrparam, z_k, &
574  alpha_s, h_prime_s, pot_s, alpha_e, h_prime_e, pot_e, alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
575  iter_ls = iter_ls +1
576  enddo
577  if( hecmesh%my_rank == 0 ) then
578  write(6,'(a, 1i8, 5es27.16e3)') 'converged: alpha_S, alpha_E, alpha_c, h_prime_c, pot_c', &
579  & iter_ls, &
580  & alpha_s, alpha_e, alpha_c, h_prime_c, pot_c
581  endif
582  end subroutine fstr_line_search_along_direction
583 
584  subroutine fstr_get_secant(a, Fa, b, Fb, c)
585  implicit none
586  real(kind=kreal), intent(in) :: a,b, fa,fb
587  real(kind=kreal), intent(out) :: c
588  if(fb /= fa) then
589  c = (a*fb - b*fa) / ( fb - fa )
590  else
591  c = 0.5*a + 0.5*b
592  endif
593  end subroutine fstr_get_secant
594 
595  function fstr_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0) result(flag_converged)
596  implicit none
597  logical :: flag_converged
598 
599  real(kind=kreal), intent(in) :: alpha_c, h_prime_0, h_prime_c, pot_0, pot_c
600  real(kind=kreal) :: wolfe1_left, wolfe1_right, wolfe2_left, wolfe2_right
601 
602  wolfe1_left = pot_c - pot_0
603  wolfe1_right = delta_wolfe*h_prime_0*alpha_c
604 
605  wolfe2_left = h_prime_c
606  wolfe2_right = sigma_wolfe*h_prime_0
607 
608  flag_converged = (wolfe1_left<=wolfe1_right) .and. (wolfe2_left >= wolfe2_right)
609  if (flag_converged) write(6,'(a, 4es27.16e3)') 'oWolfe: ', wolfe1_left, wolfe1_right, wolfe2_left, wolfe2_right
610  end function fstr_wolfe_condition
611 
612  function fstr_approx_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0) result(flag_converged)
613  implicit none
614  logical :: flag_converged
615 
616  real(kind=kreal), intent(in) :: alpha_c, h_prime_0, h_prime_c, pot_0, pot_c
617  real(kind=kreal) :: wolfe1_left, wolfe1_right, wolfe2_left, wolfe2_right
618 
619  real(kind=kreal) :: pot_eps
620  pot_eps = eps_wolfe*c_wolfe
621 
622  wolfe1_left = ( 2.0 * delta_wolfe - 1.0d0 ) * h_prime_0
623  wolfe1_right = h_prime_c
624 
625  wolfe2_left = h_prime_c
626  wolfe2_right = sigma_wolfe*h_prime_0
627 
628  flag_converged = &
629  (wolfe1_left>=wolfe1_right) &
630  .and. (wolfe2_left >= wolfe2_right) &
631  .and. (pot_c <= pot_0 + pot_eps)
632  if (flag_converged) write(6,'(a, 6es27.16e3)') 'aWolfe: ', wolfe1_left, wolfe1_right, &
633  & wolfe2_left, wolfe2_right, pot_c, pot_0 + (eps_wolfe*c_wolfe)
634  end function fstr_approx_wolfe_condition
635 end module m_fstr_quasinewton
Essential boundary conditions kept as per-DOF marks and values so that they can be imposed on the mat...
subroutine, public hecmw_ebc_init(hecMAT, hecEBC)
subroutine, public hecmw_ebc_finalize(hecEBC)
This module provides a unified convergence check for Newton iteration.
subroutine, public fstr_check_convergence(hecMESH, hecMAT, fstrSOLID, fstrPR, ndof, iter, sub_step, cstep, residual_vec, nresid, resb, res_prev, n_node_global, iterStatus, maxDLag, converg_dlag)
Wrapper that calls fstr_check_convergence_main and applies the common divergence/NaN handling (status...
Finite-rotation nodal kinematics for NLGEOM.
subroutine, public fstr_apply_solution_increment(hecMESH, fstrSOLID, ndof, x)
Apply the linear-solver solution increment x to the step displacement dunode.
subroutine, public fstr_commit_solution_increment(hecMESH, fstrSOLID, ndof)
Commit the converged step increment dunode into the total displacement unode.
This module provides functions on nonlinear analysis.
subroutine fstr_init_newton(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, hecLagMAT, ndof, ctAlgo, conMAT)
This module provides functions on nonlinear analysis.
real(kind=kreal), parameter delta_approx_wolfe
real(kind=kreal), parameter psi0_line_search
real(kind=kreal), parameter eps_wolfe
subroutine fstr_get_new_range_with_potential(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, pot_0, alpha_a, h_prime_a, pot_a, alpha_b, h_prime_b, pot_b, alpha_c, h_prime_c, pot_c, alpha_a_bar, h_prime_a_bar, pot_a_bar, alpha_b_bar, h_prime_b_bar, pot_b_bar)
subroutine fstr_apply_alpha0(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, h_prime, pot)
real(kind=kreal), parameter c_line_search
subroutine fstr_update_range(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, alpha_S, h_prime_S, pot_S, alpha_E, h_prime_E, pot_E, alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
subroutine fstr_calc_direction_lbfgs(hecMESH, g_prev, s_k, y_k, rho_k, z_k, n_mem)
real(kind=kreal), parameter delta_wolfe
subroutine fstr_apply_alpha(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, alpha, h_prime, pot)
integer, parameter n_mem_max
logical function fstr_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
integer(kind=kint), parameter maxiter_ls
subroutine fstr_line_search_along_direction(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k)
subroutine fstr_get_secant(a, Fa, b, Fb, c)
integer(kind=kint), parameter pot_type
subroutine fstr_init_line_search_range(hecMESH, hecMAT, fstrSOLID, ctime, tincr, iter, cstep, dtime, fstrPARAM, z_k, h_prime_0, pot_0, alpha_S, h_prime_S, pot_S, alpha_E, h_prime_E, pot_E)
real(kind=kreal), parameter omega_wolfe
logical function fstr_approx_wolfe_condition(alpha_c, h_prime_c, pot_c, h_prime_0, pot_0)
subroutine fstr_quasi_newton(cstep, hecMESH, hecMAT, fstrSOLID, fstrPARAM, restrt_step_num, sub_step, ctime, dtime)
This subroutine solve nonlinear solid mechanics problems by Newton-Raphson method.
real(kind=kreal), parameter sigma_wolfe