FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_contact.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 !-------------------------------------------------------------------------------
33 module mcontact
34 
35  use mcontactdef
36  use hecmw
37  use m_fstr
44  implicit none
45 
46  logical, private :: active
47 
48  ! Re-export functions from sub-modules
50  public :: initialize_embed_vectors
52  public :: calc_contact_area
57 
58 contains
59 
60  subroutine fstr_addcontactstiffness(cstep,ctAlgo, iter,hecMESH,conMAT,hecLagMAT,fstrSOLID)
61 
62  integer(kind=kint) :: cstep
63  integer(kind=kint) :: ctAlgo
64  integer(kind=kint) :: iter
65  type(hecmwst_local_mesh) :: hecMESH
66  type(hecmwst_matrix) :: conMAT
67  type(fstr_solid) :: fstrSOLID
68  type(hecmwst_matrix_lagrange) :: hecLagMAT
69  integer(kind=kint) :: i, grpid
70 
71  if( associated(heclagmat%AL_lagrange) ) heclagmat%AL_lagrange = 0.0d0
72  if( associated(heclagmat%AU_lagrange) ) heclagmat%AU_lagrange = 0.0d0
73 
74  do i = 1, fstrsolid%n_contacts
75 
76  grpid = fstrsolid%contacts(i)%group
77  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
78 
79  if( fstrsolid%contacts(i)%method == contacts2s ) then
80  call calcu_contact_stiffness_surfsurf( ctalgo, fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
81  fstrsolid%dunode(:), conmat )
82  else
83  call calcu_contact_stiffness_nodesurf( ctalgo, fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
84  fstrsolid%dunode(:), iter, heclagmat%Lagrange(:), conmat, heclagmat)
85  endif
86  enddo
87 
88  do i = 1, fstrsolid%n_embeds
89 
90  grpid = fstrsolid%embeds(i)%group
91  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) cycle
92 
93  call calcu_contact_stiffness_nodesurf( ctalgo, fstrsolid%embeds(i), hecmesh%node(:), fstrsolid%unode(:), &
94  fstrsolid%dunode(:), iter, heclagmat%Lagrange(:), conmat, heclagmat)
95 
96  enddo
97 
98  end subroutine fstr_addcontactstiffness
99 
101  subroutine fstr_update_ndforce_contact(cstep,ctAlgo,hecMESH,hecLagMAT,fstrSOLID,conMAT)
102  integer(kind=kint), intent(in) :: cstep
103  integer(kind=kint), intent(in) :: ctAlgo
104  type(hecmwst_local_mesh) :: hecMESH
105  type(fstr_solid) :: fstrSOLID
106  type(hecmwst_matrix_lagrange) :: hecLagMAT
107  type(hecmwst_matrix) :: conMAT
108 
109  call fstr_contact_ndforce_core(kctforresidual,cstep,ctalgo,hecmesh,heclagmat,fstrsolid,conmat)
110 
111  end subroutine fstr_update_ndforce_contact
112 
114  subroutine fstr_calc_contact_output_force(cstep,ctAlgo,hecMESH,hecLagMAT,fstrSOLID,conMAT)
115  integer(kind=kint), intent(in) :: cstep
116  integer(kind=kint), intent(in) :: ctAlgo
117  type(hecmwst_local_mesh) :: hecMESH
118  type(fstr_solid) :: fstrSOLID
119  type(hecmwst_matrix_lagrange) :: hecLagMAT
120  type(hecmwst_matrix) :: conMAT
121 
122  call fstr_contact_ndforce_core(kctforoutput,cstep,ctalgo,hecmesh,heclagmat,fstrsolid,conmat)
123 
124  end subroutine fstr_calc_contact_output_force
125 
135  subroutine fstr_calc_contact_output_force_exp( hecMESH, fstrSOLID )
136  type(hecmwst_local_mesh), intent(in) :: hecmesh
137  type(fstr_solid), intent(inout) :: fstrsolid
138 
139  integer(kind=kint) :: i
140 
141  if( .not. associated(fstrsolid%CONT_NFORCE) ) return
142  fstrsolid%CONT_NFORCE(:) = 0.d0
143  if( associated(fstrsolid%CONT_FRIC) ) fstrsolid%CONT_FRIC(:) = 0.d0
144 
145  do i = 1, fstrsolid%n_contacts
146  call calcu_contact_ndforce_exp( fstrsolid%contacts(i), hecmesh%node(:), &
147  fstrsolid%unode(:), fstrsolid%dunode(:), fstrsolid%CONT_NFORCE, fstrsolid%CONT_FRIC )
148  enddo
149 
151 
155  subroutine fstr_contact_ndforce_core(purpose,cstep,ctAlgo,hecMESH,hecLagMAT,fstrSOLID,conMAT)
156  integer(kind=kint), intent(in) :: purpose
157  integer(kind=kint), intent(in) :: cstep
158  integer(kind=kint), intent(in) :: ctAlgo
159  type(hecmwst_local_mesh) :: hecMESH
160  type(fstr_solid) :: fstrSOLID
161  type(hecmwst_matrix_lagrange) :: hecLagMAT
162  type(hecmwst_matrix) :: conMAT
163  integer(kind=kint) :: i, grpid
164 
165  ! Zero-clear output arrays only when computing for output
166  if( purpose == kctforoutput ) then
167  if( associated(fstrsolid%CONT_NFORCE) ) fstrsolid%CONT_NFORCE(:) = 0.d0
168  if( associated(fstrsolid%CONT_FRIC) ) fstrsolid%CONT_FRIC(:) = 0.d0
169  if( associated(fstrsolid%EMBED_NFORCE) ) fstrsolid%EMBED_NFORCE(:) = 0.d0
170  endif
171 
172  do i = 1, fstrsolid%n_contacts
173  grpid = fstrsolid%contacts(i)%group
174  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
175  if( fstrsolid%contacts(i)%method == contacts2s ) then
176  call calcu_contact_ndforce_surfsurf( purpose, ctalgo, fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
177  fstrsolid%dunode(:), conmat, fstrsolid%CONT_NFORCE, fstrsolid%CONT_FRIC )
178  else
179  call calcu_contact_ndforce_nodesurf( purpose, ctalgo, fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
180  fstrsolid%dunode(:), heclagmat%Lagrange(:), conmat, &
181  fstrsolid%CONT_NFORCE, fstrsolid%CONT_FRIC, heclagmat )
182  endif
183  enddo
184 
185  do i = 1, fstrsolid%n_embeds
186  grpid = fstrsolid%embeds(i)%group
187  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) cycle
188  call calcu_contact_ndforce_nodesurf( purpose, ctalgo, fstrsolid%embeds(i), hecmesh%node(:), fstrsolid%unode(:), &
189  fstrsolid%dunode(:), heclagmat%Lagrange(:), conmat, &
190  fstrsolid%EMBED_NFORCE, fstrsolid%EMBED_NFORCE, heclagmat )
191  enddo
192 
193  end subroutine fstr_contact_ndforce_core
194 
196  subroutine fstr_calc_contact_refstiff(cstep, hecMESH, hecMAT, fstrSOLID)
198  integer(kind=kint), intent(in) :: cstep
199  type(hecmwst_local_mesh) :: hecMESH
200  type(hecmwst_matrix) :: hecMAT
201  type(fstr_solid) :: fstrSOLID
202 
203  integer(kind=kint) :: i, grpid, ndof
204  real(kind=kreal), pointer :: diag(:)
205 
206  ndof = hecmat%NDOF
207 
208  ! Extract diagonal components once (efficient, called only once)
209  diag => hecmw_mat_diag(hecmat)
210 
211  ! Loop over contact pairs
212  do i = 1, fstrsolid%n_contacts
213  grpid = fstrsolid%contacts(i)%group
214  if(.not. fstr_iscontactactive(fstrsolid, grpid, cstep)) cycle
215 
216  call calc_contact_pair_refstiff(fstrsolid%contacts(i), diag, ndof, hecmesh)
217  enddo
218 
219  ! Same for embeds
220  do i = 1, fstrsolid%n_embeds
221  grpid = fstrsolid%embeds(i)%group
222  if(.not. fstr_isembedactive(fstrsolid, grpid, cstep)) cycle
223 
224  call calc_contact_pair_refstiff(fstrsolid%embeds(i), diag, ndof, hecmesh)
225  enddo
226 
227  deallocate(diag)
228  end subroutine fstr_calc_contact_refstiff
229 
231  subroutine fstr_scan_contact_state( cstep, sub_step, cont_step, dt, ctAlgo, hecMESH, fstrSOLID, infoCTChange )
232  integer(kind=kint), intent(in) :: cstep
233  integer(kind=kint), intent(in) :: sub_step
234  integer(kind=kint), intent(in) :: cont_step
235  real(kind=kreal), intent(in) :: dt
236  integer(kind=kint), intent(in) :: ctAlgo
237  type( hecmwst_local_mesh ), intent(in) :: hecMESH
238  type(fstr_solid), intent(inout) :: fstrSOLID
239  type(fstr_info_contactchange), intent(inout):: infoCTChange
240  character(len=9) :: flag_ctAlgo
241  integer(kind=kint) :: i, j, k, grpid
242  integer(kind=kint) :: s_chg(3,3), s_emov, s_ebey, s_islid, s_act
243  integer(kind=kint), allocatable :: in_contact(:)
244  logical :: iactive, is_init
245 
246  if( associated( fstrsolid%CONT_RELVEL ) ) fstrsolid%CONT_RELVEL(:) = 0.d0
247  if( associated( fstrsolid%CONT_STATE ) ) fstrsolid%CONT_STATE(:) = 0.d0
248 
249  if( ctalgo == kcaslagrange ) then
250  flag_ctalgo = 'SLagrange'
251  elseif( ctalgo == kcaalagrange ) then
252  flag_ctalgo = 'ALagrange'
253  endif
254 
255  ! P.A. We redefine fstrSOLID%ddunode as current coordinate of every nodes
256  ! fstrSOLID%ddunode(:) = fstrSOLID%unode(:) + fstrSOLID%dunode(:)
257  do i = 1, size(fstrsolid%unode)
258  fstrsolid%ddunode(i) = hecmesh%node(i) + fstrsolid%unode(i) + fstrsolid%dunode(i)
259  enddo
260  active = .false.
261 
262  infoctchange%n_statechange = 0
263  infoctchange%contact2neighbor = 0
264  infoctchange%contact2beyond = 0
265  infoctchange%contact2diffLpos = 0
266  infoctchange%free2contact_new = 0
267  infoctchange%contactNode_current = 0
268 
269  is_init = ( cstep == 1 .and. sub_step == 1 .and. cont_step == 0 )
270 
271  do i=1,fstrsolid%n_contacts
272  grpid = fstrsolid%contacts(i)%group
273  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) then
274  call clear_contact_state(fstrsolid%contacts(i)); cycle
275  endif
276  if( fstrsolid%contacts(i)%method == contacts2s ) then
277  call scan_contact_state_ss( fstrsolid%contacts(i), fstrsolid%ddunode(:), infoctchange, is_init, iactive )
278  else
279  call scan_contact_state( fstrsolid%contacts(i), &
280  & fstrsolid%ddunode(:), fstrsolid%dunode(:), infoctchange, &
281  & hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), &
282  & is_init, iactive, hecmesh=hecmesh, &
283  & flag_ctalgo=flag_ctalgo, ndforce=fstrsolid%QFORCE(:) )
284  endif
285  if( .not. active ) active = iactive
286  enddo
287 
288  do i=1,fstrsolid%n_embeds
289  grpid = fstrsolid%embeds(i)%group
290  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) then
291  call clear_contact_state(fstrsolid%embeds(i)); cycle
292  endif
293  call scan_embed_state( flag_ctalgo, fstrsolid%embeds(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
294  & fstrsolid%QFORCE(:), infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive )
295  if( .not. active ) active = iactive
296  enddo
297 
298  if( is_init .and. ctalgo == kcaslagrange .and. fstrsolid%n_contacts > 0 ) &
299  & call remove_duplication_tiedcontact( cstep, hecmesh, fstrsolid, infoctchange )
300 
301  infoctchange%contactNode_current = infoctchange%contactNode_previous &
302  + sum(infoctchange%n_statechange(:,kcatcont)) - sum(infoctchange%n_statechange(kcatcont,:))
303  infoctchange%contactNode_previous = infoctchange%contactNode_current
304 
305  ! Output summary of contact state changes (always on; per-node detail requires CONTACT_LOG_LEVEL>=1)
306  ! allreduce must be called by all ranks regardless of local counts
307  s_chg = infoctchange%n_statechange
308  s_chg(kcatfree,kcatcont) = s_chg(kcatfree,kcatcont) + infoctchange%free2contact_new
309  s_emov = infoctchange%contact2neighbor
310  s_ebey = infoctchange%contact2beyond
311  s_islid = infoctchange%contact2diffLpos
312  s_act = infoctchange%contactNode_current
313  ! SURF-SURF pairs add the slave nodes of their segments in contact, as update_contact_state_vectors marks them.
314  ! A slave segment is kept by one rank only, so the marks are summed onto the owner of each node and counted there.
315  allocate( in_contact(hecmesh%n_node) )
316  in_contact(:) = 0
317  do i = 1, fstrsolid%n_contacts
318  if( fstrsolid%contacts(i)%method /= contacts2s ) cycle
319  do j = 1, size(fstrsolid%contacts(i)%slave_surf)
320  if( fstrsolid%contacts(i)%slave_surf(j)%state <= 0 ) cycle
321  do k = 1, size(fstrsolid%contacts(i)%slave_surf(j)%nodes)
322  in_contact(fstrsolid%contacts(i)%slave_surf(j)%nodes(k)) = 1
323  enddo
324  enddo
325  enddo
326  call hecmw_assemble_i(hecmesh, in_contact, hecmesh%n_node, 1)
327  do i = 1, hecmesh%nn_internal
328  if( in_contact(i) /= 0 ) s_act = s_act + 1
329  enddo
330  deallocate( in_contact )
331  call hecmw_allreduce_i(hecmesh, s_chg, 9, hecmw_sum)
332  call hecmw_allreduce_i1(hecmesh, s_emov, hecmw_sum)
333  call hecmw_allreduce_i1(hecmesh, s_ebey, hecmw_sum)
334  call hecmw_allreduce_i1(hecmesh, s_islid, hecmw_sum)
335  call hecmw_allreduce_i1(hecmesh, s_act, hecmw_sum)
336  if (hecmw_comm_get_rank() == 0) then
337  write(*,'(A,i7,A,i7,A,i7,A,i7,A,i7,A,i7)') ' Contact change: Free2Cont=', s_chg(kcatfree,kcatcont), &
338  ' Cont2Free=', s_chg(kcatcont,kcatfree), &
339  ' InnerSlid=', s_islid, ' MoveNeibr=', s_emov, ' MoveBynd=', s_ebey, ' ActiveNodes=', s_act
340  if( sum(s_chg(kcatnear,:)) + sum(s_chg(:,kcatnear)) > 0 ) &
341  write(*,'(A,i7,A,i7,A,i7,A,i7)') ' near state change: Free2Near=', s_chg(kcatfree,kcatnear), &
342  ' Near2Free=', s_chg(kcatnear,kcatfree), &
343  ' Near2Cont=', s_chg(kcatnear,kcatcont), ' Cont2Near=', s_chg(kcatcont,kcatnear)
344  end if
345 
346  if( .not. active ) then
347  if( associated( fstrsolid%CONT_NFORCE ) ) fstrsolid%CONT_NFORCE(:) = 0.d0
348  if( associated( fstrsolid%CONT_FRIC ) ) fstrsolid%CONT_FRIC(:) = 0.d0
349  end if
350 
351  end subroutine
352 
354  subroutine fstr_scan_contact_state_exp( cstep, is_init, hecMESH, fstrSOLID, infoCTChange )
355  integer(kind=kint), intent(in) :: cstep
356  logical, intent(in) :: is_init
357  type( hecmwst_local_mesh ), intent(in) :: hecMESH
358  type(fstr_solid), intent(inout) :: fstrSOLID
359  type(fstr_info_contactchange), intent(inout) :: infoCTChange
360 
361  integer(kind=kint) :: i, grpid
362  integer(kind=kint) :: s_chg(3,3), s_emov, s_ebey, s_islid, s_act
363  logical :: iactive
364 
365 
366  ! P.A. We redefine fstrSOLID%ddunode as current coordinate of every nodes
367  ! fstrSOLID%ddunode(:) = fstrSOLID%unode(:) + fstrSOLID%dunode(:)
368  do i = 1, size(fstrsolid%unode)
369  fstrsolid%ddunode(i) = hecmesh%node(i) + fstrsolid%unode(i) + fstrsolid%dunode(i)
370  enddo
371  infoctchange%active = .false.
372 
373  infoctchange%n_statechange = 0
374  infoctchange%contact2neighbor = 0
375  infoctchange%contact2beyond = 0
376  infoctchange%contact2diffLpos = 0
377  infoctchange%free2contact_new = 0
378  infoctchange%contactNode_current = 0
379 
380  do i=1,fstrsolid%n_contacts
381  grpid = fstrsolid%contacts(i)%group
382  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) then
383  call clear_contact_state(fstrsolid%contacts(i)); cycle
384  endif
385 
386  call scan_contact_state( fstrsolid%contacts(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
387  & infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive, hecmesh )
388 
389  infoctchange%active = infoctchange%active .or. iactive
390  enddo
391  call hecmw_allreduce_l1(hecmesh, infoctchange%active, hecmw_lor)
392 
393  infoctchange%contactNode_current = infoctchange%contactNode_previous &
394  + sum(infoctchange%n_statechange(:,kcatcont)) - sum(infoctchange%n_statechange(kcatcont,:))
395  infoctchange%contactNode_previous = infoctchange%contactNode_current
396 
397  ! Output summary of contact state changes (always on; per-node detail requires CONTACT_LOG_LEVEL>=1)
398  ! allreduce must be called by all ranks regardless of local counts
399  s_chg = infoctchange%n_statechange
400  s_chg(kcatfree,kcatcont) = s_chg(kcatfree,kcatcont) + infoctchange%free2contact_new
401  s_emov = infoctchange%contact2neighbor
402  s_ebey = infoctchange%contact2beyond
403  s_islid = infoctchange%contact2diffLpos
404  s_act = infoctchange%contactNode_current
405  call hecmw_allreduce_i(hecmesh, s_chg, 9, hecmw_sum)
406  call hecmw_allreduce_i1(hecmesh, s_emov, hecmw_sum)
407  call hecmw_allreduce_i1(hecmesh, s_ebey, hecmw_sum)
408  call hecmw_allreduce_i1(hecmesh, s_islid, hecmw_sum)
409  call hecmw_allreduce_i1(hecmesh, s_act, hecmw_sum)
410  if (hecmw_comm_get_rank() == 0) then
411  write(*,'(A,i7,A,i7,A,i7,A,i7,A,i7,A,i7)') ' Contact change: Free2Cont=', s_chg(kcatfree,kcatcont), &
412  ' Cont2Free=', s_chg(kcatcont,kcatfree), &
413  ' InnerSlid=', s_islid, ' MoveNeibr=', s_emov, ' MoveBynd=', s_ebey, ' ActiveNodes=', s_act
414  if( sum(s_chg(kcatnear,:)) + sum(s_chg(:,kcatnear)) > 0 ) &
415  write(*,'(A,i7,A,i7,A,i7,A,i7)') ' near state change: Free2Near=', s_chg(kcatfree,kcatnear), &
416  ' Near2Free=', s_chg(kcatnear,kcatfree), &
417  ' Near2Cont=', s_chg(kcatnear,kcatcont), ' Cont2Near=', s_chg(kcatcont,kcatnear)
418  end if
419 
420  fstrsolid%ddunode = 0.d0
421  end subroutine
422 
425  logical function fstr_is_contact_active()
426  fstr_is_contact_active = active
427  end function
428 
429  subroutine fstr_set_contact_active( a )
430  logical, intent(in) :: a
431  active = a
432  end subroutine
433 
434  logical function fstr_is_contact_conv(ctAlgo,infoCTChange,hecMESH)
435  integer(kind=kint), intent(in) :: ctalgo
436  type (fstr_info_contactchange), intent(in) :: infoctchange
437  type (hecmwst_local_mesh), intent(in) :: hecmesh
438 
439  fstr_is_contact_conv = .false.
440  ! The two SURF-SURF counters are incremented on the mortar path only, so the sum is
441  ! unchanged for a NODE-SURF analysis.
442  if( sum(infoctchange%n_statechange) + infoctchange%contact2neighbor + infoctchange%contact2beyond + &
443  infoctchange%free2contact_new + infoctchange%contact2diffLpos == 0 ) &
444  fstr_is_contact_conv = .true.
445 
446  call hecmw_allreduce_l1(hecmesh, fstr_is_contact_conv, hecmw_land)
447  end function
448 
450  logical function fstr_is_matrixstructure_changed(infoCTChange)
451  type (fstr_info_contactchange) :: infoctchange
452  ! Matrix sparsity changes when a node connection appears or disappears. Each pair reports
453  ! through the counters of its sparsity_expansion mode, so a plain sum covers any mix.
454  ! contact2difflpos is excluded (no structural change).
456  if( sum(infoctchange%n_statechange) + infoctchange%contact2neighbor + infoctchange%contact2beyond + &
457  infoctchange%free2contact_new > 0 ) &
459  end function
460 
461  subroutine fstr_update_contact_multiplier( cstep, ctAlgo, hecMESH, hecLagMAT, fstrSOLID, ctchanged )
462  integer(kind=kint), intent(in) :: cstep
463  integer(kind=kint), intent(in) :: ctAlgo
464  type( hecmwst_local_mesh ), intent(in) :: hecMESH
465  type(hecmwst_matrix_lagrange), intent(in) :: hecLagMAT
466  type(fstr_solid), intent(inout) :: fstrSOLID
467  logical, intent(out) :: ctchanged
468 
469  integer(kind=kint) :: i, nc, algtype, grpid
470 
471  gnt = 0.d0; ctchanged = .false.
472  nc = fstrsolid%n_contacts+fstrsolid%n_embeds
473  do i=1, fstrsolid%n_contacts
474  grpid = fstrsolid%contacts(i)%group
475  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
476 
477  if( fstrsolid%contacts(i)%method == contacts2s ) then
478  call update_contact_multiplier_surfsurf( fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
479  fstrsolid%dunode(:), fstrsolid%contacts(i)%fcoeff )
480  else
481  algtype = fstrsolid%contacts(i)%algtype
482  if( algtype == contactsslid .or. algtype == contactfslid ) then
483  call update_contact_multiplier( ctalgo, fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:), &
484  fstrsolid%dunode(:), fstrsolid%contacts(i)%fcoeff, &
485  hecmesh, heclagmat, gnt, ctchanged )
486  else if( algtype == contacttied ) then
487  call update_tied_multiplier( fstrsolid%contacts(i), fstrsolid%unode(:), fstrsolid%dunode(:), &
488  & ctchanged )
489  endif
490  endif
491  enddo
492 
493  do i=1, fstrsolid%n_embeds
494  call update_tied_multiplier( fstrsolid%embeds(i), fstrsolid%unode(:), fstrsolid%dunode(:), &
495  & ctchanged )
496  enddo
497 
498  call hecmw_allreduce_l1(hecmesh, ctchanged, hecmw_lor)
499 
500  if( nc>0 ) gnt = gnt/nc
501  end subroutine
502 
507  subroutine fstr_begin_lambda_txn( fstrSOLID, cstep )
508  type(fstr_solid), intent(inout) :: fstrSOLID
509  integer(kind=kint), intent(in) :: cstep
510  integer(kind=kint) :: i, s, grpid
511 
512  do i = 1, fstrsolid%n_contacts
513  if( fstrsolid%contacts(i)%method /= contacts2s ) cycle
514  grpid = fstrsolid%contacts(i)%group
515  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
516  if( .not. associated(fstrsolid%contacts(i)%slave_surf) ) cycle
517  do s = 1, size(fstrsolid%contacts(i)%slave_surf)
518  fstrsolid%contacts(i)%slave_surf(s)%lam_work_n = 0
519  fstrsolid%contacts(i)%slave_surf(s)%lam_work_id(:) = 0
520  fstrsolid%contacts(i)%slave_surf(s)%lam_work_val(:,:) = 0.d0
521  ! the tangential working accumulator is cleared alongside lam_work_val; the
522  ! stick/slip warm-start is read from begin at resolve time, not restored here
523  fstrsolid%contacts(i)%slave_surf(s)%lam_work_t(:,:,:) = 0.d0
524  fstrsolid%contacts(i)%slave_surf(s)%lam_work_fstate(:,:) = contactstick
525  fstrsolid%contacts(i)%slave_surf(s)%state = fstrsolid%contacts(i)%slave_surf(s)%state_begin
526  fstrsolid%contacts(i)%slave_surf(s)%state_prev = fstrsolid%contacts(i)%slave_surf(s)%state_prev_begin
527  enddo
528  enddo
529  end subroutine
530 
535  subroutine fstr_commit_lambda_txn( fstrSOLID, cstep )
536  type(fstr_solid), intent(inout) :: fstrSOLID
537  integer(kind=kint), intent(in) :: cstep
538  integer(kind=kint) :: i, s, grpid, r, m
539  type(tcontactsurf), pointer :: surf
540 
541  do i = 1, fstrsolid%n_contacts
542  if( fstrsolid%contacts(i)%method /= contacts2s ) cycle
543  grpid = fstrsolid%contacts(i)%group
544  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
545  if( .not. associated(fstrsolid%contacts(i)%slave_surf) ) cycle
546  do s = 1, size(fstrsolid%contacts(i)%slave_surf)
547  surf => fstrsolid%contacts(i)%slave_surf(s)
548  m = 0
549  ! The master is kept if at least one slave node is active against it.
550  do r = 1, surf%lam_work_n
551  if( maxval(surf%lam_work_val(1:size(surf%nodes),r)) > 0.d0 ) then
552  m = m + 1
553  surf%lam_begin_id(m) = surf%lam_work_id(r)
554  surf%lam_begin_val(1:size(surf%nodes),m) = surf%lam_work_val(1:size(surf%nodes),r)
555  ! the tangential multiplier rides along the master that passed the lambda_n filter
556  surf%lam_begin_t(:,1:size(surf%nodes),m) = surf%lam_work_t(:,1:size(surf%nodes),r)
557  surf%lam_begin_fstate(1:size(surf%nodes),m) = surf%lam_work_fstate(1:size(surf%nodes),r)
558  endif
559  enddo
560  surf%lam_begin_n = m
561  surf%state_begin = surf%state
562  surf%state_prev_begin = surf%state_prev
563  enddo
564  enddo
565  end subroutine
566 
568  subroutine fstr_update_contact_tangentforce( cstep, fstrSOLID )
569  integer(kind=kint), intent(in) :: cstep
570  type(fstr_solid), intent(inout) :: fstrSOLID
571 
572  integer(kind=kint) :: i, grpid
573 
574  do i=1, fstrsolid%n_contacts
575 
576  grpid = fstrsolid%contacts(i)%group
577  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
578 
579  call update_contact_tangentforce( fstrsolid%contacts(i) )
580  enddo
581  end subroutine
582 
584  subroutine fstr_update_contact_state_vectors( fstrSOLID, dt )
585  type(fstr_solid), intent(inout) :: fstrsolid
586  real(kind=kreal), intent(in) :: dt
587 
588  integer(kind=kint) :: i
589 
590  if( associated( fstrsolid%CONT_RELVEL ) ) fstrsolid%CONT_RELVEL(:) = 0.d0
591  if( associated( fstrsolid%CONT_STATE ) ) fstrsolid%CONT_STATE(:) = 0.d0
592 
593  do i=1, fstrsolid%n_contacts
594  call update_contact_state_vectors( fstrsolid%contacts(i), dt, fstrsolid%CONT_RELVEL, fstrsolid%CONT_STATE )
595  enddo
596  end subroutine
597 
598 end module mcontact
real(kind=kreal) function, dimension(:), pointer, public hecmw_mat_diag(hecMAT)
Extract diagonal components from matrix D into a 1D vector Returns: diag(i) = D(ndof*ndof*(node-1) + ...
Definition: hecmw.f90:6
Contact processing at assembly level (all pairs in one tContact object)
subroutine calcu_contact_ndforce_nodesurf(purpose, ctAlgo, contact, coord, disp, ddisp, lagrange_array, conMAT, CONT_NFORCE, CONT_FRIC, hecLagMAT)
This subroutine calculates contact nodal force for each contact pair and assembles it into contact ma...
subroutine calcu_contact_stiffness_surfsurf(ctAlgo, contact, coord, disp, ddisp, hecMAT)
subroutine, public calc_contact_pair_refstiff(contact, diag, ndof, hecMESH)
Calculate reference stiffness for one contact pair.
subroutine update_contact_multiplier(ctAlgo, contact, coord, disp, ddisp, fcoeff, hecMESH, hecLagMAT, gnt, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
subroutine calcu_contact_ndforce_surfsurf(purpose, ctAlgo, contact, coord, disp, ddisp, conMAT, CONT_NFORCE, CONT_FRIC)
subroutine calcu_contact_ndforce_exp(contact, coord, disp, ddisp, CONT_NFORCE, CONT_FRIC)
Compute contact nodal normal force for output from the stored contact multiplier, for the explicit dy...
subroutine calcu_contact_stiffness_nodesurf(ctAlgo, contact, coord, disp, ddisp, iter, lagrange_array, conMAT, hecLagMAT)
This subroutine calculates contact stiffness for each contact pair and assembles it into global stiff...
subroutine update_contact_tangentforce(contact)
subroutine update_tied_multiplier(contact, disp, ddisp, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
subroutine update_contact_multiplier_surfsurf(contact, coord, disp, ddisp, fcoeff)
This subroutine updates the lagrangian multiplier of a mortar (MORTAR=YES) contact pair....
Contact mechanics calculations at element level (single contact pair)
This module provides geometric calculations for contact.
MPC (Multi-Point Constraint) processing for contact analysis.
Contact output vector processing (initialization, area calculation, parallel)
subroutine, public fstr_setup_parancon_contactvalue(hecMESH, ndof, vec, vtype)
subroutine, public calc_contact_area(hecMESH, fstrSOLID, flag)
subroutine, public initialize_contact_output_vectors(fstrSOLID, hecMAT)
subroutine, public setup_contact_elesurf_for_area(cstep, hecMESH, fstrSOLID)
subroutine, public initialize_embed_vectors(fstrSOLID, hecMAT)
subroutine, public update_contact_state_vectors(contact, dt, relvel_vec, state_vec)
Update contact state output vectors (CONT_RELVEL, CONT_STATE)
Contact search and state scanning at search level (all pairs in one tContact)
subroutine scan_contact_state(contact, currpos, currdisp, infoCTChange, nodeID, elemID, is_init, active, hecMESH, flag_ctAlgo, ndforce)
This subroutine update contact states, which include.
subroutine remove_duplication_tiedcontact(cstep, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
subroutine scan_contact_state_ss(contact, currpos, infoCTChange, is_init, active)
Scan the contact state of every integration point of every slave segment of one SURF-SURF (mortar) co...
subroutine scan_embed_state(flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, nodeID, elemID, is_init, active, B)
This subroutine update contact states, which include.
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
logical function fstr_isembedactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1126
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1116
integer(kind=kint), parameter kcaslagrange
contact analysis algorithm
Definition: m_fstr.F90:62
real(kind=kreal) dt
ANALYSIS CONTROL for NLGEOM and HEAT.
Definition: m_fstr.F90:146
integer(kind=kint), parameter kcaalagrange
Definition: m_fstr.F90:63
Top-level contact analysis module (System level)
subroutine fstr_set_contact_active(a)
subroutine fstr_update_ndforce_contact(cstep, ctAlgo, hecMESH, hecLagMAT, fstrSOLID, conMAT)
Compute contact forces for residual vector (conMATB).
logical function fstr_is_matrixstructure_changed(infoCTChange)
Any state category change moves a Lagrange multiplier row or a slave-master coupling.
subroutine fstr_scan_contact_state_exp(cstep, is_init, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
logical function fstr_is_contact_conv(ctAlgo, infoCTChange, hecMESH)
subroutine fstr_contact_ndforce_core(purpose, cstep, ctAlgo, hecMESH, hecLagMAT, fstrSOLID, conMAT)
Core routine: compute contact nodal forces for all contact/embed pairs. purpose == kctForResidual: as...
subroutine fstr_addcontactstiffness(cstep, ctAlgo, iter, hecMESH, conMAT, hecLagMAT, fstrSOLID)
subroutine fstr_calc_contact_output_force(cstep, ctAlgo, hecMESH, hecLagMAT, fstrSOLID, conMAT)
Compute contact forces for output (CONT_NFORCE/CONT_FRIC).
subroutine fstr_update_contact_multiplier(cstep, ctAlgo, hecMESH, hecLagMAT, fstrSOLID, ctchanged)
subroutine, public fstr_update_contact_state_vectors(fstrSOLID, dt)
Update contact state output vectors for all contacts.
subroutine, public fstr_calc_contact_output_force_exp(hecMESH, fstrSOLID)
Explicit-dynamic counterpart of fstr_calc_contact_output_force.
subroutine fstr_calc_contact_refstiff(cstep, hecMESH, hecMAT, fstrSOLID)
Calculate reference stiffness for all contact pairs (System Level)
subroutine fstr_commit_lambda_txn(fstrSOLID, cstep)
COMMIT lambda transaction (MORTAR=YES only): keep the masters with a positive per-node lambda and swa...
subroutine fstr_begin_lambda_txn(fstrSOLID, cstep)
BEGIN lambda transaction (MORTAR=YES only): clear the working buffer and restore the segment state fr...
subroutine fstr_scan_contact_state(cstep, sub_step, cont_step, dt, ctAlgo, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
logical function fstr_is_contact_active()
Whether contact stiffness and residual have to be assembled. Broader than is_contact_active(state): a...
subroutine fstr_update_contact_tangentforce(cstep, fstrSOLID)
Update tangent force.
This module manages the data structure for contact calculation.
integer, parameter contactsslid
integer, parameter kcatcont
Lagrange multiplier held (STICK or SLIP)
integer, parameter kcatnear
projection only, no Lagrange multiplier
integer, parameter kctforresidual
purpose flag for contact force calculation
integer, parameter contacts2s
real(kind=kreal), dimension(2), save gnt
1:current average penetration; 2:current relative tangent displacement
subroutine clear_contact_state(contact)
Reset contact state all to free.
integer, parameter contacttied
contact type or algorithm definition
integer, parameter kctforoutput
compute contact force for output (CONT_NFORCE/CONT_FRIC)
integer, parameter kcatfree
contact state category: states sharing a category contribute to the matrix in the same way
integer, parameter contactfslid
integer, parameter contactstick
Structure to define a slave surface segment of a SURF-SURF (mortar) contact pair.