23 public :: fstr_convergence_measure
24 public :: fstr_convergence_state
30 type fstr_convergence_measure
31 real(kind=kreal) ::
value = 0.0d0
32 real(kind=kreal) :: tol = 0.0d0
33 logical :: check = .false.
34 logical :: ok = .false.
35 logical :: absolute = .false.
36 integer(kind=kint) :: node = 0
37 integer(kind=kint) :: dof = 0
38 end type fstr_convergence_measure
45 type fstr_convergence_state
46 type(fstr_convergence_measure) :: m(2,3,2)
47 end type fstr_convergence_state
50 real(kind=kreal),
parameter :: fref_floor = 1.0d-8
60 residual_vec, cnvstat, iterStatus, hecLagMAT )
63 type(hecmwst_local_mesh),
intent(in) :: hecmesh
64 type(hecmwst_matrix),
intent(in) :: hecmat
67 integer(kind=kint),
intent(in) :: ndof
68 integer(kind=kint),
intent(in) :: iter
69 integer(kind=kint),
intent(in) :: sub_step
70 integer(kind=kint),
intent(in) :: cstep
71 real(kind=kreal),
intent(in) :: residual_vec(:)
72 type(fstr_convergence_state),
intent(out) :: cnvstat
73 integer(kind=kint),
intent(out) :: iterstatus
74 type(hecmwst_matrix_lagrange),
intent(in),
optional :: heclagmat
76 real(kind=kreal) :: res_for_check
77 logical :: do_failure_check
81 residual_vec, cnvstat, iterstatus, do_failure_check, res_for_check, heclagmat )
84 if( .not. do_failure_check )
return
87 if( res_for_check /= res_for_check )
then
89 else if( iter == fstrsolid%step_ctrl(cstep)%max_iter .or. &
90 res_for_check > fstrsolid%step_ctrl(cstep)%maxres )
then
97 if( hecmesh%my_rank == 0 )
then
98 write(
ilog,
'(a,i5,a,i5)')
'### Fail to Converge : at total_step=', cstep,
' sub_step=', sub_step
99 write( *,
'(a,i5,a,i5)')
' ### Fail to Converge : at total_step=', cstep,
' sub_step=', sub_step
101 fstrsolid%NRstat_i(knstmaxit) = max(fstrsolid%NRstat_i(knstmaxit), iter)
102 fstrsolid%NRstat_i(knstsumit) = fstrsolid%NRstat_i(knstsumit) + iter
103 fstrsolid%CutBack_stat = fstrsolid%CutBack_stat + 1
105 iter == fstrsolid%step_ctrl(cstep)%max_iter )
then
106 fstrsolid%NRstat_i(knstdresn) = 1
109 fstrsolid%NRstat_i(knstdresn) = 2
152 residual_vec, cnvstat, iterStatus, do_failure_check, res_for_check, hecLagMAT )
155 type(hecmwst_local_mesh),
intent(in) :: hecmesh
156 type(hecmwst_matrix),
intent(in) :: hecmat
159 integer(kind=kint),
intent(in) :: ndof
160 integer(kind=kint),
intent(in) :: iter
161 integer(kind=kint),
intent(in) :: cstep
162 real(kind=kreal),
intent(in) :: residual_vec(:)
163 type(fstr_convergence_state),
intent(out) :: cnvstat
164 integer(kind=kint),
intent(out) :: iterstatus
165 logical,
intent(out) :: do_failure_check
166 real(kind=kreal),
intent(out) :: res_for_check
167 type(hecmwst_matrix_lagrange),
intent(in),
optional :: heclagmat
172 do_failure_check = .false.
173 res_for_check = 0.0d0
177 call fstr_evaluate_convergence( hecmesh, hecmat, fstrsolid, ndof, cstep, has_dx, residual_vec, cnvstat, heclagmat )
179 if( hecmesh%my_rank == 0 )
call fstr_print_convergence_state( iter, cnvstat )
181 if( .not. has_dx )
return
183 if( fstr_decide_convergence( cnvstat ) )
then
188 do_failure_check = .true.
189 res_for_check = max( cnvstat%m(kcnvresidual, kcnvtranslation, kcnvl2)%value, &
190 cnvstat%m(kcnvresidual, kcnvrotation, kcnvl2)%value )
201 logical function fstr_decide_convergence( cnvstat )
203 type(fstr_convergence_state),
intent(in) :: cnvstat
205 type(fstr_convergence_measure) :: lag(2), dx(4), res(4)
207 lag = [ cnvstat%m(kcnvcorrection, kcnvlagrange, :) ]
208 dx = [ cnvstat%m(kcnvcorrection, kcnvtranslation:kcnvrotation, :) ]
209 res = [ cnvstat%m(kcnvresidual, kcnvtranslation:kcnvrotation, :) ]
211 fstr_decide_convergence = cnv_all_ok(lag) .and. &
212 ( ( cnv_any_check(dx) .and. cnv_all_ok(dx) ) .or. &
213 ( cnv_any_check(res) .and. cnv_all_ok(res) ) )
215 end function fstr_decide_convergence
218 logical function cnv_all_ok( ms )
220 type(fstr_convergence_measure),
intent(in) :: ms(:)
222 cnv_all_ok = all( ms%ok .or. .not. ms%check )
224 end function cnv_all_ok
227 logical function cnv_any_check( ms )
229 type(fstr_convergence_measure),
intent(in) :: ms(:)
231 cnv_any_check = any( ms%check )
233 end function cnv_any_check
239 subroutine fstr_evaluate_convergence( hecMESH, hecMAT, fstrSOLID, ndof, cstep, has_dx, residual_vec, cnvstat, &
243 type(hecmwst_local_mesh),
intent(in) :: hecmesh
244 type(hecmwst_matrix),
intent(in) :: hecmat
246 integer(kind=kint),
intent(in) :: ndof
247 integer(kind=kint),
intent(in) :: cstep
248 logical,
intent(in) :: has_dx
249 real(kind=kreal),
intent(in) :: residual_vec(:)
250 type(fstr_convergence_state),
intent(out) :: cnvstat
251 type(hecmwst_matrix_lagrange),
intent(in),
optional :: heclagmat
253 integer(kind=kint),
parameter :: nsum = 13
254 real(kind=kreal) :: sq(nsum)
255 integer(kind=kint) :: i, npndof, num_lagrange
256 real(kind=kreal) :: dx_t, dx_r, fref_t
257 logical :: has_rot, has_lag
260 if(
present(heclagmat) ) num_lagrange = heclagmat%num_lagrange
261 npndof = hecmat%NP*ndof
263 has_rot = ( ndof == 6 )
267 call fstr_get_sqnorm_dofgroup( hecmesh, ndof, residual_vec, sq(1), sq(2) )
268 call fstr_get_sqnorm_dofgroup( hecmesh, ndof, fstrsolid%QFORCE, sq(3), sq(4) )
269 call fstr_get_sqnorm_dofgroup( hecmesh, ndof, fstrsolid%DFORCE, sq(5), sq(6) )
271 call fstr_get_sqnorm_dofgroup( hecmesh, ndof, hecmat%X, sq(7), sq(8) )
272 call fstr_get_sqnorm_dofgroup( hecmesh, ndof, fstrsolid%dunode, sq(9), sq(10) )
273 do i = 1, num_lagrange
274 sq(11) = sq(11) + hecmat%X(npndof+i)*hecmat%X(npndof+i)
275 sq(12) = sq(12) + heclagmat%Lagrange(i)*heclagmat%Lagrange(i)
278 sq(13) = dble(num_lagrange)
279 call hecmw_allreduce_r( hecmesh, sq, nsum, hecmw_sum )
283 has_lag = ( sq(13) > 0.5d0 )
285 cnvstat%m(:,:,:)%tol = fstrsolid%step_ctrl(cstep)%cnv_tol(:,:,:)
286 cnvstat%m(:,:,:)%check = fstrsolid%step_ctrl(cstep)%cnv_check(:,:,:)
287 if( .not. has_rot ) cnvstat%m(:,kcnvrotation,:)%check = .false.
288 if( .not. has_lag ) cnvstat%m(:,kcnvlagrange,:)%check = .false.
289 if( .not. has_dx ) cnvstat%m(kcnvcorrection,:,:)%check = .false.
292 fref_t = max( sqrt(sq(3)), sqrt(sq(5)) )
293 call fstr_set_relative_measure( cnvstat%m(kcnvresidual,kcnvtranslation,kcnvl2), &
294 sqrt(sq(1)), fref_t )
296 call fstr_set_relative_measure( cnvstat%m(kcnvresidual,kcnvrotation,kcnvl2), &
297 sqrt(sq(2)), max( sqrt(sq(4)), sqrt(sq(6)) ) )
304 if( sq(9) > 0.0d0 ) dx_t = sqrt( sq(7)/sq(9) )
306 if( sq(10) > 0.0d0 ) dx_r = sqrt( sq(8)/sq(10) )
307 cnvstat%m(kcnvcorrection,kcnvtranslation,kcnvl2)%value = dx_t
308 if( has_rot ) cnvstat%m(kcnvcorrection,kcnvrotation,kcnvl2)%value = dx_r
311 call fstr_set_relative_measure( cnvstat%m(kcnvcorrection,kcnvlagrange,kcnvl2), &
312 sqrt(sq(11)), max( sqrt(sq(12)), fref_t ) )
317 if( any( cnvstat%m(:,:,kcnvmax)%check ) )
then
318 call fstr_evaluate_convergence_max( hecmesh, hecmat, fstrsolid, ndof, has_dx, residual_vec, cnvstat, &
325 if( sq(i) /= sq(i) ) cnvstat%m(:,:,:)%value = sq(i)
328 cnvstat%m(:,:,:)%ok = cnvstat%m(:,:,:)%check .and. ( cnvstat%m(:,:,:)%value < cnvstat%m(:,:,:)%tol )
330 end subroutine fstr_evaluate_convergence
337 subroutine fstr_evaluate_convergence_max( hecMESH, hecMAT, fstrSOLID, ndof, has_dx, residual_vec, cnvstat, &
341 type(hecmwst_local_mesh),
intent(in) :: hecmesh
342 type(hecmwst_matrix),
intent(in) :: hecmat
344 integer(kind=kint),
intent(in) :: ndof
345 logical,
intent(in) :: has_dx
346 real(kind=kreal),
intent(in) :: residual_vec(:)
347 type(fstr_convergence_state),
intent(inout) :: cnvstat
348 type(hecmwst_matrix_lagrange),
intent(in),
optional :: heclagmat
350 integer(kind=kint),
parameter :: nmax = 12
352 integer(kind=kint),
parameter :: nloc = 4
353 integer(kind=kint),
parameter :: imax_loc(nloc) = [ 1, 2, 7, 8 ]
354 integer(kind=kint),
parameter :: iq_loc(nloc) = [ kcnvresidual, kcnvresidual, kcnvcorrection, kcnvcorrection ]
355 integer(kind=kint),
parameter :: ig_loc(nloc) = [ kcnvtranslation, kcnvrotation, kcnvtranslation, kcnvrotation ]
356 real(kind=kreal) :: vmax(nmax), gmax(nmax)
357 integer(kind=kint) :: loc(2,nloc), gnode(nloc), gdof(nloc)
358 integer(kind=kint) :: i, k, npndof, num_lagrange
359 real(kind=kreal) :: dx_t, dx_r, fref_t
362 if(
present(heclagmat) ) num_lagrange = heclagmat%num_lagrange
363 npndof = hecmat%NP*ndof
367 call fstr_get_maxabs_dofgroup( hecmesh, ndof, residual_vec, vmax(1), vmax(2), loc(:,1), loc(:,2) )
368 call fstr_get_maxabs_dofgroup( hecmesh, ndof, fstrsolid%QFORCE, vmax(3), vmax(4) )
369 call fstr_get_maxabs_dofgroup( hecmesh, ndof, fstrsolid%DFORCE, vmax(5), vmax(6) )
371 call fstr_get_maxabs_dofgroup( hecmesh, ndof, hecmat%X, vmax(7), vmax(8), loc(:,3), loc(:,4) )
372 call fstr_get_maxabs_dofgroup( hecmesh, ndof, fstrsolid%dunode, vmax(9), vmax(10) )
373 do i = 1, num_lagrange
374 vmax(11) = max( vmax(11), abs(hecmat%X(npndof+i)) )
375 vmax(12) = max( vmax(12), abs(heclagmat%Lagrange(i)) )
379 call hecmw_allreduce_r( hecmesh, gmax, nmax, hecmw_max )
382 if( gmax(imax_loc(k)) > vmax(imax_loc(k)) ) loc(1,k) = 0
385 call hecmw_allreduce_i( hecmesh, gnode, nloc, hecmw_max )
388 if( loc(1,k) == gnode(k) ) gdof(k) = loc(2,k)
390 call hecmw_allreduce_i( hecmesh, gdof, nloc, hecmw_max )
393 fref_t = max( gmax(3), gmax(5) )
394 call fstr_set_relative_measure( cnvstat%m(kcnvresidual,kcnvtranslation,kcnvmax), &
397 call fstr_set_relative_measure( cnvstat%m(kcnvresidual,kcnvrotation,kcnvmax), &
398 gmax(2), max( gmax(4), gmax(6) ) )
404 if( gmax(9) > 0.0d0 ) dx_t = gmax(7) / gmax(9)
406 if( gmax(10) > 0.0d0 ) dx_r = gmax(8) / gmax(10)
407 cnvstat%m(kcnvcorrection,kcnvtranslation,kcnvmax)%value = dx_t
408 if( ndof == 6 ) cnvstat%m(kcnvcorrection,kcnvrotation,kcnvmax)%value = dx_r
409 call fstr_set_relative_measure( cnvstat%m(kcnvcorrection,kcnvlagrange,kcnvmax), &
410 gmax(11), max( gmax(12), fref_t ) )
414 cnvstat%m(iq_loc(k),ig_loc(k),kcnvmax)%node = gnode(k)
415 cnvstat%m(iq_loc(k),ig_loc(k),kcnvmax)%dof = gdof(k)
418 end subroutine fstr_evaluate_convergence_max
421 subroutine fstr_set_relative_measure( ms, val, fref )
423 type(fstr_convergence_measure),
intent(inout) :: ms
424 real(kind=kreal),
intent(in) :: val
425 real(kind=kreal),
intent(in) :: fref
427 ms%absolute = ( fref < fref_floor )
428 if( ms%absolute )
then
431 ms%value = val / fref
434 end subroutine fstr_set_relative_measure
441 subroutine fstr_get_sqnorm_dofgroup( hecMESH, ndof, vec, sq_t, sq_r )
443 type(hecmwst_local_mesh),
intent(in) :: hecmesh
444 integer(kind=kint),
intent(in) :: ndof
445 real(kind=kreal),
intent(in) :: vec(:)
446 real(kind=kreal),
intent(out) :: sq_t
447 real(kind=kreal),
intent(out) :: sq_r
449 integer(kind=kint) :: i, idof, idx
453 do i = 1, hecmesh%nn_internal
455 do idof = 1, min(ndof,3)
456 sq_t = sq_t + vec(idx+idof)*vec(idx+idof)
458 if( ndof /= 6 ) cycle
460 sq_r = sq_r + vec(idx+idof)*vec(idx+idof)
464 end subroutine fstr_get_sqnorm_dofgroup
470 subroutine fstr_get_maxabs_dofgroup( hecMESH, ndof, vec, vmax_t, vmax_r, loc_t, loc_r )
472 type(hecmwst_local_mesh),
intent(in) :: hecmesh
473 integer(kind=kint),
intent(in) :: ndof
474 real(kind=kreal),
intent(in) :: vec(:)
475 real(kind=kreal),
intent(out) :: vmax_t
476 real(kind=kreal),
intent(out) :: vmax_r
477 integer(kind=kint),
intent(out),
optional :: loc_t(2)
478 integer(kind=kint),
intent(out),
optional :: loc_r(2)
480 integer(kind=kint) :: i, idof, idx, gid
481 integer(kind=kint) :: lt(2), lr(2)
482 real(kind=kreal) :: a
490 do i = 1, hecmesh%nn_internal
492 gid = hecmesh%global_node_ID(i)
493 do idof = 1, min(ndof,3)
494 a = abs(vec(idx+idof))
495 if( a > vmax_t .or. ( a >= vmax_t .and. a > 0.0d0 .and. gid > lt(1) ) )
then
501 if( ndof /= 6 ) cycle
503 a = abs(vec(idx+idof))
504 if( a > vmax_r .or. ( a >= vmax_r .and. a > 0.0d0 .and. gid > lr(1) ) )
then
511 if(
present(loc_t) ) loc_t(:) = lt(:)
512 if(
present(loc_r) ) loc_r(:) = lr(:)
514 end subroutine fstr_get_maxabs_dofgroup
520 subroutine fstr_print_convergence_state( iter, cnvstat )
522 integer(kind=kint),
intent(in) :: iter
523 type(fstr_convergence_state),
intent(in) :: cnvstat
525 character(len=512) :: line
526 integer(kind=kint) :: iq, ig
528 write(line,
'(a,i8)')
" iter:", iter
529 do iq = kcnvresidual, kcnvcorrection
530 do ig = kcnvtranslation, kcnvlagrange
531 if( .not. cnvstat%m(iq,ig,kcnvl2)%check ) cycle
532 write(line(len_trim(line)+1:),
'(a,a,a,1pe11.4)')
", ", &
533 trim(fstr_convergence_label( iq, ig, kcnvl2, cnvstat%m(iq,ig,kcnvl2)%absolute )),
":", &
534 cnvstat%m(iq,ig,kcnvl2)%value
537 write(*,
'(a)') trim(line)
540 do iq = kcnvresidual, kcnvcorrection
541 do ig = kcnvtranslation, kcnvlagrange
542 if( .not. cnvstat%m(iq,ig,kcnvmax)%check ) cycle
543 if( len_trim(line) > 0 ) line = trim(line) //
","
544 write(line(len_trim(line)+1:),
'(a,a,a,1pe11.4)')
" ", &
545 trim(fstr_convergence_label( iq, ig, kcnvmax, cnvstat%m(iq,ig,kcnvmax)%absolute )),
":", &
546 cnvstat%m(iq,ig,kcnvmax)%value
547 if( cnvstat%m(iq,ig,kcnvmax)%node > 0 )
then
548 write(line(len_trim(line)+1:),
'(a,i0,a,i0,a)')
" (node ", cnvstat%m(iq,ig,kcnvmax)%node, &
549 ", dof ", cnvstat%m(iq,ig,kcnvmax)%dof,
")"
553 if( len_trim(line) > 0 )
write(*,
'(a,a)') repeat(
" ", 15), trim(line)
555 end subroutine fstr_print_convergence_state
558 function fstr_convergence_label( iq, ig, inorm, absolute )
result( label )
560 integer(kind=kint),
intent(in) :: iq
561 integer(kind=kint),
intent(in) :: ig
562 integer(kind=kint),
intent(in) :: inorm
563 logical,
intent(in) :: absolute
564 character(len=32) :: label
566 character(len=5),
parameter :: res_name(3) = [
'force',
'mom ',
'lag ' ]
567 character(len=10),
parameter :: corr_name(3) = [
'disp.corr.',
'rot.corr. ',
'lag.corr. ' ]
569 if( iq == kcnvresidual )
then
570 label =
'res(' // trim(res_name(ig))
571 if( inorm == kcnvmax ) label = trim(label) //
',max'
572 if( absolute ) label = trim(label) //
',abs'
573 label = trim(label) //
')'
575 label = corr_name(ig)
576 if( inorm == kcnvmax ) label = trim(label) //
'(max)'
579 end function fstr_convergence_label
588 type(hecmwst_local_mesh),
intent(in) :: hecmesh
589 type(hecmwst_matrix),
intent(in) :: hecmat
591 integer(kind=kint),
intent(in) :: cstep
592 integer(kind=kint),
intent(in) :: sub_step
593 integer(kind=kint),
intent(out) :: iterstatus
594 integer(kind=kint),
intent(in),
optional :: istat
599 if(
present(istat) )
then
600 if( istat /= 0 )
then
602 fstrsolid%NRstat_i(knstdresn) = 4
607 if( hecmw_mat_get_flag_diverged(hecmat) /=
kno )
then
610 fstrsolid%NRstat_i(knstdresn) = 6
611 else if( hecmw_mat_get_solver_type(hecmat) == 1 .and. &
612 hecmw_mat_get_flag_converged(hecmat) ==
kno )
then
616 fstrsolid%NRstat_i(knstdresn) = 5
622 if( hecmesh%my_rank == 0 )
then
623 write(*,
'(a,i5,a,i5)')
' ### Fail to Converge : at total_step=', cstep,
' sub_step=', sub_step
625 fstrsolid%CutBack_stat = fstrsolid%CutBack_stat + 1
This module provides a unified convergence check for Newton iteration.
subroutine, public fstr_check_convergence_main(hecMESH, hecMAT, fstrSOLID, fstrPR, ndof, iter, cstep, residual_vec, cnvstat, iterStatus, do_failure_check, res_for_check, hecLagMAT)
Core convergence check.
subroutine, public fstr_check_linear_solver(hecMESH, hecMAT, fstrSOLID, cstep, sub_step, iterStatus, istat)
Classify the linear solver result and record why the solve failed.
subroutine, public fstr_check_convergence(hecMESH, hecMAT, fstrSOLID, fstrPR, 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...
This module defines common data and basic structures for analysis.
integer(kind=kint), parameter kitrfloatingerror
integer(kind=kint), parameter kstdynamic
integer(kind=kint), parameter kitrconverged
integer(kind=kint), parameter ilog
FILE HANDLER.
type(fstr_param), target fstrpr
GLOBAL VARIABLE INITIALIZED IN FSTR_SETUP.
integer(kind=kint), parameter kitrcontinue
iteration control
integer(kind=kint), parameter kno
integer(kind=kint), parameter kitrdiverged
FSTR INNER CONTROL PARAMETERS (fstrPARAM)