FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
fstr_contact_def.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 !-------------------------------------------------------------------------------
13 
14  use hecmw
15  use elementinfo
16  use msurfelement
18  use bucket_search
19  use mcontactparam
20 
21  implicit none
22 
23  real(kind=kreal), save :: cgn=1.d-5
24  real(kind=kreal), save :: cgt=1.d-3
25 
26  real(kind=kreal), save :: gnt(2)
28  real(kind=kreal), save :: bakgnt(2)
30 
31  integer, parameter :: contactunknown = -1
33  integer, parameter :: contactfree = -1
34  integer, parameter :: contactnear = 0
35  integer, parameter :: contactstick = 1
36  integer, parameter :: contactslip = 2
37  integer, parameter :: candidate_intp = 3
38 
40  integer, parameter :: kcatfree = 1
41  integer, parameter :: kcatnear = 2
42  integer, parameter :: kcatcont = 3
43 
45  integer, parameter :: contacttied = 1
46  integer, parameter :: contactglued = 2
47  integer, parameter :: contactsslid = 3
48  integer, parameter :: contactfslid = 4
49 
51  integer, parameter :: kcsnone = 0
52  integer, parameter :: kcsnagata = 1
53 
55  integer, parameter :: contactn2s = 1
56  integer, parameter :: contacts2s = 2
57 
59  integer, parameter :: sparsity_none = 0
60  integer, parameter :: sparsity_neighbor = 1
61 
63  integer, parameter :: max_n_intp = 128
64 
66  integer, parameter :: c_if_slave = 1
67  integer, parameter :: c_if_master = 2
68 
70  integer, parameter :: kctforresidual = 1
71  integer, parameter :: kctforoutput = 2
72 
75  integer :: state
76  integer :: surface
77  integer :: id_lagrange
78  real(kind=kreal) :: distance
79  real(kind=kreal) :: wkdist
80  real(kind=kreal) :: lpos(3)
81  real(kind=kreal) :: gpos(3)
82  real(kind=kreal) :: direction(3)
83  real(kind=kreal) :: multiplier(3)
85  real(kind=kreal) :: tangentforce(3)
86  real(kind=kreal) :: tangentforce1(3)
87  real(kind=kreal) :: tangentforce_trial(3)
88  real(kind=kreal) :: tangentforce_final(3)
89  real(kind=kreal) :: reldisp(3)
90  !
91  real(kind=kreal) :: shrink_factor
92  real(kind=kreal) :: time_factor
93  real(kind=kreal) :: init_pos
94  real(kind=kreal) :: end_pos
95  integer :: interference_flag
96  end type
97 
100  integer(kind=kint) :: eid
101  integer(kind=kint) :: etype
102  integer(kind=kint), pointer :: nodes(:)=>null()
103  integer(kind=kint) :: state = contactfree
104  integer(kind=kint) :: state_prev = contactfree
105  integer(kind=kint) :: n_intp
106  type(tcontactstate), pointer :: states(:)=>null()
107  integer(kind=kint), pointer :: nslave_index(:)=>null()
108  ! --- lambda transaction buffers ---
109  ! begin: previous substep's COMMIT product, immutable during a substep (warm-start source)
110  ! working: current substep's accumulator, cleared at BEGIN, written by the augmentation update
111  integer(kind=kint), pointer :: lam_begin_id(:)=>null()
112  real(kind=kreal), pointer :: lam_begin_val(:,:)=>null()
113  integer(kind=kint) :: lam_begin_n = 0
114  integer(kind=kint), pointer :: lam_work_id(:)=>null()
115  real(kind=kreal), pointer :: lam_work_val(:,:)=>null()
116  integer(kind=kint) :: lam_work_n = 0
117  ! --- tangential friction parallel arrays ---
118  ! per-node covariant tangent multiplier (2 components, node a, rank r) and per-node
119  ! stick/slip state. Rank r is keyed by lam_*_id (master), node a is the slave-surf node;
120  ! both mirror lam_*_val.
121  real(kind=kreal), pointer :: lam_begin_t(:,:,:)=>null()
122  real(kind=kreal), pointer :: lam_work_t(:,:,:)=>null()
123  integer(kind=kint), pointer :: lam_begin_fstate(:,:)=>null()
124  integer(kind=kint), pointer :: lam_work_fstate(:,:)=>null()
125  end type tcontactsurf
126 
128  type tcontact
129  ! following contact definition
130  character(len=HECMW_NAME_LEN) :: name
131  integer :: ctype
132  integer :: group
133  character(len=HECMW_NAME_LEN) :: pair_name
134  integer :: surf_id1, surf_id2
135  integer :: surf_id1_sgrp
136  type(tsurfelement), pointer :: master(:)=>null()
137  integer :: n_master_owned = 0
138  integer, pointer :: slave(:)=>null()
139  real(kind=kreal) :: fcoeff
140  real(kind=kreal) :: npenalty
141  real(kind=kreal) :: tpenalty
142  real(kind=kreal) :: refstiff
143  real(kind=kreal) :: damp_alpha
144  real(kind=kreal) :: damp_gact
145 
146  type(tcontactsurf), pointer :: slave_surf(:)=>null()
147 
148  ! !CONTACT_INTERFERENCE data; default-initialized because check_apply_Contact_IF only
149  ! writes them when that card is present, while if_type is read unconditionally
150  ! (if_flag = contact%if_type /= 0) by the contact force / search paths.
151  real(kind=kreal) :: ctime = 0.d0
152  integer(kind=kint) :: if_type = 0
153  real(kind=kreal) :: if_etime = 0.d0
154  real(kind=kreal) :: initial_pos = 0.d0
155  real(kind=kreal) :: end_pos = 0.d0
156  ! following algorithm
157  ! -1: not initialized
158  ! 1: TIED-Just rigidly fixed the two surfaces
159  ! 2: GLUED-Distance between the two surfaces to zero and glue them
160  ! 3: SSLID-Small sliding contact( no position but with contact state change)
161  ! 4: FSLID-Finite sliding contact (both changes in contact state and position possible)
162  integer :: algtype
163  integer :: smoothing
164  integer :: method = contactn2s
166  integer :: sparsity_expansion = sparsity_none
167 
168  logical :: mpced
169  logical :: symmetric
170  real(kind=kreal) :: eps_fric_band = 0.d0
171 
172  ! following contact state
173  type(tcontactstate), pointer :: states(:)=>null()
174 
175  type(hecmwst_contact_comm) :: comm
176  type(bucketdb) :: master_bktdb
177 
178  type(tcontactparam), pointer :: cparam=>null()
179  end type tcontact
180 
182  logical :: active
183  integer(kind=kint) :: n_statechange(3,3)
184  integer(kind=kint) :: contact2neighbor
185  integer(kind=kint) :: contact2beyond
186  integer(kind=kint) :: contact2difflpos
187  integer(kind=kint) :: free2contact_new
188  integer(kind=kint) :: contactnode_previous
189  integer(kind=kint) :: contactnode_current
190  end type fstr_info_contactchange
191 
192  private :: is_active_contact
193 
194 contains
195 
197  subroutine contact_state_init(cstate)
198  type(tcontactstate), intent(inout) :: cstate
199  cstate%state = -1
200  cstate%surface = -1
201  cstate%id_lagrange = 0
202  cstate%distance = 0.0d0
203  cstate%wkdist = 0.0d0
204  cstate%lpos(:) = 0.0d0
205  cstate%gpos(:) = 0.0d0
206  cstate%direction(:) = 0.0d0
207  cstate%multiplier(:) = 0.0d0
208  cstate%tangentForce(:) = 0.0d0
209  cstate%tangentForce1(:) = 0.0d0
210  cstate%tangentForce_trial(:) = 0.0d0
211  cstate%tangentForce_final(:) = 0.0d0
212  cstate%reldisp(:) = 0.0d0
213  cstate%shrink_factor = 0.0d0
214  cstate%time_factor = 0.0d0
215  cstate%init_pos = 0.0d0
216  cstate%end_pos = 0.0d0
217  cstate%interference_flag = 0
218  end subroutine
219 
221  subroutine contact_state_copy(cstate1, cstate2)
222  type(tcontactstate), intent(in) :: cstate1
223  type(tcontactstate), intent(inout) :: cstate2
224  cstate2 = cstate1
225  end subroutine
226 
228  pure logical function is_contact_active(state)
229  integer, intent(in) :: state
230  is_contact_active = (state >= contactstick)
231  end function
232 
234  pure logical function is_contact_free(state)
235  integer, intent(in) :: state
236  is_contact_free = (state == contactfree)
237  end function
238 
240  pure integer function contact_state_category(state)
241  integer, intent(in) :: state
242  if( is_contact_free(state) ) then
244  else if( is_contact_active(state) ) then
246  else
248  endif
249  end function
250 
252  subroutine fstr_contact_finalize( contact )
253  type(tcontact), intent(inout) :: contact
254  integer :: i
255  if( associated( contact%slave ) ) deallocate(contact%slave)
256  if( associated( contact%master ) ) then
257  do i=1,size( contact%master )
258  call finalize_surf( contact%master(i) )
259  enddo
260  deallocate(contact%master)
261  endif
262  if( associated(contact%states) ) deallocate(contact%states)
263  call hecmw_contact_comm_finalize(contact%comm)
264  call bucketdb_finalize( contact%master_bktDB )
265  end subroutine
266 
268  logical function fstr_contact_check( contact, hecMESH )
269  type(tcontact), intent(inout) :: contact
270  type(hecmwst_local_mesh), pointer :: hecmesh
271 
272  integer :: i
273  logical :: isfind
274 
275  fstr_contact_check = .false.
276 
277  ! if contact pair exist?
278  isfind = .false.
279  do i=1,hecmesh%contact_pair%n_pair
280  if( hecmesh%contact_pair%name(i) == contact%pair_name ) then
281  contact%ctype = hecmesh%contact_pair%type(i)
282  contact%surf_id1 = hecmesh%contact_pair%slave_grp_id(i)
283  contact%surf_id2 = hecmesh%contact_pair%master_grp_id(i)
284  contact%surf_id1_sgrp = hecmesh%contact_pair%slave_orisgrp_id(i)
285  isfind = .true.
286  endif
287  enddo
288  if( .not. isfind ) return;
289  if( contact%fcoeff<=0.d0 ) contact%fcoeff=0.d0
290  if( contact%ctype < 1 .and. contact%ctype > 3 ) return
291  if( contact%group<=0 ) return
292 
293  fstr_contact_check = .true.
294  end function
295 
297  integer(kind=kint) function fstr_count_internal_slaves( contact, hecMESH )
298  type(tcontact), intent(in) :: contact
299  type(hecmwst_local_mesh), pointer :: hecmesh
300 
301  integer :: i, is, ie, cgrp
302 
304 
305  cgrp = contact%surf_id1
306  if( cgrp<=0 ) return
307  is= hecmesh%node_group%grp_index(cgrp-1) + 1
308  ie= hecmesh%node_group%grp_index(cgrp )
309  do i=is,ie
310  if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal ) then
312  endif
313  enddo
314  end function
315 
317  logical function fstr_contact_init( contact, hecMESH, cparam )
318  type(tcontact), intent(inout) :: contact
319  type(hecmwst_local_mesh), pointer :: hecmesh
320  type(tcontactparam), target :: cparam
321 
322  integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
323  integer :: count, id_area
324  logical :: slave_owner, take_master
325  integer, allocatable :: slave_index(:)
326 
327  fstr_contact_init = .false.
328 
329  contact%cparam => cparam
330 
331  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
332 
333  ! update_surface_normal normalises vertex normals only after the cross-rank assembly, so a uniform factor cancels
334  ! but a partial one does not: a rank owning no slave must take no master surface at all, even though the
335  ! partitioner does leave master elements here to keep the communication tables symmetric
336  take_master = .true.
337  if( slave_owner ) take_master = fstr_count_internal_slaves( contact, hecmesh ) > 0
338 
339  ! master surface
340  cgrp = contact%surf_id2
341  if( cgrp<=0 ) return
342  is= hecmesh%surf_group%grp_index(cgrp-1) + 1
343  ie= hecmesh%surf_group%grp_index(cgrp )
344 
345  ! Owned-only master face count, independent of take_master: the SURF-SURF visibility
346  ! guard in fstr_setup sums it over ranks to get the global unique master face count.
347  contact%n_master_owned = 0
348  do i=is,ie
349  ic = hecmesh%surf_group%grp_item(2*i-1)
350  if( hecmesh%elem_ID(ic*2) == hecmesh%my_rank ) contact%n_master_owned = contact%n_master_owned + 1
351  enddo
352 
353  count = 0
354  if( take_master ) then
355  do i=is,ie
356  ic = hecmesh%surf_group%grp_item(2*i-1)
357  id_area = hecmesh%elem_ID(ic*2)
358  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
359  count = count + 1
360  enddo
361  endif
362  allocate( contact%master(count) )
363  count = 0
364  if( take_master ) then
365  do i=is,ie
366  ic = hecmesh%surf_group%grp_item(2*i-1)
367  id_area = hecmesh%elem_ID(ic*2)
368  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
369  count = count + 1
370  nsurf = hecmesh%surf_group%grp_item(2*i)
371  ic_type = hecmesh%elem_type(ic)
372  call initialize_surf( ic, ic_type, nsurf, contact%master(count) )
373  iss = hecmesh%elem_node_index(ic-1)
374  do j=1, size( contact%master(count)%nodes )
375  nn = contact%master(count)%nodes(j)
376  contact%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
377  enddo
378  enddo
379  endif
380 
381  call update_surface_reflen( contact%master, hecmesh%node )
382 
383  cgrp = contact%surf_id1
384  if( cgrp<=0 ) return
385  is= hecmesh%node_group%grp_index(cgrp-1) + 1
386  ie= hecmesh%node_group%grp_index(cgrp )
387  nslave = 0
388  do i=is,ie
389  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
390  nslave = nslave + 1
391  enddo
392  allocate( contact%slave(nslave) )
393  allocate( slave_index(hecmesh%n_node) )
394  slave_index(:) = 0
395  ii = 0
396  do i=is,ie
397  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
398  ii = ii + 1
399  contact%slave(ii) = hecmesh%node_group%grp_item(i)
400  slave_index(contact%slave(ii)) = ii
401  enddo
402 
403  ! contact state
404  allocate( contact%states(nslave) )
405  do i=1,nslave
406  call contact_state_init( contact%states(i) )
407  enddo
408 
409  ! neighborhood of surface group
410  call update_surface_box_info( contact%master, hecmesh%node )
411  call bucketdb_init( contact%master_bktDB )
412  call update_surface_bucket_info( contact%master, contact%master_bktDB )
413  call find_surface_neighbor( contact%master, contact%master_bktDB )
414 
415  if(contact%method == contacts2s) then
416  ! The mortar integral passes the master shape functions through a length-4 array and
417  ! sizes its element vectors for a first-order pair, so a second-order master face
418  ! overruns them. initialize_csurf rejects the slave side for the same reason.
419  do i=1, size( contact%master )
420  if( contact%master(i)%etype /= fe_quad4n .and. contact%master(i)%etype /= fe_tri3n ) then
421  write(*,*) '### Error: MORTAR=YES supports first-order surfaces only (quad4/tri3) : etype=', &
422  contact%master(i)%etype
423  stop hecmw_exit_model
424  endif
425  enddo
426 
427  ! slave surface
428  cgrp = contact%surf_id1_sgrp
429  if( cgrp<=0 ) return
430  is= hecmesh%surf_group%grp_index(cgrp-1) + 1
431  ie= hecmesh%surf_group%grp_index(cgrp )
432 
433  ! Slave segments are taken owned-only (a serial mesh owns every element, so this is
434  ! the full slave surface there). The master surface must be visible in full on every
435  ! slave-owning rank; that is what !PARTITION, CONTACT_OWNER=SLAVE gives and what the
436  ! visibility guard in fstr_setup checks.
437  count = 0
438  do i=is,ie
439  ic = hecmesh%surf_group%grp_item(2*i-1)
440  if( hecmesh%elem_ID(ic*2) /= hecmesh%my_rank ) cycle
441  count = count + 1
442  enddo
443  allocate( contact%slave_surf(count) )
444  count = 0
445  do i=is,ie
446  ic = hecmesh%surf_group%grp_item(2*i-1)
447  if( hecmesh%elem_ID(ic*2) /= hecmesh%my_rank ) cycle
448  count = count + 1
449  nsurf = hecmesh%surf_group%grp_item(2*i)
450  ic_type = hecmesh%elem_type(ic)
451  call initialize_csurf( ic, ic_type, nsurf, contact%slave_surf(count) )
452  iss = hecmesh%elem_node_index(ic-1)
453  do j=1, size( contact%slave_surf(count)%nodes )
454  nn = contact%slave_surf(count)%nodes(j)
455  contact%slave_surf(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
456  contact%slave_surf(count)%nslave_index(j) = slave_index(hecmesh%elem_node_item( iss+nn ))
457  enddo
458  enddo
459 
460  ! state for each integration points
461  do i=1, size( contact%slave_surf )
462  nn = contact%slave_surf(i)%n_intp
463  allocate( contact%slave_surf(i)%states(nn) )
464  do j = 1, contact%slave_surf(i)%n_intp
465  contact%slave_surf(i)%states(j)%state = -1
466  contact%slave_surf(i)%states(j)%multiplier(:) = 0.d0
467  contact%slave_surf(i)%states(j)%tangentForce(:) = 0.d0
468  contact%slave_surf(i)%states(j)%tangentForce1(:) = 0.d0
469  contact%slave_surf(i)%states(j)%tangentForce_trial(:) = 0.d0
470  contact%slave_surf(i)%states(j)%tangentForce_final(:) = 0.d0
471  contact%slave_surf(i)%states(j)%reldisp(:) = 0.d0
472  contact%slave_surf(i)%states(j)%time_factor = 0.d0
473  contact%slave_surf(i)%states(j)%interference_flag = 0
474  enddo
475  enddo
476  endif
477 
478  ! initialize contact communication table
479  call hecmw_contact_comm_init( contact%comm, hecmesh, 1, nslave, contact%slave )
480 
481  contact%symmetric = .true.
482  fstr_contact_init = .true.
483  end function
484 
486  logical function fstr_embed_init( embed, hecMESH, cparam )
487  type(tcontact), intent(inout) :: embed
488  type(hecmwst_local_mesh), pointer :: hecmesh
489  type(tcontactparam), target :: cparam
490 
491  integer :: i, j, is, ie, cgrp, nslave, ic, ic_type, iss, nn, ii
492  integer :: count, id_area
493  logical :: slave_owner, take_master
494 
495  fstr_embed_init = .false.
496 
497  embed%cparam => cparam
498 
499  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
500 
501  take_master = .true.
502  if( slave_owner ) take_master = fstr_count_internal_slaves( embed, hecmesh ) > 0
503 
504  ! master surface
505  cgrp = embed%surf_id2
506  if( cgrp<=0 ) return
507  is= hecmesh%elem_group%grp_index(cgrp-1) + 1
508  ie= hecmesh%elem_group%grp_index(cgrp )
509 
510  count = 0
511  if( take_master ) then
512  do i=is,ie
513  ic = hecmesh%elem_group%grp_item(i)
514  id_area = hecmesh%elem_ID(ic*2)
515  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
516  count = count + 1
517  enddo
518  endif
519  allocate( embed%master(count) )
520  count = 0
521  if( take_master ) then
522  do i=is,ie
523  ic = hecmesh%elem_group%grp_item(i)
524  id_area = hecmesh%elem_ID(ic*2)
525  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
526  count = count + 1
527  ic_type = hecmesh%elem_type(ic)
528  call initialize_surf( ic, ic_type, 0, embed%master(count) )
529  iss = hecmesh%elem_node_index(ic-1)
530  do j=1, size( embed%master(count)%nodes )
531  nn = embed%master(count)%nodes(j)
532  embed%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
533  enddo
534  enddo
535  endif
536 
537  ! slave surface
538  cgrp = embed%surf_id1
539  if( cgrp<=0 ) return
540  is= hecmesh%node_group%grp_index(cgrp-1) + 1
541  ie= hecmesh%node_group%grp_index(cgrp )
542  nslave = 0
543  do i=is,ie
544  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
545  nslave = nslave + 1
546  enddo
547  allocate( embed%slave(nslave) )
548  ii = 0
549  do i=is,ie
550  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
551  ii = ii + 1
552  embed%slave(ii) = hecmesh%node_group%grp_item(i)
553  enddo
554 
555  ! embed state
556  allocate( embed%states(nslave) )
557  do i=1,nslave
558  call contact_state_init( embed%states(i) )
559  enddo
560 
561  ! neighborhood of surface group
562  call update_surface_box_info( embed%master, hecmesh%node )
563  call bucketdb_init( embed%master_bktDB )
564  call update_surface_bucket_info( embed%master, embed%master_bktDB )
565  call find_surface_neighbor( embed%master, embed%master_bktDB )
566 
567  ! initialize contact communication table
568  call hecmw_contact_comm_init( embed%comm, hecmesh, 1, nslave, embed%slave )
569 
570  ! initialize penalty coefficients
571  embed%nPenalty = 1.0d0 ! default normal penalty coefficient
572  embed%tPenalty = 0.1d0 ! default tangential penalty coefficient
573  embed%refStiff = 0.0d0 ! will be calculated after first stiffness assembly
574  embed%damp_alpha = 0.0d0
575  embed%damp_gact = 0.0d0
576 
577  embed%symmetric = .true.
578  fstr_embed_init = .true.
579  end function
580 
581  function check_apply_contact_if( contact_if, contacts )
582  type(tcontactinterference), intent(inout) :: contact_if
583  type(tcontact) :: contacts(:)
584 
585  integer :: i, j
586  logical :: isfind
587  integer(kind=kint) :: check_apply_contact_if
588 
590  ! if contact pair exist?
591  isfind = .false.
592  do i = 1, size(contacts)
593  if( contacts(i)%pair_name == contact_if%cp_name ) then
594  ! !CONTACT_INTERFERENCE is not implemented for the SURF-SURF mortar path
595  if( contacts(i)%method == contacts2s ) then
596  write(*,*) '### Error: CONTACT_INTERFERENCE is not supported with MORTAR=YES'
597  stop hecmw_exit_model
598  endif
599  contacts(i)%if_type = contact_if%if_type
600  contacts(i)%if_etime = contact_if%etime
601  contacts(i)%initial_pos = contact_if%initial_pos
602  contacts(i)%end_pos = contact_if%end_pos
603  do j = 1, size(contacts(i)%states)
604  contacts(i)%states(j)%interference_flag = contact_if%if_type
605  contacts(i)%states(j)%init_pos = contact_if%initial_pos
606  contacts(i)%states(j)%end_pos = contact_if%end_pos
607  if( contact_if%if_type /= c_if_slave )then
608  contacts(i)%states(j)%time_factor = (contact_if%end_pos - contact_if%initial_pos) / contact_if%etime
609  else
610  contacts(i)%states(j)%time_factor = contact_if%etime
611  end if
612  end do
613  isfind = .true.
614  check_apply_contact_if = 0; return
615  endif
616  enddo
617  if( .not. isfind ) return;
619 
620  end function
621 
623  subroutine clear_contact_state( contact )
624  type(tcontact), intent(inout) :: contact
625  integer :: i
626  if( .not. associated(contact%states) ) return
627  do i=1,size( contact%states )
628  contact%states(i)%state = -1
629  enddo
630  end subroutine
631 
633  logical function is_active_contact( acgrp, contact )
634  integer, intent(in) :: acgrp(:)
635  type(tcontact), intent(in) :: contact
636  if( any( acgrp==contact%group ) ) then
637  is_active_contact = .true.
638  else
639  is_active_contact = .false.
640  endif
641  end function
642 
644  subroutine initialize_csurf( eid, etype, nsurf, surf )
645  use elementinfo
646  integer(kind=kint), intent(in) :: eid
647  integer(kind=kint), intent(in) :: etype
648  integer(kind=kint), intent(in) :: nsurf
649  type(tcontactsurf), intent(inout) :: surf
650  integer(kind=kint) :: n, outtype, nodes(100)
651  surf%eid = eid
652 
653  call getsubface( etype, nsurf, outtype, nodes )
654  surf%etype = outtype
655  n=getnumberofnodes( outtype )
656  if(surf%etype == fe_quad4n )then
657  surf%n_intp = 16
658  else if(surf%etype == fe_tri3n )then
659  surf%n_intp = 27
660  else
661  write(*,*) '### Error: MORTAR=YES supports first-order surfaces only (quad4/tri3) : etype=', surf%etype
662  stop hecmw_exit_model
663  end if
664  allocate( surf%nodes(n) )
665  allocate( surf%nslave_index(n) )
666  surf%nodes(1:n)=nodes(1:n)
667  surf%nslave_index(:)= 0
668  ! lam_*_val: dim1 = slave-surf node a (size n), dim2 = rank r (master, size n_intp)
669  allocate( surf%lam_begin_id(surf%n_intp), surf%lam_begin_val(n,surf%n_intp) )
670  allocate( surf%lam_work_id (surf%n_intp), surf%lam_work_val (n,surf%n_intp) )
671  surf%lam_begin_id(:) = 0; surf%lam_begin_val(:,:) = 0.0d0; surf%lam_begin_n = 0
672  surf%lam_work_id (:) = 0; surf%lam_work_val (:,:) = 0.0d0; surf%lam_work_n = 0
673  ! tangential friction parallel arrays: (2, node a, rank r) / (node a, rank r)
674  allocate( surf%lam_begin_t(2,n,surf%n_intp), surf%lam_work_t(2,n,surf%n_intp) )
675  allocate( surf%lam_begin_fstate(n,surf%n_intp), surf%lam_work_fstate(n,surf%n_intp) )
676  surf%lam_begin_t(:,:,:) = 0.0d0; surf%lam_work_t(:,:,:) = 0.0d0
677  surf%lam_begin_fstate(:,:) = contactstick; surf%lam_work_fstate(:,:) = contactstick
678  end subroutine
679 
680 
681 end module mcontactdef
This module provides bucket-search functionality It provides definition of bucket info and its access...
subroutine, public bucketdb_finalize(bktdb)
Finalizer.
subroutine, public bucketdb_init(bktdb)
Initializer.
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
integer(kind=kind(2)) function getnumberofnodes(etype)
Obtain number of nodes of the element.
Definition: element.f90:132
subroutine getsubface(intype, innumber, outtype, nodes)
Find the definition of surface of the element.
Definition: element.f90:194
integer, parameter fe_tri3n
Definition: element.f90:70
integer, parameter fe_quad4n
Definition: element.f90:73
Definition: hecmw.f90:6
subroutine, public hecmw_contact_comm_init(conComm, hecMESH, ndof, n_contact_dof, contact_dofs)
subroutine, public hecmw_contact_comm_finalize(conComm)
This module manages the data structure for contact calculation.
integer, parameter contactslip
integer, parameter sparsity_none
sparsity expansion mode (per contact pair, set by !CONTACT EXPANSION=)
subroutine contact_state_copy(cstate1, cstate2)
Copy.
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(kind=kint) function check_apply_contact_if(contact_if, contacts)
integer, parameter kcsnone
contact smoothing type
integer, parameter contacts2s
integer, parameter contactnear
near contact: projection info available, no LM constraint
subroutine initialize_csurf(eid, etype, nsurf, surf)
Initializer of a slave surface segment (SURF-SURF mortar)
integer, parameter contactunknown
real(kind=kreal), dimension(2), save gnt
1:current average penetration; 2:current relative tangent displacement
logical function fstr_contact_check(contact, hecMESH)
Check the consistency with given mesh of contact definition.
pure logical function is_contact_free(state)
Whether the contact state is completely free (no projection info)
integer(kind=kint) function fstr_count_internal_slaves(contact, hecMESH)
Number of slave nodes of this contact owned by the current rank.
subroutine clear_contact_state(contact)
Reset contact state all to free.
integer, parameter max_n_intp
upper bound of integration points per SURF-SURF slave segment
integer, parameter contactglued
logical function fstr_embed_init(embed, hecMESH, cparam)
Initializer of tContactState for embed case.
integer, parameter contactn2s
contact method
subroutine contact_state_init(cstate)
Initializer.
integer, parameter contacttied
contact type or algorithm definition
pure integer function contact_state_category(state)
Which of the three categories the contact state belongs to.
integer, parameter kctforoutput
compute contact force for output (CONT_NFORCE/CONT_FRIC)
logical function fstr_contact_init(contact, hecMESH, cparam)
Initializer of tContactState.
pure logical function is_contact_active(state)
Whether the contact state has active LM constraint (STICK or SLIP)
subroutine fstr_contact_finalize(contact)
Finalizer.
integer, parameter c_if_slave
contact interference type
integer, parameter kcatfree
contact state category: states sharing a category contribute to the matrix in the same way
real(kind=kreal), dimension(2), save bakgnt
1:current average penetration; 2:current relative tangent displacement!
real(kind=kreal), save cgn
convergent condition of penetration
integer, parameter c_if_master
integer, parameter candidate_intp
SURF-SURF: integration point to be re-projected in this scan.
integer, parameter contactfree
contact state definition
integer, parameter sparsity_neighbor
register current master + neighbors (fewer matrix rebuilds)
integer, parameter contactfslid
real(kind=kreal), save cgt
convergent condition of relative tangent disp
integer, parameter contactstick
integer, parameter kcsnagata
This module manage the parameters for contact calculation.
This module manages surface elements in 3D It provides basic definition of surface elements (triangla...
Definition: surf_ele.f90:8
subroutine initialize_surf(eid, etype, nsurf, surf)
Initializer.
Definition: surf_ele.f90:44
subroutine update_surface_reflen(surf, coord)
Compute reference length of surface elements.
Definition: surf_ele.f90:151
subroutine update_surface_box_info(surf, currpos)
Update info of cubic box including surface elements.
Definition: surf_ele.f90:170
subroutine find_surface_neighbor(surf, bktDB)
Find neighboring surface elements.
Definition: surf_ele.f90:85
subroutine update_surface_bucket_info(surf, bktDB)
Update bucket info for searching surface elements.
Definition: surf_ele.f90:195
subroutine finalize_surf(surf)
Memory management subroutine.
Definition: surf_ele.f90:76
Structure to includes all info needed by contact calculation.
This structure records contact status.
Structure to define a slave surface segment of a SURF-SURF (mortar) contact pair.
Structure to define surface group.
Definition: surf_ele.f90:23