FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_contact_search.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 !-------------------------------------------------------------------------------
8  use m_fstr
9  use hecmw
10  use elementinfo
11  use mcontactdef
16  implicit none
17 
18  integer(kind=kint), parameter :: contact_log_level = 0
19 
20 contains
21 
25  subroutine track_contact_position( nslave, contact, currpos, currdisp, infoCTChange, nodeID, elemID, flag_ctAlgo )
26  integer, intent(in) :: nslave
27  type( tcontact ), intent(inout) :: contact
28  type( fstr_info_contactchange ), intent(inout) :: infoCTChange
29  real(kind=kreal), intent(in) :: currpos(:)
30  real(kind=kreal), intent(in) :: currdisp(:)
31  integer(kind=kint), intent(in) :: nodeID(:)
32  integer(kind=kint), intent(in) :: elemID(:)
33  character(len=9), intent(in), optional :: flag_ctAlgo
34 
35  integer(kind=kint) :: slave, sid0, sid, etype
36  integer(kind=kint) :: nn, i, j, iSS
37  real(kind=kreal) :: coord(3), elem(3, l_max_elem_node), elem0(3, l_max_elem_node)
38  logical :: isin
39  real(kind=kreal) :: opos(2)
40  integer(kind=kint) :: bktID, nCand, idm
41  integer(kind=kint), allocatable :: indexCand(:)
42  logical :: is_implicit
43 
44  is_implicit = present(flag_ctalgo)
45 
46  sid = 0
47 
48  slave = contact%slave(nslave)
49  coord(:) = currpos(3*slave-2:3*slave)
51  sid0 = contact%states(nslave)%surface
52  opos = contact%states(nslave)%lpos(1:2)
53  etype = contact%master(sid0)%etype
54  nn = getnumberofnodes( etype )
55  do j=1,nn
56  iss = contact%master(sid0)%nodes(j)
57  elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
58  enddo
59  call project_point2surfelement( coord, contact%master(sid0), currpos, &
60  contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
61  contact%states(nslave)%lpos(1:2), contact%cparam%CLR_SAME_ELEM, smoothing=contact%smoothing )
62  if( .not. isin ) then
63  do i=1, contact%master(sid0)%n_neighbor
64  sid = contact%master(sid0)%neighbor(i)
65  call project_point2surfelement( coord, contact%master(sid), currpos, &
66  contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
67  localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
68  if( isin ) then
69  contact%states(nslave)%surface = sid
70  exit
71  endif
72  enddo
73  endif
74 
75  if( .not. isin ) then ! such case is considered to rarely or never occur
76  write(*,*) 'Warning: contact moved beyond neighbor elements'
77  ! get master candidates from bucketDB
78  bktid = bucketdb_getbucketid(contact%master_bktDB, coord)
79  ncand = bucketdb_getnumcand(contact%master_bktDB, bktid)
80  if (ncand > 0) then
81  allocate(indexcand(ncand))
82  call bucketdb_getcand(contact%master_bktDB, bktid, ncand, indexcand)
83  do idm= 1, ncand
84  sid = indexcand(idm)
85  if( sid==sid0 ) cycle
86  if( associated(contact%master(sid0)%neighbor) ) then
87  if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
88  endif
89  if (.not. is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
90  call project_point2surfelement( coord, contact%master(sid), currpos, &
91  contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
92  localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
93  if( isin ) then
94  contact%states(nslave)%surface = sid
95  exit
96  endif
97  enddo
98  deallocate(indexcand)
99  endif
100  endif
101 
102  if( isin ) then
103  if( contact%states(nslave)%surface==sid0 ) then
104  if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS)) then
105  !$omp atomic
106  infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
107  endif
108  else
109  if (contact_log_level >= 1) write(*,'(A,i10,A,i10,A,f7.3,A,2f7.3)') "Node",nodeid(slave)," move to contact with", &
110  elemid(contact%master(sid)%eid), " with distance ", &
111  contact%states(nslave)%distance," at ",contact%states(nslave)%lpos(1:2)
112  !$omp atomic
113  infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
114  endif
115  if( is_implicit .and. flag_ctalgo=='SLagrange' ) then
116  ! Setup elem array for update_TangentForce
117  etype = contact%master(contact%states(nslave)%surface)%etype
118  nn = size(contact%master(contact%states(nslave)%surface)%nodes)
119  do j=1,nn
120  iss = contact%master(contact%states(nslave)%surface)%nodes(j)
121  elem(1:3,j)=currpos(3*iss-2:3*iss)
122  enddo
123  call update_tangentforce(etype,nn,elem0,elem,contact%states(nslave))
124  endif
125  iss = isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
126  if( iss>0 ) &
127  call cal_node_normal( contact%states(nslave)%surface, iss, contact%master, currpos, &
128  contact%states(nslave)%lpos(1:2), contact%states(nslave)%direction(:) )
129  else if( .not. isin ) then
130  if (contact_log_level >= 1) write(*,'(A,i10,A)') "Node",nodeid(slave)," move out of contact"
131  contact%states(nslave)%state = contactfree
132  contact%states(nslave)%multiplier(:) = 0.d0
133  endif
134 
135  end subroutine track_contact_position
136 
144  subroutine scan_contact_state( contact, currpos, currdisp, infoCTChange, &
145  nodeID, elemID, is_init, active, hecMESH, flag_ctAlgo, ndforce )
146  type( tcontact ), intent(inout) :: contact
147  type( fstr_info_contactchange ), intent(inout) :: infoCTChange
148  real(kind=kreal), intent(in) :: currpos(:)
149  real(kind=kreal), intent(in) :: currdisp(:)
150  integer(kind=kint), intent(in) :: nodeID(:)
151  integer(kind=kint), intent(in) :: elemID(:)
152  logical, intent(in) :: is_init
153  logical, intent(out) :: active
154  type( hecmwst_local_mesh ), intent(in), optional :: hecMESH
155  character(len=9), intent(in), optional :: flag_ctAlgo
156  real(kind=kreal), intent(in), optional :: ndforce(:)
157 
158  real(kind=kreal) :: distclr
159  integer(kind=kint) :: slave, id, etype
160  integer(kind=kint) :: i, iSS, nactive
161  real(kind=kreal) :: coord(3)
162  real(kind=kreal) :: nlforce
163  logical :: isin
164  integer(kind=kint), allocatable :: contact_surf(:), states_prev(:)
165  real(kind=kreal) :: effective_near_dist, distclr_use
166  !
167  integer, pointer :: indexMaster(:),indexCand(:)
168  integer :: nMaster,idm,nMasterMax,bktID,nCand
169  logical :: is_implicit
170 
171  is_implicit = present(flag_ctalgo)
172 
173  if( is_init ) then
174  distclr = contact%cparam%DISTCLR_INIT
175  else
176  distclr = contact%cparam%DISTCLR_FREE
177  if( contact%algtype == contacttied ) then
178  active = .false.
179  do i= 1, size(contact%slave)
180  if( contact%states(i)%state==contactstick ) then
181  active = .true.
182  exit
183  endif
184  enddo
185  endif
186  endif
187 
188  allocate(contact_surf(size(nodeid)))
189  allocate(states_prev(size(contact%slave)))
190  contact_surf(:) = huge(0)
191  do i = 1, size(contact%slave)
192  states_prev(i) = contact%states(i)%state
193  enddo
194 
195  if( contact%smoothing == kcsnagata ) then
196  call update_surface_normal( contact%master, currpos, hecmesh )
197  call create_intermediate_points( contact%master, currpos, contact%pair_name )
198  endif
199 
200  call update_surface_box_info( contact%master, currpos )
201  call update_surface_bucket_info( contact%master, contact%master_bktDB )
202 
203  ! Compute effective near distance for CONTACTNEAR detection
204  ! If damping is configured (damp_gact > 0), use it as the near distance
205  effective_near_dist = contact%cparam%NEAR_DIST
206  if (contact%damp_gact > 0.0d0) then
207  effective_near_dist = max(effective_near_dist, contact%damp_gact)
208  endif
209 
210  !$omp parallel do &
211  !$omp& default(none) &
212  !$omp& private(i,slave,id,nlforce,coord,indexMaster,nMaster,iSS,idm,etype,isin, &
213  !$omp& bktID,nCand,indexCand,distclr_use) &
214  !$omp& firstprivate(nMasterMax,is_implicit,effective_near_dist) &
215  !$omp& shared(contact,ndforce,flag_ctAlgo,infoCTChange,currpos,currdisp,nodeID,elemID,distclr,contact_surf,is_init) &
216  !$omp& reduction(.or.:active) &
217  !$omp& schedule(dynamic,1)
218  do i= 1, size(contact%slave)
219  if(contact%if_type /= 0) call set_shrink_factor(contact%ctime, contact%states(i), contact%if_etime, contact%if_type)
220  slave = contact%slave(i)
221  if( contact%states(i)%state==contactstick .or. contact%states(i)%state==contactslip ) then
222  id = contact%states(i)%surface
223  nlforce = contact%states(i)%multiplier(1)
224 
225  ! update direction of TIED contact
226  if( contact%algtype == contacttied ) then
227  call update_direction( i, contact, currpos )
228  if (.not.is_init) cycle
229  endif
230 
231  if( nlforce < contact%cparam%TENSILE_FORCE ) then
232  contact%states(i)%state = contactfree
233  contact%states(i)%multiplier(:) = 0.d0
234  if (contact_log_level >= 1) write(*,'(A,i10,A,i10,A,e12.3)') "Node",nodeid(slave)," free from contact with element", &
235  elemid(contact%master(id)%eid), " with tensile force ", nlforce
236  cycle
237  endif
238  if( contact%algtype /= contactfslid ) then ! small slide problem
239  contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
240  else
241  if( is_implicit ) then
242  call track_contact_position( i, contact, currpos, currdisp, infoctchange, nodeid, elemid, &
243  flag_ctalgo=flag_ctalgo )
244  else
245  call track_contact_position( i, contact, currpos, currdisp, infoctchange, nodeid, elemid )
246  endif
247  if( contact%states(i)%state /= contactfree ) then
248  id = contact%states(i)%surface
249  contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
250  endif
251  endif
252 
253  else if( contact%states(i)%state==contactnear ) then
254  ! NEAR tracking: re-project on current master surface
255  coord(:) = currpos(3*slave-2:3*slave)
256  id = contact%states(i)%surface
257  if (effective_near_dist > 0.0d0) then
258  distclr_use = max(distclr, effective_near_dist / contact%master(id)%reflen)
259  else
260  distclr_use = distclr
261  end if
262  call project_point2surfelement( coord, contact%master(id), currpos, &
263  contact%states(i), isin, distclr_use, &
264  contact%states(i)%lpos(1:2), contact%cparam%CLR_SAME_ELEM, smoothing=contact%smoothing )
265  if (isin) then
266  if (contact%states(i)%distance <= distclr * contact%master(id)%reflen) then
267  ! Within contact threshold -> upgrade to STICK
268  contact%states(i)%state = contactstick
269  contact%states(i)%multiplier(:) = 0.d0
270  if (contact_log_level >= 1) write(*,'(A,i10,A,i10,A,i6)') "Node",nodeid(slave)," upgraded NEAR->STICK on element", &
271  elemid(contact%master(id)%eid)," rank=",hecmw_comm_get_rank()
272  else if (contact%states(i)%distance > effective_near_dist) then
273  ! Beyond NEAR range -> free
274  contact%states(i)%state = contactfree
275  contact%states(i)%multiplier(:) = 0.d0
276  end if
277  ! else: stay NEAR
278  if (.not. is_contact_free(contact%states(i)%state)) then
279  etype = contact%master(id)%etype
280  iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
281  if( iss>0 ) &
282  call cal_node_normal( id, iss, contact%master, currpos, &
283  contact%states(i)%lpos(1:2), contact%states(i)%direction(:) )
284  contact_surf(contact%slave(i)) = elemid(contact%master(id)%eid)
285  end if
286  else
287  ! Lost projection -> free
288  contact%states(i)%state = contactfree
289  contact%states(i)%multiplier(:) = 0.d0
290  end if
291 
292  else if( contact%states(i)%state==contactfree ) then
293  if( contact%algtype == contacttied .and. .not. is_init ) cycle
294  coord(:) = currpos(3*slave-2:3*slave)
295 
296  ! get master candidates from bucketDB
297  bktid = bucketdb_getbucketid(contact%master_bktDB, coord)
298  ncand = bucketdb_getnumcand(contact%master_bktDB, bktid)
299  if (ncand == 0) cycle
300  allocate(indexcand(ncand))
301  call bucketdb_getcand(contact%master_bktDB, bktid, ncand, indexcand)
302 
303  nmastermax = ncand
304  allocate(indexmaster(nmastermax))
305  nmaster = 0
306 
307  ! narrow down candidates
308  do idm= 1, ncand
309  id = indexcand(idm)
310  if (.not. is_in_surface_box( contact%master(id), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
311  nmaster = nmaster + 1
312  indexmaster(nmaster) = id
313  enddo
314  deallocate(indexcand)
315 
316  if(nmaster == 0) then
317  deallocate(indexmaster)
318  cycle
319  endif
320 
321  do idm = 1,nmaster
322  id = indexmaster(idm)
323  ! Expand distclr for NEAR detection
324  if (effective_near_dist > 0.0d0) then
325  distclr_use = max(distclr, effective_near_dist / contact%master(id)%reflen)
326  else
327  distclr_use = distclr
328  end if
329  call project_point2surfelement( coord, contact%master(id), currpos, &
330  contact%states(i), isin, distclr_use, localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
331  if( .not. isin ) cycle
332  ! Classify: STICK or NEAR
333  if (effective_near_dist > 0.0d0 .and. &
334  contact%states(i)%distance > distclr * contact%master(id)%reflen) then
335  contact%states(i)%state = contactnear
336  end if
337  contact%states(i)%surface = id
338  contact%states(i)%multiplier(:) = 0.d0
339  etype = contact%master(id)%etype
340  iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
341  if( iss>0 ) &
342  call cal_node_normal( id, iss, contact%master, currpos, contact%states(i)%lpos(1:2), &
343  contact%states(i)%direction(:) )
344  contact_surf(contact%slave(i)) = elemid(contact%master(id)%eid)
345  if (contact_log_level >= 1) then
346  if (contact%states(i)%state == contactnear) then
347  write(*,'(A,i10,A,i10,A,f7.3,A,i6)') "Node",nodeid(slave)," near element", &
348  elemid(contact%master(id)%eid), &
349  " with distance ", contact%states(i)%distance," rank=",hecmw_comm_get_rank()
350  else
351  write(*,'(A,i10,A,i10,A,f7.3,A,2f7.3,A,3f7.3,A,i6)') "Node",nodeid(slave)," contact with element", &
352  elemid(contact%master(id)%eid), &
353  " with distance ", contact%states(i)%distance," at ",contact%states(i)%lpos(1:2), &
354  " along direction ", contact%states(i)%direction," rank=",hecmw_comm_get_rank()
355  end if
356  end if
357  exit
358  enddo
359  deallocate(indexmaster)
360  endif
361  enddo
362  !$omp end parallel do
363 
364  if( contact%algtype == contacttied .and. .not. is_init ) then
365  deallocate(contact_surf)
366  deallocate(states_prev)
367  return
368  endif
369 
370  call hecmw_contact_comm_allreduce_i(contact%comm, contact_surf, hecmw_min)
371  nactive = 0
372  do i = 1, size(contact%slave)
373  if (.not. is_contact_free(contact%states(i)%state)) then ! any slave in contact or near
374  id = contact%states(i)%surface
375  if (abs(contact_surf(contact%slave(i))) /= elemid(contact%master(id)%eid)) then ! that is in contact with other surface
376  contact%states(i)%state = contactfree ! should be freed
377  if (contact_log_level >= 1) &
378  & write(*,'(A,i10,A,i10,A,i6,A,i6,A)') "Node",nodeid(contact%slave(i)), &
379  & " contact with element",elemid(contact%master(id)%eid), &
380  & " in rank",hecmw_comm_get_rank()," freed due to duplication"
381  else if (is_contact_active(contact%states(i)%state)) then
382  nactive = nactive + 1
383  endif
384  endif
385  if (is_contact_free(states_prev(i)) .and. .not. is_contact_free(contact%states(i)%state)) then
386  infoctchange%free2contact = infoctchange%free2contact + 1
387  elseif (.not. is_contact_free(states_prev(i)) .and. is_contact_free(contact%states(i)%state)) then
388  infoctchange%contact2free = infoctchange%contact2free + 1
389  endif
390  enddo
391  active = (nactive > 0)
392  deallocate(contact_surf)
393  deallocate(states_prev)
394  end subroutine scan_contact_state
395 
399  subroutine scan_embed_state( flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, &
400  nodeID, elemID, is_init, active, B )
401  character(len=9), intent(in) :: flag_ctAlgo
402  type( tcontact ), intent(inout) :: embed
403  type( fstr_info_contactchange ), intent(inout) :: infoCTChange
404  real(kind=kreal), intent(in) :: currpos(:)
405  real(kind=kreal), intent(in) :: currdisp(:)
406  real(kind=kreal), intent(in) :: ndforce(:)
407  integer(kind=kint), intent(in) :: nodeID(:)
408  integer(kind=kint), intent(in) :: elemID(:)
409  logical, intent(in) :: is_init
410  logical, intent(out) :: active
411  real(kind=kreal), optional, target :: b(:)
412 
413  real(kind=kreal) :: distclr
414  integer(kind=kint) :: slave, id, etype
415  integer(kind=kint) :: nn, i, j, iSS, nactive
416  real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
417  logical :: isin
418  integer(kind=kint), allocatable :: contact_surf(:), states_prev(:)
419  !
420  integer, pointer :: indexMaster(:),indexCand(:)
421  integer :: nMaster,idm,nMasterMax,bktID,nCand
422  logical :: is_present_B
423  real(kind=kreal), pointer :: bp(:)
424 
425  if( is_init ) then
426  distclr = embed%cparam%DISTCLR_INIT
427  else
428  distclr = embed%cparam%DISTCLR_FREE
429  active = .false.
430  do i= 1, size(embed%slave)
431  if( embed%states(i)%state==contactstick ) then
432  active = .true.
433  exit
434  endif
435  enddo
436  return
437  endif
438 
439  allocate(contact_surf(size(nodeid)))
440  allocate(states_prev(size(embed%slave)))
441  contact_surf(:) = huge(0)
442  do i = 1, size(embed%slave)
443  states_prev(i) = embed%states(i)%state
444  enddo
445 
446  call update_surface_box_info( embed%master, currpos )
447  call update_surface_bucket_info( embed%master, embed%master_bktDB )
448 
449  ! for gfortran-10: optional parameter seems not allowed within omp parallel
450  is_present_b = present(b)
451  if( is_present_b ) bp => b
452 
453  !$omp parallel do &
454  !$omp& default(none) &
455  !$omp& private(i,slave,id,coord,indexMaster,nMaster,nn,j,iSS,elem,idm,etype,isin, &
456  !$omp& bktID,nCand,indexCand) &
457  !$omp& firstprivate(nMasterMax,is_present_B) &
458  !$omp& shared(embed,ndforce,flag_ctAlgo,infoCTChange,currpos,currdisp,nodeID,elemID,Bp,distclr,contact_surf) &
459  !$omp& reduction(.or.:active) &
460  !$omp& schedule(dynamic,1)
461  do i= 1, size(embed%slave)
462  slave = embed%slave(i)
463  if( embed%states(i)%state==contactfree ) then
464  coord(:) = currpos(3*slave-2:3*slave)
465 
466  ! get master candidates from bucketDB
467  bktid = bucketdb_getbucketid(embed%master_bktDB, coord)
468  ncand = bucketdb_getnumcand(embed%master_bktDB, bktid)
469  if (ncand == 0) cycle
470  allocate(indexcand(ncand))
471  call bucketdb_getcand(embed%master_bktDB, bktid, ncand, indexcand)
472 
473  nmastermax = ncand
474  allocate(indexmaster(nmastermax))
475  nmaster = 0
476 
477  ! narrow down candidates
478  do idm= 1, ncand
479  id = indexcand(idm)
480  if (.not. is_in_surface_box( embed%master(id), coord(1:3), embed%cparam%BOX_EXP_RATE )) cycle
481  nmaster = nmaster + 1
482  indexmaster(nmaster) = id
483  enddo
484  deallocate(indexcand)
485 
486  if(nmaster == 0) then
487  deallocate(indexmaster)
488  cycle
489  endif
490 
491  do idm = 1,nmaster
492  id = indexmaster(idm)
493  etype = embed%master(id)%etype
494  if( mod(etype,10) == 2 ) etype = etype - 1 !search by 1st-order shape function
495  nn = getnumberofnodes(etype)
496  do j=1,nn
497  iss = embed%master(id)%nodes(j)
498  elem(1:3,j)=currpos(3*iss-2:3*iss)
499  enddo
500  call project_point2solidelement( coord,etype,nn,elem,embed%master(id)%reflen,embed%states(i), &
501  isin,distclr,localclr=embed%cparam%CLEARANCE )
502  if( .not. isin ) cycle
503  embed%states(i)%surface = id
504  embed%states(i)%multiplier(:) = 0.d0
505  contact_surf(embed%slave(i)) = elemid(embed%master(id)%eid)
506  if (contact_log_level >= 1) write(*,'(A,i10,A,i10,A,3f7.3,A,i6)') "Node",nodeid(slave)," embeded to element", &
507  elemid(embed%master(id)%eid), " at ",embed%states(i)%lpos(:)," rank=",hecmw_comm_get_rank()
508  exit
509  enddo
510  deallocate(indexmaster)
511  endif
512  enddo
513  !$omp end parallel do
514 
515  call hecmw_contact_comm_allreduce_i(embed%comm, contact_surf, hecmw_min)
516  nactive = 0
517  do i = 1, size(embed%slave)
518  if (embed%states(i)%state /= contactfree) then ! any slave in contact
519  id = embed%states(i)%surface
520  if (abs(contact_surf(embed%slave(i))) /= elemid(embed%master(id)%eid)) then ! that is in contact with other surface
521  embed%states(i)%state = contactfree ! should be freed
522  if (contact_log_level >= 1) write(*,'(A,i10,A,i10,A,i6,A,i6,A)') "Node",nodeid(embed%slave(i))," contact with element", &
523  & elemid(embed%master(id)%eid), " in rank",hecmw_comm_get_rank()," freed due to duplication"
524  else
525  nactive = nactive + 1
526  endif
527  endif
528  if (states_prev(i) == contactfree .and. embed%states(i)%state /= contactfree) then
529  infoctchange%free2contact = infoctchange%free2contact + 1
530  elseif (states_prev(i) /= contactfree .and. embed%states(i)%state == contactfree) then
531  infoctchange%contact2free = infoctchange%contact2free + 1
532  endif
533  enddo
534  active = (nactive > 0)
535  deallocate(contact_surf)
536  deallocate(states_prev)
537  end subroutine scan_embed_state
538 
540  subroutine remove_duplication_tiedcontact( cstep, hecMESH, fstrSOLID, infoCTChange )
541  integer(kind=kint), intent(in) :: cstep
542  type( hecmwst_local_mesh ), intent(in) :: hecMESH
543  type(fstr_solid), intent(inout) :: fstrSOLID
544  type(fstr_info_contactchange), intent(inout):: infoCTChange
545 
546  integer(kind=kint) :: i, j, grpid, slave
547  integer(kind=kint) :: k, id, iSS
548  integer(kind=kint) :: ig0, ig, iS0, iE0
549  integer(kind=kint), allocatable :: states(:)
550 
551  allocate(states(hecmesh%n_node))
552  states(:) = contactfree
553 
554  ! if a boundary condition is given, the slave
555  do ig0= 1, fstrsolid%BOUNDARY_ngrp_tot
556  grpid = fstrsolid%BOUNDARY_ngrp_GRPID(ig0)
557  if( .not. fstr_isboundaryactive( fstrsolid, grpid, cstep ) ) cycle
558  ig= fstrsolid%BOUNDARY_ngrp_ID(ig0)
559  is0= hecmesh%node_group%grp_index(ig-1) + 1
560  ie0= hecmesh%node_group%grp_index(ig )
561  do k= is0, ie0
562  iss = hecmesh%node_group%grp_item(k)
563  !states(iSS) = CONTACTSTICK
564  enddo
565  enddo
566 
567  do i=1,fstrsolid%n_contacts
568  if( fstrsolid%contacts(i)%algtype /= contacttied ) cycle
569  grpid = fstrsolid%contacts(i)%group
570  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
571 
572  do j=1, size(fstrsolid%contacts(i)%slave)
573  if( is_contact_free(fstrsolid%contacts(i)%states(j)%state) ) cycle ! free
574  slave = fstrsolid%contacts(i)%slave(j)
575  if( is_contact_free(states(slave)) ) then
576  states(slave) = fstrsolid%contacts(i)%states(j)%state
577  id = fstrsolid%contacts(i)%states(j)%surface
578  do k=1,size( fstrsolid%contacts(i)%master(id)%nodes )
579  iss = fstrsolid%contacts(i)%master(id)%nodes(k)
580  states(iss) = fstrsolid%contacts(i)%states(j)%state
581  enddo
582  else !found duplicate tied contact slave node
583  fstrsolid%contacts(i)%states(j)%state = contactfree
584  infoctchange%free2contact = infoctchange%free2contact - 1
585  if (contact_log_level >= 1) write(*,'(A,i10,A,i6,A,i6,A)') "Node",hecmesh%global_node_ID(slave), &
586  " in rank",hecmw_comm_get_rank()," freed due to duplication"
587  endif
588  enddo
589  enddo
590 
591  end subroutine
592 
593 end module m_fstr_contact_search
594 
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:131
integer function isinsideelement(fetype, localcoord, clearance)
if a point is inside a surface element -1: No; 0: Yes; >0: Node's (vertex) number
Definition: element.f90:1036
Definition: hecmw.f90:6
Contact mechanics calculations at element level (single contact pair)
This module provides geometric calculations for contact.
subroutine project_point2solidelement(xyz, etype, nn, elemt, reflen, cstate, isin, distclr, ctpos, localclr)
This subroutine find the projection of a slave point onto master surface.
subroutine project_point2surfelement(xyz, surf, currpos, cstate, isin, distclr, ctpos, localclr, smoothing)
Wrapper for project_Point2Element that takes tSurfElement structure This subroutine handles element c...
subroutine update_direction(nslave, contact, currpos)
This subroutine tracks down next contact position after a finite slide.
subroutine, public cal_node_normal(csurf, isin, surf, currpos, lpos, normal)
Calculate averaged nodal normal.
This module provides interference fit (shrink) functions for contact.
subroutine, public set_shrink_factor(ctime, cstate, etime, if_type)
Contact search and state scanning at search level (all pairs in one tContact)
subroutine track_contact_position(nslave, contact, currpos, currdisp, infoCTChange, nodeID, elemID, flag_ctAlgo)
This subroutine tracks down next contact position after a finite slide When flag_ctAlgo is present,...
subroutine scan_contact_state(contact, currpos, currdisp, infoCTChange, nodeID, elemID, is_init, active, hecMESH, flag_ctAlgo, ndforce)
This subroutine update contact states, which include.
integer(kind=kint), parameter contact_log_level
Set >= 1 to enable per-node contact log output (for debugging)
subroutine remove_duplication_tiedcontact(cstep, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
subroutine scan_embed_state(flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, nodeID, elemID, is_init, active, B)
This subroutine update contact states, which include.
Contact surface smoothing using Nagata patch interpolation.
subroutine, public update_surface_normal(surf, currpos, hecMESH)
subroutine, public create_intermediate_points(surf, currpos, contact_name)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1077
logical function fstr_isboundaryactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1053
This module manages the data structure for contact calculation.
integer, parameter contactslip
integer, parameter contactnear
near contact: projection info available, no LM constraint
pure logical function is_contact_free(state)
Whether the contact state is completely free (no projection info)
integer, parameter contacttied
contact type or algorithm definition
pure logical function is_contact_active(state)
Whether the contact state has active LM constraint (STICK or SLIP)
integer, parameter contactfree
contact state definition
integer, parameter contactfslid
integer, parameter contactstick
integer, parameter kcsnagata
Structure to includes all info needed by contact calculation.