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