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 
39  integer, parameter :: contacttied = 1
40  integer, parameter :: contactglued = 2
41  integer, parameter :: contactsslid = 3
42  integer, parameter :: contactfslid = 4
43 
45  integer, parameter :: kcsnone = 0
46  integer, parameter :: kcsnagata = 1
47 
49  integer, parameter :: c_if_slave = 1
50  integer, parameter :: c_if_master = 2
51 
53  integer, parameter :: kctforresidual = 1
54  integer, parameter :: kctforoutput = 2
55 
58  integer :: state
59  integer :: surface
60  real(kind=kreal) :: distance
61  real(kind=kreal) :: wkdist
62  real(kind=kreal) :: lpos(3)
63  real(kind=kreal) :: gpos(3)
64  real(kind=kreal) :: direction(3)
65  real(kind=kreal) :: multiplier(3)
67  real(kind=kreal) :: tangentforce(3)
68  real(kind=kreal) :: tangentforce1(3)
69  real(kind=kreal) :: tangentforce_trial(3)
70  real(kind=kreal) :: tangentforce_final(3)
71  real(kind=kreal) :: reldisp(3)
72  !
73  real(kind=kreal) :: shrink_factor
74  real(kind=kreal) :: time_factor
75  real(kind=kreal) :: init_pos
76  real(kind=kreal) :: end_pos
77  integer :: interference_flag
78  end type
79 
81  type tcontact
82  ! following contact definition
83  character(len=HECMW_NAME_LEN) :: name
84  integer :: ctype
85  integer :: group
86  character(len=HECMW_NAME_LEN) :: pair_name
87  integer :: surf_id1, surf_id2
88  integer :: surf_id1_sgrp
89  type(tsurfelement), pointer :: master(:)=>null()
90  integer, pointer :: slave(:)=>null()
91  real(kind=kreal) :: fcoeff
92  real(kind=kreal) :: npenalty
93  real(kind=kreal) :: tpenalty
94  real(kind=kreal) :: refstiff
95  real(kind=kreal) :: damp_alpha
96  real(kind=kreal) :: damp_gact
97 
98  real(kind=kreal) :: ctime
99  integer(kind=kint) :: if_type
100  real(kind=kreal) :: if_etime
101  real(kind=kreal) :: initial_pos
102  real(kind=kreal) :: end_pos
103  ! following algorithm
104  ! -1: not initialized
105  ! 1: TIED-Just rigidly fixed the two surfaces
106  ! 2: GLUED-Distance between the two surfaces to zero and glue them
107  ! 3: SSLID-Small sliding contact( no position but with contact state change)
108  ! 4: FSLID-Finite sliding contact (both changes in contact state and position possible)
109  integer :: algtype
110  integer :: smoothing
111 
112  logical :: mpced
113  logical :: symmetric
114 
115  ! following contact state
116  type(tcontactstate), pointer :: states(:)=>null()
117 
118  type(hecmwst_contact_comm) :: comm
119  type(bucketdb) :: master_bktdb
120 
121  type(tcontactparam), pointer :: cparam=>null()
122  end type tcontact
123 
125  logical :: active
126  integer(kind=kint) :: contact2free
127  integer(kind=kint) :: contact2neighbor
128  integer(kind=kint) :: contact2difflpos
129  integer(kind=kint) :: free2contact
130  integer(kind=kint) :: contactnode_previous
131  integer(kind=kint) :: contactnode_current
132  end type fstr_info_contactchange
133 
134  private :: is_mpc_available
135  private :: is_active_contact
136 
137 contains
138 
140  subroutine contact_state_init(cstate)
141  type(tcontactstate), intent(inout) :: cstate
142  cstate%state = -1
143  cstate%surface = -1
144  cstate%distance = 0.0d0
145  cstate%wkdist = 0.0d0
146  cstate%lpos(:) = 0.0d0
147  cstate%gpos(:) = 0.0d0
148  cstate%direction(:) = 0.0d0
149  cstate%multiplier(:) = 0.0d0
150  cstate%tangentForce(:) = 0.0d0
151  cstate%tangentForce1(:) = 0.0d0
152  cstate%tangentForce_trial(:) = 0.0d0
153  cstate%tangentForce_final(:) = 0.0d0
154  cstate%reldisp(:) = 0.0d0
155  cstate%shrink_factor = 0.0d0
156  cstate%time_factor = 0.0d0
157  cstate%init_pos = 0.0d0
158  cstate%end_pos = 0.0d0
159  cstate%interference_flag = 0
160  end subroutine
161 
163  subroutine contact_state_copy(cstate1, cstate2)
164  type(tcontactstate), intent(in) :: cstate1
165  type(tcontactstate), intent(inout) :: cstate2
166  cstate2 = cstate1
167  end subroutine
168 
170  pure logical function is_contact_active(state)
171  integer, intent(in) :: state
172  is_contact_active = (state >= contactstick)
173  end function
174 
176  pure logical function has_projection(state)
177  integer, intent(in) :: state
178  has_projection = (state >= contactnear)
179  end function
180 
182  pure logical function is_contact_free(state)
183  integer, intent(in) :: state
184  is_contact_free = (state == contactfree)
185  end function
186 
188  subroutine print_contact_state(fnum, cstate)
189  integer, intent(in) :: fnum
190  type(tcontactstate), intent(in) :: cstate
191  write(fnum, *) "--Contact state=",cstate%state
192  write(fnum, *) cstate%surface, cstate%distance
193  write(fnum, *) cstate%lpos
194  write(fnum, *) cstate%direction
195  write(fnum, *) cstate%multiplier
196  end subroutine
197 
199  logical function is_mpc_available( contact )
200  type(tcontact), intent(in) :: contact
201  is_mpc_available = .true.
202  if( contact%fcoeff/=0.d0 ) is_mpc_available = .false.
203  end function
204 
206  subroutine fstr_write_contact( file, contact )
207  integer(kind=kint), intent(in) :: file
208  type(tcontact), intent(in) :: contact
209  integer :: i
210  write(file,*) "CONTACT:", contact%ctype,contact%group,trim(contact%pair_name),contact%fcoeff
211  write(file,*) "---Slave----"
212  write(file,*) "num.slave",size(contact%slave)
213  if( associated(contact%slave) ) then
214  do i=1,size(contact%slave)
215  write(file, *) contact%slave(i)
216  enddo
217  endif
218  write(file,*) "----master---"
219  write(file,*) "num.master",size(contact%master)
220  if( associated(contact%master) ) then
221  do i=1,size(contact%master)
222  call write_surf( file, contact%master(i) )
223  enddo
224  endif
225  end subroutine
226 
228  subroutine fstr_contact_finalize( contact )
229  type(tcontact), intent(inout) :: contact
230  integer :: i
231  if( associated( contact%slave ) ) deallocate(contact%slave)
232  if( associated( contact%master ) ) then
233  do i=1,size( contact%master )
234  call finalize_surf( contact%master(i) )
235  enddo
236  deallocate(contact%master)
237  endif
238  if( associated(contact%states) ) deallocate(contact%states)
239  call hecmw_contact_comm_finalize(contact%comm)
240  call bucketdb_finalize( contact%master_bktDB )
241  end subroutine
242 
244  logical function fstr_contact_check( contact, hecMESH )
245  type(tcontact), intent(inout) :: contact
246  type(hecmwst_local_mesh), pointer :: hecmesh
247 
248  integer :: i
249  logical :: isfind
250 
251  fstr_contact_check = .false.
252 
253  ! if contact pair exist?
254  isfind = .false.
255  do i=1,hecmesh%contact_pair%n_pair
256  if( hecmesh%contact_pair%name(i) == contact%pair_name ) then
257  contact%ctype = hecmesh%contact_pair%type(i)
258  contact%surf_id1 = hecmesh%contact_pair%slave_grp_id(i)
259  contact%surf_id2 = hecmesh%contact_pair%master_grp_id(i)
260  contact%surf_id1_sgrp = hecmesh%contact_pair%slave_orisgrp_id(i)
261  isfind = .true.
262  endif
263  enddo
264  if( .not. isfind ) return;
265  if( contact%fcoeff<=0.d0 ) contact%fcoeff=0.d0
266  if( contact%ctype < 1 .and. contact%ctype > 3 ) return
267  if( contact%group<=0 ) return
268 
269  fstr_contact_check = .true.
270  end function
271 
273  integer(kind=kint) function fstr_count_internal_slaves( contact, hecMESH )
274  type(tcontact), intent(in) :: contact
275  type(hecmwst_local_mesh), pointer :: hecmesh
276 
277  integer :: i, is, ie, cgrp
278 
280 
281  cgrp = contact%surf_id1
282  if( cgrp<=0 ) return
283  is= hecmesh%node_group%grp_index(cgrp-1) + 1
284  ie= hecmesh%node_group%grp_index(cgrp )
285  do i=is,ie
286  if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal ) then
288  endif
289  enddo
290  end function
291 
293  logical function fstr_contact_init( contact, hecMESH, cparam )
294  type(tcontact), intent(inout) :: contact
295  type(hecmwst_local_mesh), pointer :: hecmesh
296  type(tcontactparam), target :: cparam
297 
298  integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
299  integer :: count, id_area
300  logical :: slave_owner, take_master
301 
302  fstr_contact_init = .false.
303 
304  contact%cparam => cparam
305 
306  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
307 
308  ! update_surface_normal normalises vertex normals only after the cross-rank assembly, so a uniform factor cancels
309  ! but a partial one does not: a rank owning no slave must take no master surface at all, even though the
310  ! partitioner does leave master elements here to keep the communication tables symmetric
311  take_master = .true.
312  if( slave_owner ) take_master = fstr_count_internal_slaves( contact, hecmesh ) > 0
313 
314  ! master surface
315  cgrp = contact%surf_id2
316  if( cgrp<=0 ) return
317  is= hecmesh%surf_group%grp_index(cgrp-1) + 1
318  ie= hecmesh%surf_group%grp_index(cgrp )
319 
320  count = 0
321  if( take_master ) then
322  do i=is,ie
323  ic = hecmesh%surf_group%grp_item(2*i-1)
324  id_area = hecmesh%elem_ID(ic*2)
325  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
326  count = count + 1
327  enddo
328  endif
329  allocate( contact%master(count) )
330  count = 0
331  if( take_master ) then
332  do i=is,ie
333  ic = hecmesh%surf_group%grp_item(2*i-1)
334  id_area = hecmesh%elem_ID(ic*2)
335  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
336  count = count + 1
337  nsurf = hecmesh%surf_group%grp_item(2*i)
338  ic_type = hecmesh%elem_type(ic)
339  call initialize_surf( ic, ic_type, nsurf, contact%master(count) )
340  iss = hecmesh%elem_node_index(ic-1)
341  do j=1, size( contact%master(count)%nodes )
342  nn = contact%master(count)%nodes(j)
343  contact%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
344  enddo
345  enddo
346  endif
347 
348  call update_surface_reflen( contact%master, hecmesh%node )
349 
350  cgrp = contact%surf_id1
351  if( cgrp<=0 ) return
352  is= hecmesh%node_group%grp_index(cgrp-1) + 1
353  ie= hecmesh%node_group%grp_index(cgrp )
354  nslave = 0
355  do i=is,ie
356  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
357  nslave = nslave + 1
358  enddo
359  allocate( contact%slave(nslave) )
360  ii = 0
361  do i=is,ie
362  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
363  ii = ii + 1
364  contact%slave(ii) = hecmesh%node_group%grp_item(i)
365  enddo
366 
367  ! contact state
368  allocate( contact%states(nslave) )
369  do i=1,nslave
370  call contact_state_init( contact%states(i) )
371  enddo
372 
373  ! neighborhood of surface group
374  call update_surface_box_info( contact%master, hecmesh%node )
375  call bucketdb_init( contact%master_bktDB )
376  call update_surface_bucket_info( contact%master, contact%master_bktDB )
377  call find_surface_neighbor( contact%master, contact%master_bktDB )
378 
379  ! initialize contact communication table
380  call hecmw_contact_comm_init( contact%comm, hecmesh, 1, nslave, contact%slave )
381 
382  contact%symmetric = .true.
383  fstr_contact_init = .true.
384  end function
385 
387  logical function fstr_embed_init( embed, hecMESH, cparam )
388  type(tcontact), intent(inout) :: embed
389  type(hecmwst_local_mesh), pointer :: hecmesh
390  type(tcontactparam), target :: cparam
391 
392  integer :: i, j, is, ie, cgrp, nslave, ic, ic_type, iss, nn, ii
393  integer :: count, id_area
394  logical :: slave_owner, take_master
395 
396  fstr_embed_init = .false.
397 
398  embed%cparam => cparam
399 
400  slave_owner = hecmw_partcontact_get_owner( hecmesh%hecmw_flag_partcontact ) == hecmw_flag_partcontact_owner_slave
401 
402  take_master = .true.
403  if( slave_owner ) take_master = fstr_count_internal_slaves( embed, hecmesh ) > 0
404 
405  ! master surface
406  cgrp = embed%surf_id2
407  if( cgrp<=0 ) return
408  is= hecmesh%elem_group%grp_index(cgrp-1) + 1
409  ie= hecmesh%elem_group%grp_index(cgrp )
410 
411  count = 0
412  if( take_master ) then
413  do i=is,ie
414  ic = hecmesh%elem_group%grp_item(i)
415  id_area = hecmesh%elem_ID(ic*2)
416  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
417  count = count + 1
418  enddo
419  endif
420  allocate( embed%master(count) )
421  count = 0
422  if( take_master ) then
423  do i=is,ie
424  ic = hecmesh%elem_group%grp_item(i)
425  id_area = hecmesh%elem_ID(ic*2)
426  if( .not. slave_owner .and. id_area /= hecmesh%my_rank ) cycle
427  count = count + 1
428  ic_type = hecmesh%elem_type(ic)
429  call initialize_surf( ic, ic_type, 0, embed%master(count) )
430  iss = hecmesh%elem_node_index(ic-1)
431  do j=1, size( embed%master(count)%nodes )
432  nn = embed%master(count)%nodes(j)
433  embed%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
434  enddo
435  enddo
436  endif
437 
438  ! slave surface
439  cgrp = embed%surf_id1
440  if( cgrp<=0 ) return
441  is= hecmesh%node_group%grp_index(cgrp-1) + 1
442  ie= hecmesh%node_group%grp_index(cgrp )
443  nslave = 0
444  do i=is,ie
445  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
446  nslave = nslave + 1
447  enddo
448  allocate( embed%slave(nslave) )
449  ii = 0
450  do i=is,ie
451  if( slave_owner .and. hecmesh%node_group%grp_item(i) > hecmesh%nn_internal ) cycle
452  ii = ii + 1
453  embed%slave(ii) = hecmesh%node_group%grp_item(i)
454  enddo
455 
456  ! embed state
457  allocate( embed%states(nslave) )
458  do i=1,nslave
459  call contact_state_init( embed%states(i) )
460  enddo
461 
462  ! neighborhood of surface group
463  call update_surface_box_info( embed%master, hecmesh%node )
464  call bucketdb_init( embed%master_bktDB )
465  call update_surface_bucket_info( embed%master, embed%master_bktDB )
466  call find_surface_neighbor( embed%master, embed%master_bktDB )
467 
468  ! initialize contact communication table
469  call hecmw_contact_comm_init( embed%comm, hecmesh, 1, nslave, embed%slave )
470 
471  ! initialize penalty coefficients
472  embed%nPenalty = 1.0d0 ! default normal penalty coefficient
473  embed%tPenalty = 0.1d0 ! default tangential penalty coefficient
474  embed%refStiff = 0.0d0 ! will be calculated after first stiffness assembly
475  embed%damp_alpha = 0.0d0
476  embed%damp_gact = 0.0d0
477 
478  embed%symmetric = .true.
479  fstr_embed_init = .true.
480  end function
481 
482  function check_apply_contact_if( contact_if, contacts )
483  type(tcontactinterference), intent(inout) :: contact_if
484  type(tcontact) :: contacts(:)
485 
486  integer :: i, j
487  logical :: isfind
488  integer(kind=kint) :: check_apply_contact_if
489 
491  ! if contact pair exist?
492  isfind = .false.
493  do i = 1, size(contacts)
494  if( contacts(i)%pair_name == contact_if%cp_name ) then
495  contacts(i)%if_type = contact_if%if_type
496  contacts(i)%if_etime = contact_if%etime
497  contacts(i)%initial_pos = contact_if%initial_pos
498  contacts(i)%end_pos = contact_if%end_pos
499  do j = 1, size(contacts(i)%states)
500  contacts(i)%states(j)%interference_flag = contact_if%if_type
501  contacts(i)%states(j)%init_pos = contact_if%initial_pos
502  contacts(i)%states(j)%end_pos = contact_if%end_pos
503  if( contact_if%if_type /= c_if_slave )then
504  contacts(i)%states(j)%time_factor = (contact_if%end_pos - contact_if%initial_pos) / contact_if%etime
505  else
506  contacts(i)%states(j)%time_factor = contact_if%etime
507  end if
508  end do
509  isfind = .true.
510  check_apply_contact_if = 0; return
511  endif
512  enddo
513  if( .not. isfind ) return;
515 
516  end function
517 
519  subroutine clear_contact_state( contact )
520  type(tcontact), intent(inout) :: contact
521  integer :: i
522  if( .not. associated(contact%states) ) return
523  do i=1,size( contact%states )
524  contact%states(i)%state = -1
525  enddo
526  end subroutine
527 
529  logical function is_active_contact( acgrp, contact )
530  integer, intent(in) :: acgrp(:)
531  type(tcontact), intent(in) :: contact
532  if( any( acgrp==contact%group ) ) then
533  is_active_contact = .true.
534  else
535  is_active_contact = .false.
536  endif
537  end function
538 
540  subroutine print_contatct_pair( file, pair )
541  integer(kind=kint), intent(in) :: file
542  type( hecmwst_contact_pair ), intent(in) :: pair
543 
544  integer(kind=kint) :: i
545  write(file,*) "Number of contact pair", pair%n_pair
546  do i=1,pair%n_pair
547  write(file,*) trim(pair%name(i)), pair%type(i), pair%slave_grp_id(i) &
548  ,pair%master_grp_id(i), pair%slave_orisgrp_id(i)
549  enddo
550  end subroutine
551 
552 
553 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
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
subroutine contact_state_copy(cstate1, cstate2)
Copy.
integer, parameter contactsslid
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 contactnear
near contact: projection info available, no LM constraint
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 contactglued
logical function fstr_embed_init(embed, hecMESH, cparam)
Initializer of tContactState for embed case.
subroutine contact_state_init(cstate)
Initializer.
integer, parameter contacttied
contact type or algorithm definition
integer, parameter kctforoutput
compute contact force for output (CONT_NFORCE/CONT_FRIC)
logical function fstr_contact_init(contact, hecMESH, cparam)
Initializer of tContactState.
subroutine fstr_write_contact(file, contact)
Write out contact definition.
subroutine print_contatct_pair(file, pair)
Write out the contact definition read from mesh file.
subroutine print_contact_state(fnum, cstate)
Print out contact state.
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
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 contactfree
contact state definition
integer, parameter contactfslid
real(kind=kreal), save cgt
convergent condition of relative tangent disp
integer, parameter contactstick
integer, parameter kcsnagata
pure logical function has_projection(state)
Whether the contact state has valid projection info (NEAR, STICK, or SLIP)
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:225
subroutine write_surf(file, surf)
Write out elemental surface.
Definition: surf_ele.f90:85
subroutine update_surface_box_info(surf, currpos)
Update info of cubic box including surface elements.
Definition: surf_ele.f90:244
subroutine find_surface_neighbor(surf, bktDB)
Find neighboring surface elements.
Definition: surf_ele.f90:97
subroutine update_surface_bucket_info(surf, bktDB)
Update bucket info for searching surface elements.
Definition: surf_ele.f90:269
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 surface group.
Definition: surf_ele.f90:23