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