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