FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_dynamic_nlexplicit.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  use m_fstr
9  use m_static_lib
16  use m_fstr_update
17  use m_fstr_residual
18  use m_fstr_restart
20  use m_fstr_rcap_io
21  use mcontact
23  use m_fstr_timeinc
24 
25 contains
26 
27  !C================================================================C
28  !C-- subroutine fstr_solve_LINEAR_DYNAMIC
29  !C================================================================C
30  subroutine fstr_solve_dynamic_nlexplicit(hecMESH,hecMAT,fstrSOLID,fstrEIG &
31  ,fstrDYN,fstrRESULT,fstrPARAM,infoCTChange &
32  ,fstrCPL, restrt_step_num, restrt_step_count )
33  implicit none
34  type(hecmwst_local_mesh) :: hecMESH
35  type(hecmwst_matrix) :: hecMAT
36  type(fstr_eigen) :: fstrEIG
37  type(fstr_solid) :: fstrSOLID
38  type(hecmwst_result_data) :: fstrRESULT
39  type(fstr_param) :: fstrPARAM
40  type(fstr_dynamic) :: fstrDYN
41  type(hecmwst_matrix_lagrange) :: hecLagMAT
42  type(fstr_info_contactchange) :: infoCTChange
43  type(fstr_couple) :: fstrCPL !for COUPLE
44  type(hecmwst_matrix), pointer :: hecMATmpc
45  integer(kind=kint), allocatable :: mark(:)
46  integer(kind=kint) :: nnod, ndof, nn, numnp
47  integer(kind=kint) :: i, j, ids, ide, kk
48  integer(kind=kint) :: kkk0, kkk1
49  integer(kind=kint) :: ierror
50  integer(kind=kint) :: iiii5, iexit
51  integer(kind=kint) :: revocap_flag
52  real(kind=kreal), allocatable :: prevb(:)
53  real(kind=kreal) :: bsize, res
54  real(kind=kreal) :: time_1, time_2
55  integer(kind=kint) :: restrt_step_num
56  integer(kind=kint) :: restrt_step_count
57  real(kind=kreal), parameter :: pi = 3.14159265358979323846d0
58  integer(kind=kint) :: tot_step, sub_step, step_count
59  logical :: is_OutPoint
60 
61  call hecmw_mpc_mat_init_explicit(hecmesh, hecmat, hecmatmpc)
62 
63  hecmat%NDOF=hecmesh%n_dof
64  nnod=hecmesh%n_node
65  ndof=hecmat%NDOF
66  nn=ndof*ndof
67 
68  if( fstrparam%fg_couple == 1) then
69  if( fstrparam%fg_couple_type==5 .or. &
70  fstrparam%fg_couple_type==6 ) then
71  allocate( prevb(hecmat%NP*ndof) ,stat=ierror )
72  prevb = 0.0d0
73  if( ierror /= 0 ) then
74  write(idbg,*) 'stop due to allocation error <fstr_solve_NONLINEAR_DYNAMIC, prevB>'
75  write(idbg,*) ' rank = ', hecmesh%my_rank,' ierror = ',ierror
76  call flush(idbg)
77  call hecmw_abort( hecmw_comm_get_comm())
78  endif
79  endif
80  endif
81 
82  fstrsolid%dunode(:) =0.d0
83 
84  call fstr_prepare_dynamic_explicit( hecmesh, hecmat, hecmatmpc, fstrsolid, fstreig, fstrdyn, &
85  & ndof, nnod, restrt_step_count )
86 
87  if( associated( fstrsolid%contacts ) ) then
88  if( ndof /= 3 ) then
89  if( hecmesh%my_rank == 0 ) write(*,*) 'Explicit contact analysis requires three displacement DOFs per node'
90  call hecmw_abort(hecmw_comm_get_comm())
91  endif
92  call initialize_contact_output_vectors(fstrsolid,hecmat)
93  call setup_contact_elesurf_for_area( 1, hecmesh, fstrsolid )
94  call forward_increment_lagrange(1,ndof,fstrdyn%VEC1,hecmesh,fstrsolid,infoctchange,&
95  & fstrsolid%ddunode,restrt_step_count == 0)
96  endif
97 
98  if( restrt_step_count == 0 ) then
99  call fstr_dynamic_output(1, 0, 0.d0, hecmesh, fstrsolid, fstrdyn, fstrparam, .true.)
100  call dynamic_output_monit(1, 0, 0.d0, hecmesh, fstrparam, fstrdyn, fstreig, fstrsolid)
101  end if
102 
103  step_count = restrt_step_count
104  do tot_step = 1, fstrsolid%nstep_tot
105  if(hecmesh%my_rank==0) write(*,'(a,i5)') ' loading step=',tot_step
106 
107  sub_step = restrt_step_num
108  do while(.true.)
109  call fstr_timeinc_settimeincrement( fstrsolid%step_ctrl(tot_step), fstrparam, sub_step, &
110  & fstrsolid%NRstat_i, fstrsolid%NRstat_r, fstrsolid%AutoINC_stat, fstrsolid%CutBack_stat )
111 
112  fstrdyn%t_curr = fstr_get_time()
113  fstrdyn%t_delta = fstr_get_timeinc()
114 
115  step_count = step_count + 1
116 
117  call fstr_advance_dynamic_explicit( tot_step, sub_step, &
118  hecmesh, hecmat, hecmatmpc, fstrsolid, fstreig, fstrdyn, fstrparam, &
119  fstrcpl, infoctchange, &
120  restrt_step_num, ndof, nnod, prevb, &
121  fstr_timeinc_isstepfinished( fstrsolid%step_ctrl(tot_step) ) )
122 
123  ! ----- Result output (include visualize output)
124  ! Evaluate isTimePoint before time advance, then OR with isStepFinished after
125  is_outpoint = fstr_timeinc_istimepoint( fstrsolid%step_ctrl(tot_step), fstrparam )
126 
127  !C-- output result of monitoring node
128  call dynamic_output_monit(tot_step, sub_step, fstrdyn%t_curr, hecmesh, fstrparam, fstrdyn, fstreig, fstrsolid)
129 
130  if( fstrdyn%restart_nout > 0 ) then
131  if ( mod(step_count,fstrdyn%restart_nout).eq.0 ) then
132  call fstr_write_restart_dyna_nl(tot_step,sub_step,hecmesh,fstrsolid,fstrdyn,fstrparam,&
133  .false.,infoctchange%contactNode_current,step_count)
134  end if
135  end if
136 
137  call fstr_proceed_time()
138  fstrdyn%t_curr = fstr_get_time()
139 
140  ! isStepFinished must be evaluated after fstr_proceed_time
141  is_outpoint = is_outpoint .or. fstr_timeinc_isstepfinished( fstrsolid%step_ctrl(tot_step) )
142 
143  !C-- output new displacement, velocity and acceleration
144  call fstr_dynamic_output(tot_step, step_count, fstrdyn%t_curr, hecmesh, fstrsolid, fstrdyn, fstrparam, is_outpoint)
145 
146  if( fstr_timeinc_isstepfinished( fstrsolid%step_ctrl(tot_step) ) ) exit
147 
148  if( sub_step == fstrsolid%step_ctrl(tot_step)%num_substep ) then
149  if( hecmesh%my_rank == 0 ) then
150  write(*,'(a,i5,a,f6.3)') '### Number of substeps reached max number: at total_step=', &
151  & tot_step, ' time=', fstr_get_time()
152  endif
153  call fstr_abort( hecmw_exit_noconv )
154  endif
155 
156  sub_step = sub_step + 1
157  enddo
158 
159  if( fstrdyn%restart_nout > 0 ) then
160  call fstr_write_restart_dyna_nl(tot_step,sub_step,hecmesh,fstrsolid,fstrdyn,fstrparam,&
161  .true.,infoctchange%contactNode_current,step_count)
162  end if
163  restrt_step_num = 1
164  enddo
165 
166  if( fstrparam%fg_couple == 1) then
167  if( fstrparam%fg_couple_type==5 .or. &
168  fstrparam%fg_couple_type==6 ) then
169  deallocate( prevb ,stat=ierror )
170  if( ierror /= 0 ) then
171  write(idbg,*) 'stop due to deallocation error <fstr_solve_NONLINEAR_DYNAMIC, prevB>'
172  write(idbg,*) ' rank = ', hecmesh%my_rank,' ierror = ',ierror
173  call flush(idbg)
174  call hecmw_abort( hecmw_comm_get_comm())
175  endif
176  endif
177  endif
178 
179  call hecmw_mpc_mat_finalize_explicit(hecmesh, hecmat, hecmatmpc)
180 
181  end subroutine fstr_solve_dynamic_nlexplicit
182 
189  subroutine fstr_prepare_dynamic_explicit( hecMESH, hecMAT, hecMATmpc, fstrSOLID, fstrEIG, fstrDYN, &
190  ndof, nnod, restrt_step_count )
191  implicit none
192  type(hecmwst_local_mesh), intent(inout) :: hecMESH
193  type(hecmwst_matrix), intent(inout) :: hecMAT
194  type(hecmwst_matrix), pointer, intent(inout) :: hecMATmpc
195  type(fstr_solid), intent(inout) :: fstrSOLID
196  type(fstr_eigen), intent(inout) :: fstrEIG
197  type(fstr_dynamic), intent(inout) :: fstrDYN
198  integer(kind=kint), intent(in) :: ndof
199  integer(kind=kint), intent(in) :: nnod
200  integer(kind=kint), intent(in) :: restrt_step_count
201 
202  integer(kind=kint), allocatable :: mark(:)
203  integer(kind=kint) :: j
204  real(kind=kreal) :: a1, a2
205 
206  a1 = 1.d0/fstrdyn%t_delta**2
207  a2 = 1.d0/(2.d0*fstrdyn%t_delta)
208 
209  call setmass(fstrsolid,hecmesh,hecmat,fstreig)
210  call hecmw_mpc_trans_mass(hecmesh, hecmat, hecmatmpc, fstreig%mass)
211 
212  allocate(mark(hecmat%NP * hecmat%NDOF))
213  call hecmw_mpc_mark_slave(hecmesh, hecmat, mark)
214 
215  do j = 1 ,ndof*nnod
216  fstrdyn%VEC1(j) = (a1 + a2 *fstrdyn%ray_m) * fstreig%mass(j)
217  if(mark(j) == 1) fstrdyn%VEC1(j) = 1.d0
218  if(dabs(fstrdyn%VEC1(j)) < 1.0e-20) then
219  if( hecmesh%my_rank == 0 ) then
220  write(*,*) 'stop due to fstrDYN%VEC(j) = 0 , j = ', j
221  write(imsg,*) 'stop due to fstrDYN%VEC(j) = 0 , j = ', j
222  end if
223  call hecmw_abort( hecmw_comm_get_comm())
224  endif
225  end do
226 
227  deallocate(mark)
228 
229  !C-- virtual past displacements for central-difference startup
230  if( restrt_step_count == 0 ) then
231  do j = 1 ,ndof*nnod
232  fstrdyn%DISP(j,3) = fstrdyn%DISP(j,1) - fstrdyn%VEL (j,1)/(2.d0*a2) + fstrdyn%ACC (j,1)/ (2.d0*a1)
233  fstrdyn%DISP(j,2) = fstrdyn%DISP(j,1) - fstrdyn%VEL (j,1)/ a2 + fstrdyn%ACC (j,1)/ (2.d0*a1) * 4.d0
234  end do
235  endif
236 
237  end subroutine fstr_prepare_dynamic_explicit
238 
240  subroutine fstr_advance_dynamic_explicit( cstep, istep, &
241  hecMESH, hecMAT, hecMATmpc, fstrSOLID, fstrEIG, fstrDYN, fstrPARAM, &
242  fstrCPL, infoCTChange, &
243  restrt_step_num, ndof, nnod, prevB, &
244  is_last_step )
245  implicit none
246  integer(kind=kint), intent(in) :: cstep
247  integer(kind=kint), intent(in) :: istep
248  type(hecmwst_local_mesh), intent(inout) :: hecMESH
249  type(hecmwst_matrix), intent(inout) :: hecMAT
250  type(hecmwst_matrix), pointer, intent(inout) :: hecMATmpc
251  type(fstr_solid), intent(inout) :: fstrSOLID
252  type(fstr_eigen), intent(inout) :: fstrEIG
253  type(fstr_dynamic), intent(inout) :: fstrDYN
254  type(fstr_param), intent(inout) :: fstrPARAM
255  type(fstr_couple), intent(inout) :: fstrCPL
256  type(fstr_info_contactchange), intent(inout) :: infoCTChange
257  integer(kind=kint), intent(in) :: restrt_step_num
258  integer(kind=kint), intent(in) :: ndof
259  integer(kind=kint), intent(in) :: nnod
260  real(kind=kreal), allocatable, intent(inout) :: prevb(:)
261  logical, intent(in) :: is_last_step
262 
263  integer(kind=kint) :: j, kk, kkk0, kkk1
264  integer(kind=kint) :: revocap_flag
265  real(kind=kreal) :: bsize
266  real(kind=kreal), parameter :: pi = 3.14159265358979323846d0
267  real(kind=kreal) :: a1, a2
268  real(kind=kreal) :: b1, b2, b3, a3
269 
270  !C-- central-difference coefficients (depend only on dt)
271  a1 = 1.d0/fstrdyn%t_delta**2
272  a2 = 1.d0/(2.d0*fstrdyn%t_delta)
273  !C-- coupling-only coefficients (kept zero for central difference)
274  a3 = 0.d0
275  b1 = 0.d0; b2 = 0.d0; b3 = 0.d0
276 
277  !C-- mechanical boundary condition
278  call dynamic_mat_ass_load (cstep, fstrdyn%t_curr, hecmesh, hecmat, fstrsolid, fstrdyn, fstrparam)
279  do j=1, hecmesh%n_node* hecmesh%n_dof
280  hecmat%B(j)=hecmat%B(j)-fstrsolid%QFORCE(j)
281  end do
282 
283  !C ********************************************************************************
284  !C for couple analysis
285  if( fstrparam%fg_couple == 1 ) then
286  if( fstrparam%fg_couple_type==5 .or. &
287  fstrparam%fg_couple_type==6 ) then
288  do j = 1, hecmat%NP * ndof
289  prevb(j) = hecmat%B(j)
290  enddo
291  endif
292  endif
293  do
294  if( fstrparam%fg_couple == 1 ) then
295  if( fstrparam%fg_couple_type==1 .or. &
296  fstrparam%fg_couple_type==3 .or. &
297  fstrparam%fg_couple_type==5 ) call fstr_rcap_get( fstrcpl )
298  if( fstrparam%fg_couple_first /= 0 ) then
299  bsize = dfloat( istep ) / dfloat( fstrparam%fg_couple_first )
300  if( bsize > 1.0 ) bsize = 1.0
301  do kkk0 = 1, fstrcpl%coupled_node_n
302  kkk1 = 3 * kkk0
303  fstrcpl%trac(kkk1-2) = bsize * fstrcpl%trac(kkk1-2)
304  fstrcpl%trac(kkk1-1) = bsize * fstrcpl%trac(kkk1-1)
305  fstrcpl%trac(kkk1 ) = bsize * fstrcpl%trac(kkk1 )
306  enddo
307  endif
308  if( fstrparam%fg_couple_window > 0 ) then
309  j = istep - restrt_step_num + 1
310  kk = fstrdyn%n_step - restrt_step_num + 1
311  bsize = 0.5*(1.0-cos(2.0*pi*dfloat(j)/dfloat(kk)))
312  do kkk0 = 1, fstrcpl%coupled_node_n
313  kkk1 = 3 * kkk0
314  fstrcpl%trac(kkk1-2) = bsize * fstrcpl%trac(kkk1-2)
315  fstrcpl%trac(kkk1-1) = bsize * fstrcpl%trac(kkk1-1)
316  fstrcpl%trac(kkk1 ) = bsize * fstrcpl%trac(kkk1 )
317  enddo
318  endif
319  call dynamic_mat_ass_couple( hecmesh, hecmat, fstrsolid, fstrcpl )
320  endif
321  !C ********************************************************************************
322 
323  call hecmw_mpc_trans_rhs(hecmesh, hecmat, hecmatmpc)
324 
325  do j = 1 ,ndof*nnod
326  hecmatmpc%B(j) = hecmatmpc%B(j) + 2.d0*a1* fstreig%mass(j) * fstrdyn%DISP(j,1) &
327  + (- a1 + a2 * fstrdyn%ray_m) * fstreig%mass(j) * fstrdyn%DISP(j,3)
328  end do
329 
330  !C
331  !C-- geometrical boundary condition
332 
333  call dynamic_explicit_ass_bc(hecmesh, hecmatmpc, fstrsolid, fstrdyn, fstrdyn%t_curr)
334  call dynamic_explicit_ass_vl(hecmesh, hecmatmpc, fstrsolid, fstrdyn, fstrdyn%t_curr)
335  call dynamic_explicit_ass_ac(hecmesh, hecmatmpc, fstrsolid, fstrdyn, fstrdyn%t_curr)
336 
337  ! Finish the calculation
338  do j = 1 ,ndof*nnod
339  hecmatmpc%X(j) = hecmatmpc%B(j) / fstrdyn%VEC1(j)
340  if(dabs(hecmatmpc%X(j)) > 1.0d+5) then
341  if( hecmesh%my_rank == 0 ) then
342  print *, 'Displacement increment too large, please adjust your step size!',istep,hecmatmpc%X(j)
343  write(imsg,*) 'Displacement increment too large, please adjust your step size!',istep,hecmatmpc%B(j),fstrdyn%VEC1(j)
344  end if
345  call fstr_abort( hecmw_exit_noconv )
346  end if
347  end do
348  call hecmw_mpc_tback_sol(hecmesh, hecmat, hecmatmpc)
349 
350  !C *****************************************************
351  !C for couple analysis
352  if( fstrparam%fg_couple == 1 ) then
353  if( fstrparam%fg_couple_type>1 ) then
354  do j=1, fstrcpl%coupled_node_n
355  if( fstrcpl%dof == 3 ) then
356  kkk0 = j*3
357  kkk1 = fstrcpl%coupled_node(j)*3
358 
359  fstrcpl%disp (kkk0-2) = hecmat%X(kkk1-2)
360  fstrcpl%disp (kkk0-1) = hecmat%X(kkk1-1)
361  fstrcpl%disp (kkk0 ) = hecmat%X(kkk1 )
362 
363  fstrcpl%velo (kkk0-2) = -b1*fstrdyn%ACC(kkk1-2,1) - b2*fstrdyn%VEL(kkk1-2,1) + &
364  b3*( hecmat%X(kkk1-2) - fstrdyn%DISP(kkk1-2,1) )
365  fstrcpl%velo (kkk0-1) = -b1*fstrdyn%ACC(kkk1-1,1) - b2*fstrdyn%VEL(kkk1-1,1) + &
366  b3*( hecmat%X(kkk1-1) - fstrdyn%DISP(kkk1-1,1) )
367  fstrcpl%velo (kkk0 ) = -b1*fstrdyn%ACC(kkk1,1) - b2*fstrdyn%VEL(kkk1,1) + &
368  b3*( hecmat%X(kkk1) - fstrdyn%DISP(kkk1,1) )
369  fstrcpl%accel(kkk0-2) = -a1*fstrdyn%ACC(kkk1-2,1) - a2*fstrdyn%VEL(kkk1-2,1) + &
370  a3*( hecmat%X(kkk1-2) - fstrdyn%DISP(kkk1-2,1) )
371  fstrcpl%accel(kkk0-1) = -a1*fstrdyn%ACC(kkk1-1,1) - a2*fstrdyn%VEL(kkk1-1,1) + &
372  a3*( hecmat%X(kkk1-1) - fstrdyn%DISP(kkk1-1,1) )
373  fstrcpl%accel(kkk0 ) = -a1*fstrdyn%ACC(kkk1,1) - a2*fstrdyn%VEL(kkk1,1) + &
374  a3*( hecmat%X(kkk1) - fstrdyn%DISP(kkk1,1) )
375  else
376  kkk0 = j*2
377  kkk1 = fstrcpl%coupled_node(j)*2
378 
379  fstrcpl%disp (kkk0-1) = hecmat%X(kkk1-1)
380  fstrcpl%disp (kkk0 ) = hecmat%X(kkk1 )
381 
382  fstrcpl%velo (kkk0-1) = -b1*fstrdyn%ACC(kkk1-1,1) - b2*fstrdyn%VEL(kkk1-1,1) + &
383  b3*( hecmat%X(kkk1-1) - fstrdyn%DISP(kkk1-1,1) )
384  fstrcpl%velo (kkk0 ) = -b1*fstrdyn%ACC(kkk1,1) - b2*fstrdyn%VEL(kkk1,1) + &
385  b3*( hecmat%X(kkk1) - fstrdyn%DISP(kkk1,1) )
386  fstrcpl%accel(kkk0-1) = -a1*fstrdyn%ACC(kkk1-1,1) - a2*fstrdyn%VEL(kkk1-1,1) + &
387  a3*( hecmat%X(kkk1-1) - fstrdyn%DISP(kkk1-1,1) )
388  fstrcpl%accel(kkk0 ) = -a1*fstrdyn%ACC(kkk1,1) - a2*fstrdyn%VEL(kkk1,1) + &
389  a3*( hecmat%X(kkk1) - fstrdyn%DISP(kkk1,1) )
390  endif
391  end do
392  call fstr_rcap_send( fstrcpl )
393  endif
394 
395  select case ( fstrparam%fg_couple_type )
396  case (4)
397  call fstr_rcap_get( fstrcpl )
398  case (5)
399  call fstr_get_convergence( revocap_flag )
400  if( revocap_flag==0 ) then
401  do j = 1, hecmat%NP * ndof
402  hecmat%B(j) = prevb(j)
403  enddo
404  cycle
405  endif
406  case (6)
407  call fstr_get_convergence( revocap_flag )
408  if( revocap_flag==0 ) then
409  do j = 1, hecmat%NP * ndof
410  hecmat%B(j) = prevb(j)
411  enddo
412  call fstr_rcap_get( fstrcpl )
413  cycle
414  else
415  if( .not. is_last_step ) call fstr_rcap_get( fstrcpl )
416  endif
417  end select
418  endif
419  exit
420  enddo
421 
422  !C *****************************************************
423  !C-- contact corrector
424  !C
425  do j = 1 ,ndof*nnod
426  fstrsolid%unode(j) = fstrdyn%DISP(j,1)
427  fstrsolid%dunode(j) = hecmat%X(j)-fstrdyn%DISP(j,1)
428  enddo
429  if( associated( fstrsolid%contacts ) ) then
430  !call fstr_scan_contact_state( cstep, fstrDYN%t_delta, kcaSLAGRANGE, hecMESH, fstrSOLID, infoCTChange )
431  call forward_increment_lagrange(cstep,ndof,fstrdyn%VEC1,hecmesh,fstrsolid,infoctchange,&
432  & fstrsolid%ddunode,.false.)
433  do j = 1 ,ndof*nnod
434  hecmat%X(j) = hecmat%X(j) + fstrsolid%ddunode(j)
435  enddo
436  endif
437 
438  !C-- new displacement, velocity and acceleration
439  do j = 1 ,ndof*nnod
440  fstrdyn%ACC (j,1) = a1*(hecmat%X(j) - 2.d0*fstrdyn%DISP(j,1) + fstrdyn%DISP(j,3))
441  fstrdyn%VEL (j,1) = a2*(hecmat%X(j) - fstrdyn%DISP(j,3))
442  fstrsolid%unode(j) = fstrdyn%DISP(j,1)
443  fstrsolid%dunode(j) = hecmat%X(j)-fstrdyn%DISP(j,1)
444  fstrdyn%DISP(j,3) = fstrdyn%DISP(j,1)
445  fstrdyn%DISP(j,1) = hecmat%X(j)
446  hecmat%X(j) = fstrsolid%dunode(j)
447  fstrdyn%kineticEnergy = fstrdyn%kineticEnergy + 0.5d0*fstreig%mass(j)*fstrdyn%VEL(j,1)*fstrdyn%VEL(j,1)
448  end do
449 
450  ! ----- update strain, stress, and internal force
451  call fstr_updatenewton( hecmesh, hecmat, fstrsolid, fstrdyn%t_curr, fstrdyn%t_delta, 0, fstrdyn%strainEnergy )
452 
453  ! ----- update reaction force at constrained DOFs using converged QFORCE
454  call fstr_update_reaction_spc( cstep, hecmesh, fstrsolid )
455 
456  do j = 1 ,ndof*nnod
457  fstrsolid%unode(j) = fstrsolid%unode(j) + fstrsolid%dunode(j)
458  end do
459  call fstr_updatestate( hecmesh, fstrsolid, fstrdyn%t_delta )
460 
461  end subroutine fstr_advance_dynamic_explicit
462 
463 
464  subroutine forward_increment_lagrange(cstep,ndof,mmat,hecMESH,fstrSOLID,infoCTChange,uc,is_init)
465  integer, intent(in) :: cstep
466  integer, intent(in) :: ndof
467  real(kind=kreal), intent(in) :: mmat(:)
468  type( hecmwst_local_mesh ), intent(in) :: hecmesh
469  type(fstr_solid), intent(inout) :: fstrSOLID
470  type(fstr_info_contactchange) :: infoCTChange
471  real(kind=kreal), intent(out) :: uc(:)
472  logical, intent(in) :: is_init
473  integer :: i, j, k, slave, nn, iSS, sid, iter, offset
474  real(kind=kreal), allocatable :: contact_force(:), friction_force(:), compliance(:)
475  real(kind=kreal) :: fdum, conv, dlambda, rel_t(3), tangent(3), friction(3)
476  real(kind=kreal) :: tangent_compliance, friction_limit, friction_norm, rel_t_norm
477  real(kind=kreal) :: element_disp(3*(l_max_surface_node+1))
478  real(kind=kreal) :: tm(3,3*(l_max_surface_node+1)), tt(3,3*(l_max_surface_node+1))
479  real(kind=kreal) :: bn(3*(l_max_surface_node+1))
480  integer, parameter :: MAX_CONTACT_ITER = 1000
481 
482  uc = 0.d0
483  call fstr_scan_contact_state_exp( cstep, is_init, hecmesh, fstrsolid, infoctchange )
484  if( .not. infoctchange%active ) return
485 
486  allocate(contact_force(hecmesh%n_node*ndof), friction_force(hecmesh%n_node*ndof), &
487  compliance(hecmesh%n_node*ndof))
488  compliance = 1.d0/mmat
489  call mask_explicit_contact_constraints(ndof, hecmesh, fstrsolid, compliance)
490 
491  do i=1,fstrsolid%n_contacts
492  do j=1,size(fstrsolid%contacts(i)%slave)
493  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
494  fstrsolid%contacts(i)%states(j)%multiplier(:) = 0.d0
495  fstrsolid%contacts(i)%states(j)%wkdist = 0.d0
496  enddo
497  enddo
498 
499  iter = 0
500  do
501  contact_force = 0.d0
502  do i=1,fstrsolid%n_contacts
503  do j= 1, size(fstrsolid%contacts(i)%slave)
504  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
505  if( fstrsolid%contacts(i)%states(j)%distance>epsilon(1.d0) ) then
506  fstrsolid%contacts(i)%states(j)%state = contactfree
507  cycle
508  endif
509  slave = fstrsolid%contacts(i)%slave(j)
510  sid = fstrsolid%contacts(i)%states(j)%surface
511  nn = size( fstrsolid%contacts(i)%master(sid)%nodes )
512  if( nn > l_max_surface_node ) then
513  if( hecmesh%my_rank == 0 ) write(*,*) 'Too many nodes on explicit contact surface:', nn
514  call hecmw_abort(hecmw_comm_get_comm())
515  endif
516  call computetm_tt(fstrsolid%contacts(i)%states(j), fstrsolid%contacts(i)%master(sid), &
517  0.d0, tm, tt, fstrsolid%contacts(i)%smoothing, bn)
518  offset = (slave-1)*ndof
519  contact_force(offset+1:offset+3) = contact_force(offset+1:offset+3) &
520  + fstrsolid%contacts(i)%states(j)%multiplier(1)*bn(1:3)
521  do k=1,nn
522  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
523  offset = (iss-1)*ndof
524  contact_force(offset+1:offset+3) = contact_force(offset+1:offset+3) &
525  + fstrsolid%contacts(i)%states(j)%multiplier(1)*bn(3*k+1:3*k+3)
526  enddo
527  enddo
528  enddo
529 
530  call hecmw_assemble_r(hecmesh, contact_force, hecmesh%n_node, ndof)
531  call hecmw_update_r(hecmesh, contact_force, hecmesh%n_node, ndof)
532 
533  conv = 0.d0
534  do i=1,fstrsolid%n_contacts
535  do j= 1, size(fstrsolid%contacts(i)%slave)
536  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
537  slave = fstrsolid%contacts(i)%slave(j)
538  sid = fstrsolid%contacts(i)%states(j)%surface
539  nn = size( fstrsolid%contacts(i)%master(sid)%nodes )
540  call computetm_tt(fstrsolid%contacts(i)%states(j), fstrsolid%contacts(i)%master(sid), &
541  0.d0, tm, tt, fstrsolid%contacts(i)%smoothing, bn)
542  offset = (slave-1)*ndof
543  fstrsolid%contacts(i)%states(j)%wkdist = &
544  dot_product(bn(1:3), contact_force(offset+1:offset+3)*compliance(offset+1:offset+3))
545  fdum = dot_product(bn(1:3), bn(1:3)*compliance(offset+1:offset+3))
546  do k=1,nn
547  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
548  offset = (iss-1)*ndof
549  fstrsolid%contacts(i)%states(j)%wkdist = fstrsolid%contacts(i)%states(j)%wkdist &
550  + dot_product(bn(3*k+1:3*k+3), contact_force(offset+1:offset+3)*compliance(offset+1:offset+3))
551  fdum = fdum + dot_product(bn(3*k+1:3*k+3), bn(3*k+1:3*k+3)*compliance(offset+1:offset+3))
552  enddo
553  dlambda = 0.d0
554  if( fdum > 1.d-20 ) &
555  dlambda = (fstrsolid%contacts(i)%states(j)%distance-fstrsolid%contacts(i)%states(j)%wkdist)/fdum
556  conv = conv + dlambda*dlambda
557  fstrsolid%contacts(i)%states(j)%multiplier(1) = fstrsolid%contacts(i)%states(j)%multiplier(1) + dlambda
558  enddo
559  enddo
560  call hecmw_allreduce_r1(hecmesh, conv, hecmw_sum)
561  iter = iter+1
562  if( dsqrt(conv)<1.d-8 ) exit
563  if( iter >= max_contact_iter ) then
564  if( hecmesh%my_rank == 0 ) write(*,*) 'Explicit contact correction failed to converge'
565  call hecmw_abort(hecmw_comm_get_comm())
566  endif
567  enddo
568 
569  contact_force = 0.d0
570  do i=1,fstrsolid%n_contacts
571  do j=1,size(fstrsolid%contacts(i)%slave)
572  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
573  slave = fstrsolid%contacts(i)%slave(j)
574  sid = fstrsolid%contacts(i)%states(j)%surface
575  nn = size(fstrsolid%contacts(i)%master(sid)%nodes)
576  call computetm_tt(fstrsolid%contacts(i)%states(j), fstrsolid%contacts(i)%master(sid), &
577  0.d0, tm, tt, fstrsolid%contacts(i)%smoothing, bn)
578  offset = (slave-1)*ndof
579  contact_force(offset+1:offset+3) = contact_force(offset+1:offset+3) &
580  + fstrsolid%contacts(i)%states(j)%multiplier(1)*bn(1:3)
581  do k=1,nn
582  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
583  offset = (iss-1)*ndof
584  contact_force(offset+1:offset+3) = contact_force(offset+1:offset+3) &
585  + fstrsolid%contacts(i)%states(j)%multiplier(1)*bn(3*k+1:3*k+3)
586  enddo
587  enddo
588  enddo
589  call hecmw_assemble_r(hecmesh, contact_force, hecmesh%n_node, ndof)
590  call hecmw_update_r(hecmesh, contact_force, hecmesh%n_node, ndof)
591 
592  do i=1,hecmesh%n_node*ndof
593  uc(i) = contact_force(i)*compliance(i)
594  enddo
595 
596  friction_force = 0.d0
597  do i=1,fstrsolid%n_contacts
598  do j=1,size(fstrsolid%contacts(i)%slave)
599  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
600  if( fstrsolid%contacts(i)%fcoeff <= 0.d0 ) then
601  fstrsolid%contacts(i)%states(j)%tangentForce_final(:) = 0.d0
602  fstrsolid%contacts(i)%states(j)%reldisp(:) = 0.d0
603  cycle
604  endif
605 
606  slave = fstrsolid%contacts(i)%slave(j)
607  sid = fstrsolid%contacts(i)%states(j)%surface
608  nn = size(fstrsolid%contacts(i)%master(sid)%nodes)
609  call computetm_tt(fstrsolid%contacts(i)%states(j), fstrsolid%contacts(i)%master(sid), &
610  fstrsolid%contacts(i)%fcoeff, tm, tt, fstrsolid%contacts(i)%smoothing)
611 
612  offset = (slave-1)*ndof
613  element_disp(1:3) = fstrsolid%dunode(offset+1:offset+3) + uc(offset+1:offset+3)
614  do k=1,nn
615  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
616  offset = (iss-1)*ndof
617  element_disp(3*k+1:3*k+3) = fstrsolid%dunode(offset+1:offset+3) + uc(offset+1:offset+3)
618  enddo
619  rel_t = matmul(tt(1:3,1:3*(nn+1)), element_disp(1:3*(nn+1)))
620  fstrsolid%contacts(i)%states(j)%reldisp(:) = rel_t
621 
622  rel_t_norm = dsqrt(dot_product(rel_t,rel_t))
623  friction = 0.d0
624  if( rel_t_norm > 1.d-20 ) then
625  tangent = rel_t/rel_t_norm
626  offset = (slave-1)*ndof
627  tangent_compliance = sum(matmul(tangent,tt(1:3,1:3))**2*compliance(offset+1:offset+3))
628  do k=1,nn
629  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
630  offset = (iss-1)*ndof
631  tangent_compliance = tangent_compliance &
632  + sum(matmul(tangent,tt(1:3,3*k+1:3*k+3))**2*compliance(offset+1:offset+3))
633  enddo
634  if( tangent_compliance > 1.d-20 ) friction = rel_t/tangent_compliance
635  endif
636 
637  friction_limit = fstrsolid%contacts(i)%fcoeff &
638  * dabs(fstrsolid%contacts(i)%states(j)%multiplier(1))
639  friction_norm = dsqrt(dot_product(friction,friction))
640  if( friction_norm > friction_limit .and. friction_norm > 1.d-20 ) then
641  friction = friction*(friction_limit/friction_norm)
642  fstrsolid%contacts(i)%states(j)%state = contactslip
643  else
644  fstrsolid%contacts(i)%states(j)%state = contactstick
645  endif
646  friction_norm = dsqrt(dot_product(friction,friction))
647  fstrsolid%contacts(i)%states(j)%tangentForce_final(:) = friction
648  fstrsolid%contacts(i)%states(j)%multiplier(2) = friction_norm
649  fstrsolid%contacts(i)%states(j)%multiplier(3) = 0.d0
650 
651  offset = (slave-1)*ndof
652  friction_force(offset+1:offset+3) = friction_force(offset+1:offset+3) &
653  - matmul(transpose(tm(1:3,1:3)), friction)
654  do k=1,nn
655  iss = fstrsolid%contacts(i)%master(sid)%nodes(k)
656  offset = (iss-1)*ndof
657  friction_force(offset+1:offset+3) = friction_force(offset+1:offset+3) &
658  - matmul(transpose(tm(1:3,3*k+1:3*k+3)), friction)
659  enddo
660  enddo
661  enddo
662  call hecmw_assemble_r(hecmesh, friction_force, hecmesh%n_node, ndof)
663  call hecmw_update_r(hecmesh, friction_force, hecmesh%n_node, ndof)
664  do i=1,hecmesh%n_node*ndof
665  uc(i) = (contact_force(i)+friction_force(i))*compliance(i)
666  enddo
667 
668  call fstr_update_contact_tangentforce(cstep, fstrsolid)
669  deallocate(contact_force, friction_force, compliance)
670  end subroutine forward_increment_lagrange
671 
672  subroutine mask_explicit_contact_constraints(ndof, hecMESH, fstrSOLID, compliance)
673  integer(kind=kint), intent(in) :: ndof
674  type(hecmwst_local_mesh), intent(in) :: hecMESH
675  type(fstr_solid), intent(in) :: fstrSOLID
676  real(kind=kreal), intent(inout) :: compliance(:)
677  integer(kind=kint) :: ig0, ig, ityp, idofS, idofE, iS0, iE0, ik, node, idof
678 
679  do ig0=1,fstrsolid%BOUNDARY_ngrp_tot
680  ig = fstrsolid%BOUNDARY_ngrp_ID(ig0)
681  ityp = fstrsolid%BOUNDARY_ngrp_type(ig0)
682  idofs = ityp/10
683  idofe = ityp-idofs*10
684  if( fstrsolid%BOUNDARY_ngrp_rotID(ig0) > 0 ) then
685  idofs = 1
686  idofe = ndof
687  endif
688  is0 = hecmesh%node_group%grp_index(ig-1)+1
689  ie0 = hecmesh%node_group%grp_index(ig)
690  do ik=is0,ie0
691  node = hecmesh%node_group%grp_item(ik)
692  do idof=idofs,min(idofe,ndof)
693  compliance((node-1)*ndof+idof) = 0.d0
694  enddo
695  enddo
696  enddo
697 
698  if( fstrsolid%VELOCITY_type /= kbcinitial ) then
699  do ig0=1,fstrsolid%VELOCITY_ngrp_tot
700  ig = fstrsolid%VELOCITY_ngrp_ID(ig0)
701  ityp = fstrsolid%VELOCITY_ngrp_type(ig0)
702  idofs = ityp/10
703  idofe = ityp-idofs*10
704  if( fstrsolid%VELOCITY_ngrp_rotID(ig0) > 0 ) then
705  idofs = 1
706  idofe = ndof
707  endif
708  is0 = hecmesh%node_group%grp_index(ig-1)+1
709  ie0 = hecmesh%node_group%grp_index(ig)
710  do ik=is0,ie0
711  node = hecmesh%node_group%grp_item(ik)
712  do idof=idofs,min(idofe,ndof)
713  compliance((node-1)*ndof+idof) = 0.d0
714  enddo
715  enddo
716  enddo
717  endif
718 
719  if( fstrsolid%ACCELERATION_type /= kbcinitial ) then
720  do ig0=1,fstrsolid%ACCELERATION_ngrp_tot
721  ig = fstrsolid%ACCELERATION_ngrp_ID(ig0)
722  ityp = fstrsolid%ACCELERATION_ngrp_type(ig0)
723  idofs = ityp/10
724  idofe = ityp-idofs*10
725  is0 = hecmesh%node_group%grp_index(ig-1)+1
726  ie0 = hecmesh%node_group%grp_index(ig)
727  do ik=is0,ie0
728  node = hecmesh%node_group%grp_item(ik)
729  do idof=idofs,min(idofe,ndof)
730  compliance((node-1)*ndof+idof) = 0.d0
731  enddo
732  enddo
733  enddo
734  endif
735  end subroutine mask_explicit_contact_constraints
736 
737 end module fstr_dynamic_nlexplicit
This module contains subroutines for nonlinear explicit dynamic analysis.
subroutine forward_increment_lagrange(cstep, ndof, mmat, hecMESH, fstrSOLID, infoCTChange, uc, is_init)
subroutine fstr_solve_dynamic_nlexplicit(hecMESH, hecMAT, fstrSOLID, fstrEIG, fstrDYN, fstrRESULT, fstrPARAM, infoCTChange, fstrCPL, restrt_step_num, restrt_step_count)
subroutine fstr_advance_dynamic_explicit(cstep, istep, hecMESH, hecMAT, hecMATmpc, fstrSOLID, fstrEIG, fstrDYN, fstrPARAM, fstrCPL, infoCTChange, restrt_step_num, ndof, nnod, prevB, is_last_step)
Advance one time step of explicit dynamic analysis.
subroutine fstr_prepare_dynamic_explicit(hecMESH, hecMAT, hecMATmpc, fstrSOLID, fstrEIG, fstrDYN, ndof, nnod, restrt_step_count)
Prepare initial state for explicit dynamic analysis (central difference).
subroutine mask_explicit_contact_constraints(ndof, hecMESH, fstrSOLID, compliance)
This module contains functions to set acceleration boundary condition in dynamic analysis.
subroutine dynamic_explicit_ass_ac(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, t_curr, iter)
This module contains functions to set velocity boundary condition in dynamic analysis.
subroutine dynamic_explicit_ass_vl(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, t_curr, iter)
This module contains functions to set displacement boundary condition in dynamic analysis.
subroutine dynamic_explicit_ass_bc(hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, t_curr, iter)
This subroutine setup disp boundary condition.
This module contains functions relates to coupling analysis.
subroutine dynamic_mat_ass_couple(hecMESH, hecMAT, fstrSOLID, fstrCPL)
This module contains function to set boundary condition of external load in dynamic analysis.
subroutine dynamic_mat_ass_load(cstep, t_curr, hecMESH, hecMAT, fstrSOLID, fstrDYNAMIC, fstrPARAM, iter)
This function sets boundary condition of external load.
This module provides functions to output result.
subroutine fstr_dynamic_output(cstep, istep, t_curr, hecMESH, fstrSOLID, fstrDYNAMIC, fstrPARAM, outflag)
Output result.
subroutine dynamic_output_monit(cstep, istep, t_curr, hecMESH, fstrPARAM, fstrDYNAMIC, fstrEIG, fstrSOLID)
Common utilities for contact element calculations.
subroutine, public computetm_tt(ctState, tSurf, fcoeff, Tm, Tt, smoothing_type, Bn)
Compute Tm (relative displacement mapping) and optionally Tt (tangential mapping) This subroutine con...
Set up lumped mass matrix.
subroutine setmass(fstrSOLID, hecMESH, hecMAT, fstrEIG)
subroutine, public fstr_rcap_send(fstrCPL)
subroutine, public fstr_rcap_get(fstrCPL)
subroutine fstr_get_convergence(revocap_flag)
This module provides function to calculate residual of nodal force.
subroutine, public fstr_update_reaction_spc(cstep, hecMESH, fstrSOLID)
Set fstrSOLIDREACTION at constrained DOFs using current fstrSOLIDQFORCE. Constrained DOFs are enumera...
This module provides functions to read in and write out restart files.
Definition: fstr_Restart.f90:8
subroutine fstr_write_restart_dyna_nl(cstep, substep, hecMESH, fstrSOLID, fstrDYNAMIC, fstrPARAM, is_StepFinished, contactNode, step_count)
write out restart file for nonlinear dynamic analysis
This module provides functions to deal with time and increment of stress analysis.
real(kind=kreal) function fstr_get_timeinc()
logical function fstr_timeinc_istimepoint(stepinfo, fstrPARAM)
subroutine fstr_timeinc_settimeincrement(stepinfo, fstrPARAM, substep, NRstatI, NRstatR, AutoINC_stat, Cutback_stat)
real(kind=kreal) function fstr_get_time()
subroutine fstr_proceed_time()
logical function fstr_timeinc_isstepfinished(stepinfo)
This module provides function to calculate to do updates.
Definition: fstr_Update.f90:6
subroutine fstr_updatestate(hecMESH, fstrSOLID, tincr)
Update elastiplastic status.
subroutine fstr_updatenewton(hecMESH, hecMAT, fstrSOLID, time, tincr, iter, strainEnergy)
Update displacement, stress, strain and internal forces.
Definition: fstr_Update.f90:28
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
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 kbcinitial
Definition: m_fstr.F90:69
This modules just summarizes all modules used in static analysis.
Definition: static_LIB.f90:6
Top-level contact analysis module (System level)
subroutine fstr_scan_contact_state_exp(cstep, is_init, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
subroutine fstr_update_contact_tangentforce(cstep, fstrSOLID)
Update tangent force.
Data for coupling analysis.
Definition: m_fstr.F90:651
Data for DYNAMIC ANSLYSIS (fstrDYNAMIC)
Definition: m_fstr.F90:544
Package of data used by Lanczos eigenvalue solver.
Definition: m_fstr.F90:632
FSTR INNER CONTROL PARAMETERS (fstrPARAM)
Definition: m_fstr.F90:161