FrontISTR  5.9.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  real(kind=kreal) :: distance
78  real(kind=kreal) :: wkdist
79  real(kind=kreal) :: lpos(3)
80  real(kind=kreal) :: gpos(3)
81  real(kind=kreal) :: direction(3)
82  real(kind=kreal) :: multiplier(3)
84  real(kind=kreal) :: tangentforce(3)
85  real(kind=kreal) :: tangentforce1(3)
86  real(kind=kreal) :: tangentforce_trial(3)
87  real(kind=kreal) :: tangentforce_final(3)
88  real(kind=kreal) :: reldisp(3)
89  !
90  real(kind=kreal) :: shrink_factor
91  real(kind=kreal) :: time_factor
92  real(kind=kreal) :: init_pos
93  real(kind=kreal) :: end_pos
94  integer :: interference_flag
95  end type
96 
99  integer(kind=kint) :: eid
100  integer(kind=kint) :: etype
101  integer(kind=kint), pointer :: nodes(:)=>null()
102  integer(kind=kint) :: state = contactfree
103  integer(kind=kint) :: state_prev = contactfree
104  integer(kind=kint) :: n_intp
105  type(tcontactstate), pointer :: states(:)=>null()
106  integer(kind=kint), pointer :: nslave_index(:)=>null()
107  ! --- lambda transaction buffers ---
108  ! begin: previous substep's COMMIT product, immutable during a substep (warm-start source)
109  ! working: current substep's accumulator, cleared at BEGIN, written by the augmentation update
110  integer(kind=kint), pointer :: lam_begin_id(:)=>null()
111  real(kind=kreal), pointer :: lam_begin_val(:,:)=>null()
112  integer(kind=kint) :: lam_begin_n = 0
113  integer(kind=kint), pointer :: lam_work_id(:)=>null()
114  real(kind=kreal), pointer :: lam_work_val(:,:)=>null()
115  integer(kind=kint) :: lam_work_n = 0
116  ! --- tangential friction parallel arrays ---
117  ! per-node covariant tangent multiplier (2 components, node a, rank r) and per-node
118  ! stick/slip state. Rank r is keyed by lam_*_id (master), node a is the slave-surf node;
119  ! both mirror lam_*_val.
120  real(kind=kreal), pointer :: lam_begin_t(:,:,:)=>null()
121  real(kind=kreal), pointer :: lam_work_t(:,:,:)=>null()
122  integer(kind=kint), pointer :: lam_begin_fstate(:,:)=>null()
123  integer(kind=kint), pointer :: lam_work_fstate(:,:)=>null()
124  ! segment state carried in the same transaction (cutback does not restore slave_surf)
125  integer(kind=kint) :: state_begin = contactfree
126  integer(kind=kint) :: state_prev_begin = contactfree
127  end type tcontactsurf
128 
130  type tcontact
131  ! following contact definition
132  character(len=HECMW_NAME_LEN) :: name
133  integer :: ctype
134  integer :: group
135  character(len=HECMW_NAME_LEN) :: pair_name
136  integer :: surf_id1, surf_id2
137  integer :: surf_id1_sgrp
138  type(tsurfelement), pointer :: master(:)=>null()
139  integer :: n_master_owned = 0
140  integer, pointer :: slave(:)=>null()
141  real(kind=kreal) :: fcoeff
142  real(kind=kreal) :: npenalty
143  real(kind=kreal) :: tpenalty
144  real(kind=kreal) :: refstiff
145  real(kind=kreal) :: damp_alpha
146  real(kind=kreal) :: damp_gact
147 
148  type(tcontactsurf), pointer :: slave_surf(:)=>null()
149 
150  ! !CONTACT_INTERFERENCE data; default-initialized because check_apply_Contact_IF only
151  ! writes them when that card is present, while if_type is read unconditionally
152  ! (if_flag = contact%if_type /= 0) by the contact force / search paths.
153  real(kind=kreal) :: ctime = 0.d0
154  integer(kind=kint) :: if_type = 0
155  real(kind=kreal) :: if_etime = 0.d0
156  real(kind=kreal) :: initial_pos = 0.d0
157  real(kind=kreal) :: end_pos = 0.d0
158  ! following algorithm
159  ! -1: not initialized
160  ! 1: TIED-Just rigidly fixed the two surfaces
161  ! 2: GLUED-Distance between the two surfaces to zero and glue them
162  ! 3: SSLID-Small sliding contact( no position but with contact state change)
163  ! 4: FSLID-Finite sliding contact (both changes in contact state and position possible)
164  integer :: algtype
165  integer :: smoothing
166  integer :: method = contactn2s
168  integer :: sparsity_expansion = sparsity_none
169 
170  logical :: mpced
171  logical :: symmetric
172  real(kind=kreal) :: eps_fric_band = 0.d0
173 
174  ! following contact state
175  type(tcontactstate), pointer :: states(:)=>null()
176 
177  type(hecmwst_contact_comm) :: comm
178  type(bucketdb) :: master_bktdb
179 
180  type(tcontactparam), pointer :: cparam=>null()
181  end type tcontact
182 
184  logical :: active
185  integer(kind=kint) :: n_statechange(3,3)
186  integer(kind=kint) :: contact2neighbor
187  integer(kind=kint) :: contact2beyond
188  integer(kind=kint) :: contact2difflpos
189  integer(kind=kint) :: free2contact_new
190  integer(kind=kint) :: contactnode_previous
191  integer(kind=kint) :: contactnode_current
192  end type fstr_info_contactchange
193 
194  private :: is_active_contact
195 
196 contains
197 
199  subroutine contact_state_init(cstate)
200  type(tcontactstate), intent(inout) :: cstate
201  cstate%state = -1
202  cstate%surface = -1
203  cstate%distance = 0.0d0
204  cstate%wkdist = 0.0d0
205  cstate%lpos(:) = 0.0d0
206  cstate%gpos(:) = 0.0d0
207  cstate%direction(:) = 0.0d0
208  cstate%multiplier(:) = 0.0d0
209  cstate%tangentForce(:) = 0.0d0
210  cstate%tangentForce1(:) = 0.0d0
211  cstate%tangentForce_trial(:) = 0.0d0
212  cstate%tangentForce_final(:) = 0.0d0
213  cstate%reldisp(:) = 0.0d0
214  cstate%shrink_factor = 0.0d0
215  cstate%time_factor = 0.0d0
216  cstate%init_pos = 0.0d0
217  cstate%end_pos = 0.0d0
218  cstate%interference_flag = 0
219  end subroutine
220 
222  subroutine contact_state_copy(cstate1, cstate2)
223  type(tcontactstate), intent(in) :: cstate1
224  type(tcontactstate), intent(inout) :: cstate2
225  cstate2 = cstate1
226  end subroutine
227 
229  pure logical function is_contact_active(state)
230  integer, intent(in) :: state
231  is_contact_active = (state >= contactstick)
232  end function
233 
235  pure logical function is_contact_free(state)
236  integer, intent(in) :: state
237  is_contact_free = (state == contactfree)
238  end function
239 
241  pure integer function contact_state_category(state)
242  integer, intent(in) :: state
243  if( is_contact_free(state) ) then
245  else if( is_contact_active(state) ) then
247  else
249  endif
250  end function
251 
253  subroutine fstr_contact_finalize( contact )
254  type(tcontact), intent(inout) :: contact
255  integer :: i
256  if( associated( contact%slave ) ) deallocate(contact%slave)
257  if( associated( contact%master ) ) then
258  do i=1,size( contact%master )
259  call finalize_surf( contact%master(i) )
260  enddo
261  deallocate(contact%master)
262  endif
263  if( associated(contact%states) ) deallocate(contact%states)
264  call hecmw_contact_comm_finalize(contact%comm)
265  call bucketdb_finalize( contact%master_bktDB )
266  end subroutine
267 
269  logical function fstr_contact_check( contact, hecMESH )
270  type(tcontact), intent(inout) :: contact
271  type(hecmwst_local_mesh), pointer :: hecmesh
272 
273  integer :: i
274  logical :: isfind
275 
276  fstr_contact_check = .false.
277 
278  ! if contact pair exist?
279  isfind = .false.
280  do i=1,hecmesh%contact_pair%n_pair
281  if( hecmesh%contact_pair%name(i) == contact%pair_name ) then
282  contact%ctype = hecmesh%contact_pair%type(i)
283  contact%surf_id1 = hecmesh%contact_pair%slave_grp_id(i)
284  contact%surf_id2 = hecmesh%contact_pair%master_grp_id(i)
285  contact%surf_id1_sgrp = hecmesh%contact_pair%slave_orisgrp_id(i)
286  isfind = .true.
287  endif
288  enddo
289  if( .not. isfind ) return;
290  if( contact%fcoeff<=0.d0 ) contact%fcoeff=0.d0
291  if( contact%ctype < 1 .and. contact%ctype > 3 ) return
292  if( contact%group<=0 ) return
293 
294  fstr_contact_check = .true.
295  end function
296 
298  integer(kind=kint) function fstr_count_internal_slaves( contact, hecMESH )
299  type(tcontact), intent(in) :: contact
300  type(hecmwst_local_mesh), pointer :: hecmesh
301 
302  integer :: i, is, ie, cgrp
303 
305 
306  cgrp = contact%surf_id1
307  if( cgrp<=0 ) return
308  is= hecmesh%node_group%grp_index(cgrp-1) + 1
309  ie= hecmesh%node_group%grp_index(cgrp )
310  do i=is,ie
311  if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal ) then
313  endif
314  enddo
315  end function
316 
318  logical function fstr_contact_init( contact, hecMESH, cparam )
319  type(tcontact), intent(inout) :: contact
320  type(hecmwst_local_mesh), pointer :: hecmesh
321  type(tcontactparam), target :: cparam
322 
323  integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
324  integer :: count, id_area
325  logical :: slave_owner, take_master
326  integer, allocatable :: slave_index(:)
327 
328  fstr_contact_init = .false.
329 
330  contact%cparam => cparam
331 
332  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
333 
334  ! update_surface_normal normalises vertex normals only after the cross-rank assembly, so a uniform factor cancels
335  ! but a partial one does not: a rank owning no slave must take no master surface at all, even though the
336  ! partitioner does leave master elements here to keep the communication tables symmetric
337  take_master = .true.
338  if( slave_owner ) take_master = fstr_count_internal_slaves( contact, hecmesh ) > 0
339 
340  ! master surface
341  cgrp = contact%surf_id2
342  if( cgrp<=0 ) return
343  is= hecmesh%surf_group%grp_index(cgrp-1) + 1
344  ie= hecmesh%surf_group%grp_index(cgrp )
345 
346  ! Owned-only master face count, independent of take_master: the SURF-SURF visibility
347  ! guard in fstr_setup sums it over ranks to get the global unique master face count.
348  contact%n_master_owned = 0
349  do i=is,ie
350  ic = hecmesh%surf_group%grp_item(2*i-1)
351  if( hecmesh%elem_ID(ic*2) == hecmesh%my_rank ) contact%n_master_owned = contact%n_master_owned + 1
352  enddo
353 
354  count = 0
355  if( take_master ) then
356  do i=is,ie
357  ic = hecmesh%surf_group%grp_item(2*i-1)
358  id_area = hecmesh%elem_ID(ic*2)
359  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
360  count = count + 1
361  enddo
362  endif
363  allocate( contact%master(count) )
364  count = 0
365  if( take_master ) then
366  do i=is,ie
367  ic = hecmesh%surf_group%grp_item(2*i-1)
368  id_area = hecmesh%elem_ID(ic*2)
369  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
370  count = count + 1
371  nsurf = hecmesh%surf_group%grp_item(2*i)
372  ic_type = hecmesh%elem_type(ic)
373  call initialize_surf( ic, ic_type, nsurf, contact%master(count) )
374  iss = hecmesh%elem_node_index(ic-1)
375  do j=1, size( contact%master(count)%nodes )
376  nn = contact%master(count)%nodes(j)
377  contact%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
378  enddo
379  enddo
380  endif
381 
382  call update_surface_reflen( contact%master, hecmesh%node )
383 
384  cgrp = contact%surf_id1
385  if( cgrp<=0 ) return
386  is= hecmesh%node_group%grp_index(cgrp-1) + 1
387  ie= hecmesh%node_group%grp_index(cgrp )
388  nslave = 0
389  do i=is,ie
390  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
391  nslave = nslave + 1
392  enddo
393  allocate( contact%slave(nslave) )
394  allocate( slave_index(hecmesh%n_node) )
395  slave_index(:) = 0
396  ii = 0
397  do i=is,ie
398  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
399  ii = ii + 1
400  contact%slave(ii) = hecmesh%node_group%grp_item(i)
401  slave_index(contact%slave(ii)) = ii
402  enddo
403 
404  ! contact state
405  allocate( contact%states(nslave) )
406  do i=1,nslave
407  call contact_state_init( contact%states(i) )
408  enddo
409 
410  ! neighborhood of surface group
411  call update_surface_box_info( contact%master, hecmesh%node )
412  call bucketdb_init( contact%master_bktDB )
413  call update_surface_bucket_info( contact%master, contact%master_bktDB )
414  call find_surface_neighbor( contact%master, contact%master_bktDB )
415 
416  if(contact%method == contacts2s) then
417  ! The mortar integral passes the master shape functions through a length-4 array and
418  ! sizes its element vectors for a first-order pair, so a second-order master face
419  ! overruns them. initialize_csurf rejects the slave side for the same reason.
420  do i=1, size( contact%master )
421  if( contact%master(i)%etype /= fe_quad4n .and. contact%master(i)%etype /= fe_tri3n ) then
422  write(*,*) '### Error: MORTAR=YES supports first-order surfaces only (quad4/tri3) : etype=', &
423  contact%master(i)%etype
424  stop hecmw_exit_model
425  endif
426  enddo
427 
428  ! slave surface
429  cgrp = contact%surf_id1_sgrp
430  if( cgrp<=0 ) return
431  is= hecmesh%surf_group%grp_index(cgrp-1) + 1
432  ie= hecmesh%surf_group%grp_index(cgrp )
433 
434  ! Slave segments are taken owned-only (a serial mesh owns every element, so this is
435  ! the full slave surface there). The master surface must be visible in full on every
436  ! slave-owning rank; that is what !PARTITION, CONTACT_OWNER=SLAVE gives and what the
437  ! visibility guard in fstr_setup checks.
438  count = 0
439  do i=is,ie
440  ic = hecmesh%surf_group%grp_item(2*i-1)
441  if( hecmesh%elem_ID(ic*2) /= hecmesh%my_rank ) cycle
442  count = count + 1
443  enddo
444  allocate( contact%slave_surf(count) )
445  count = 0
446  do i=is,ie
447  ic = hecmesh%surf_group%grp_item(2*i-1)
448  if( hecmesh%elem_ID(ic*2) /= hecmesh%my_rank ) cycle
449  count = count + 1
450  nsurf = hecmesh%surf_group%grp_item(2*i)
451  ic_type = hecmesh%elem_type(ic)
452  call initialize_csurf( ic, ic_type, nsurf, contact%slave_surf(count) )
453  iss = hecmesh%elem_node_index(ic-1)
454  do j=1, size( contact%slave_surf(count)%nodes )
455  nn = contact%slave_surf(count)%nodes(j)
456  contact%slave_surf(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
457  contact%slave_surf(count)%nslave_index(j) = slave_index(hecmesh%elem_node_item( iss+nn ))
458  enddo
459  enddo
460 
461  ! state for each integration points
462  do i=1, size( contact%slave_surf )
463  nn = contact%slave_surf(i)%n_intp
464  allocate( contact%slave_surf(i)%states(nn) )
465  do j = 1, contact%slave_surf(i)%n_intp
466  contact%slave_surf(i)%states(j)%state = -1
467  contact%slave_surf(i)%states(j)%multiplier(:) = 0.d0
468  contact%slave_surf(i)%states(j)%tangentForce(:) = 0.d0
469  contact%slave_surf(i)%states(j)%tangentForce1(:) = 0.d0
470  contact%slave_surf(i)%states(j)%tangentForce_trial(:) = 0.d0
471  contact%slave_surf(i)%states(j)%tangentForce_final(:) = 0.d0
472  contact%slave_surf(i)%states(j)%reldisp(:) = 0.d0
473  contact%slave_surf(i)%states(j)%time_factor = 0.d0
474  contact%slave_surf(i)%states(j)%interference_flag = 0
475  enddo
476  enddo
477  endif
478 
479  ! initialize contact communication table
480  call hecmw_contact_comm_init( contact%comm, hecmesh, 1, nslave, contact%slave )
481 
482  contact%symmetric = .true.
483  fstr_contact_init = .true.
484  end function
485 
487  logical function fstr_embed_init( embed, hecMESH, cparam )
488  type(tcontact), intent(inout) :: embed
489  type(hecmwst_local_mesh), pointer :: hecmesh
490  type(tcontactparam), target :: cparam
491 
492  integer :: i, j, is, ie, cgrp, nslave, ic, ic_type, iss, nn, ii
493  integer :: count, id_area
494  logical :: slave_owner, take_master
495 
496  fstr_embed_init = .false.
497 
498  embed%cparam => cparam
499 
500  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
501 
502  take_master = .true.
503  if( slave_owner ) take_master = fstr_count_internal_slaves( embed, hecmesh ) > 0
504 
505  ! master surface
506  cgrp = embed%surf_id2
507  if( cgrp<=0 ) return
508  is= hecmesh%elem_group%grp_index(cgrp-1) + 1
509  ie= hecmesh%elem_group%grp_index(cgrp )
510 
511  count = 0
512  if( take_master ) then
513  do i=is,ie
514  ic = hecmesh%elem_group%grp_item(i)
515  id_area = hecmesh%elem_ID(ic*2)
516  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
517  count = count + 1
518  enddo
519  endif
520  allocate( embed%master(count) )
521  count = 0
522  if( take_master ) then
523  do i=is,ie
524  ic = hecmesh%elem_group%grp_item(i)
525  id_area = hecmesh%elem_ID(ic*2)
526  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
527  count = count + 1
528  ic_type = hecmesh%elem_type(ic)
529  call initialize_surf( ic, ic_type, 0, embed%master(count) )
530  iss = hecmesh%elem_node_index(ic-1)
531  do j=1, size( embed%master(count)%nodes )
532  nn = embed%master(count)%nodes(j)
533  embed%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
534  enddo
535  enddo
536  endif
537 
538  ! slave surface
539  cgrp = embed%surf_id1
540  if( cgrp<=0 ) return
541  is= hecmesh%node_group%grp_index(cgrp-1) + 1
542  ie= hecmesh%node_group%grp_index(cgrp )
543  nslave = 0
544  do i=is,ie
545  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
546  nslave = nslave + 1
547  enddo
548  allocate( embed%slave(nslave) )
549  ii = 0
550  do i=is,ie
551  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
552  ii = ii + 1
553  embed%slave(ii) = hecmesh%node_group%grp_item(i)
554  enddo
555 
556  ! embed state
557  allocate( embed%states(nslave) )
558  do i=1,nslave
559  call contact_state_init( embed%states(i) )
560  enddo
561 
562  ! neighborhood of surface group
563  call update_surface_box_info( embed%master, hecmesh%node )
564  call bucketdb_init( embed%master_bktDB )
565  call update_surface_bucket_info( embed%master, embed%master_bktDB )
566  call find_surface_neighbor( embed%master, embed%master_bktDB )
567 
568  ! initialize contact communication table
569  call hecmw_contact_comm_init( embed%comm, hecmesh, 1, nslave, embed%slave )
570 
571  ! initialize penalty coefficients
572  embed%nPenalty = 1.0d0 ! default normal penalty coefficient
573  embed%tPenalty = 0.1d0 ! default tangential penalty coefficient
574  embed%refStiff = 0.0d0 ! will be calculated after first stiffness assembly
575  embed%damp_alpha = 0.0d0
576  embed%damp_gact = 0.0d0
577 
578  embed%symmetric = .true.
579  fstr_embed_init = .true.
580  end function
581 
582  function check_apply_contact_if( contact_if, contacts )
583  type(tcontactinterference), intent(inout) :: contact_if
584  type(tcontact) :: contacts(:)
585 
586  integer :: i, j
587  logical :: isfind
588  integer(kind=kint) :: check_apply_contact_if
589 
591  ! if contact pair exist?
592  isfind = .false.
593  do i = 1, size(contacts)
594  if( contacts(i)%pair_name == contact_if%cp_name ) then
595  ! !CONTACT_INTERFERENCE is not implemented for the SURF-SURF mortar path
596  if( contacts(i)%method == contacts2s ) then
597  write(*,*) '### Error: CONTACT_INTERFERENCE is not supported with MORTAR=YES'
598  stop hecmw_exit_model
599  endif
600  contacts(i)%if_type = contact_if%if_type
601  contacts(i)%if_etime = contact_if%etime
602  contacts(i)%initial_pos = contact_if%initial_pos
603  contacts(i)%end_pos = contact_if%end_pos
604  do j = 1, size(contacts(i)%states)
605  contacts(i)%states(j)%interference_flag = contact_if%if_type
606  contacts(i)%states(j)%init_pos = contact_if%initial_pos
607  contacts(i)%states(j)%end_pos = contact_if%end_pos
608  if( contact_if%if_type /= c_if_slave )then
609  contacts(i)%states(j)%time_factor = (contact_if%end_pos - contact_if%initial_pos) / contact_if%etime
610  else
611  contacts(i)%states(j)%time_factor = contact_if%etime
612  end if
613  end do
614  isfind = .true.
615  check_apply_contact_if = 0; return
616  endif
617  enddo
618  if( .not. isfind ) return;
620 
621  end function
622 
624  subroutine clear_contact_state( contact )
625  type(tcontact), intent(inout) :: contact
626  integer :: i
627  if( .not. associated(contact%states) ) return
628  do i=1,size( contact%states )
629  contact%states(i)%state = -1
630  enddo
631  end subroutine
632 
634  logical function is_active_contact( acgrp, contact )
635  integer, intent(in) :: acgrp(:)
636  type(tcontact), intent(in) :: contact
637  if( any( acgrp==contact%group ) ) then
638  is_active_contact = .true.
639  else
640  is_active_contact = .false.
641  endif
642  end function
643 
645  subroutine initialize_csurf( eid, etype, nsurf, surf )
646  use elementinfo
647  integer(kind=kint), intent(in) :: eid
648  integer(kind=kint), intent(in) :: etype
649  integer(kind=kint), intent(in) :: nsurf
650  type(tcontactsurf), intent(inout) :: surf
651  integer(kind=kint) :: n, outtype, nodes(100)
652  surf%eid = eid
653 
654  call getsubface( etype, nsurf, outtype, nodes )
655  surf%etype = outtype
656  n=getnumberofnodes( outtype )
657  if(surf%etype == fe_quad4n )then
658  surf%n_intp = 16
659  else if(surf%etype == fe_tri3n )then
660  surf%n_intp = 27
661  else
662  write(*,*) '### Error: MORTAR=YES supports first-order surfaces only (quad4/tri3) : etype=', surf%etype
663  stop hecmw_exit_model
664  end if
665  allocate( surf%nodes(n) )
666  allocate( surf%nslave_index(n) )
667  surf%nodes(1:n)=nodes(1:n)
668  surf%nslave_index(:)= 0
669  ! lam_*_val: dim1 = slave-surf node a (size n), dim2 = rank r (master, size n_intp)
670  allocate( surf%lam_begin_id(surf%n_intp), surf%lam_begin_val(n,surf%n_intp) )
671  allocate( surf%lam_work_id (surf%n_intp), surf%lam_work_val (n,surf%n_intp) )
672  surf%lam_begin_id(:) = 0; surf%lam_begin_val(:,:) = 0.0d0; surf%lam_begin_n = 0
673  surf%lam_work_id (:) = 0; surf%lam_work_val (:,:) = 0.0d0; surf%lam_work_n = 0
674  ! state_begin / state_prev_begin keep their type default (CONTACTFREE)
675  ! tangential friction parallel arrays: (2, node a, rank r) / (node a, rank r)
676  allocate( surf%lam_begin_t(2,n,surf%n_intp), surf%lam_work_t(2,n,surf%n_intp) )
677  allocate( surf%lam_begin_fstate(n,surf%n_intp), surf%lam_work_fstate(n,surf%n_intp) )
678  surf%lam_begin_t(:,:,:) = 0.0d0; surf%lam_work_t(:,:,:) = 0.0d0
679  surf%lam_begin_fstate(:,:) = contactstick; surf%lam_work_fstate(:,:) = contactstick
680  end subroutine
681 
682 
683 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