26 integer,
intent(in) :: nslave
27 type(
tcontact ),
intent(inout) :: contact
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
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)
39 real(kind=kreal) :: opos(2)
40 integer(kind=kint) :: bktID, nCand, idm
41 integer(kind=kint),
allocatable :: indexCand(:)
42 logical :: is_implicit
44 is_implicit =
present(flag_ctalgo)
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
56 iss = contact%master(sid0)%nodes(j)
57 elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
60 contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
61 contact%states(nslave)%lpos(1:2), contact%cparam%CLR_SAME_ELEM, smoothing=contact%smoothing )
63 do i=1, contact%master(sid0)%n_neighbor
64 sid = contact%master(sid0)%neighbor(i)
66 contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
67 localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
69 contact%states(nslave)%surface = sid
76 write(*,*)
'Warning: contact moved beyond neighbor elements'
78 bktid = bucketdb_getbucketid(contact%master_bktDB, coord)
79 ncand = bucketdb_getnumcand(contact%master_bktDB, bktid)
81 allocate(indexcand(ncand))
82 call bucketdb_getcand(contact%master_bktDB, bktid, ncand, indexcand)
86 if(
associated(contact%master(sid0)%neighbor) )
then
87 if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
89 if (.not. is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
91 contact%states(nslave), isin, contact%cparam%DISTCLR_NOCHECK, &
92 localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
94 contact%states(nslave)%surface = sid
103 if( contact%states(nslave)%surface==sid0 )
then
104 if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS))
then
106 infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
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)
113 infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
115 if( is_implicit .and. flag_ctalgo==
'SLagrange' )
then
117 etype = contact%master(contact%states(nslave)%surface)%etype
118 nn =
size(contact%master(contact%states(nslave)%surface)%nodes)
120 iss = contact%master(contact%states(nslave)%surface)%nodes(j)
121 elem(1:3,j)=currpos(3*iss-2:3*iss)
123 call update_tangentforce(etype,nn,elem0,elem,contact%states(nslave))
125 iss =
isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
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"
132 contact%states(nslave)%multiplier(:) = 0.d0
145 nodeID, elemID, is_init, active, hecMESH, flag_ctAlgo, ndforce )
146 type(
tcontact ),
intent(inout) :: contact
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(:)
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
164 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
165 real(kind=kreal) :: effective_near_dist, distclr_use
167 integer,
pointer :: indexMaster(:),indexCand(:)
168 integer :: nMaster,idm,nMasterMax,bktID,nCand
169 logical :: is_implicit
171 is_implicit =
present(flag_ctalgo)
174 distclr = contact%cparam%DISTCLR_INIT
176 distclr = contact%cparam%DISTCLR_FREE
179 do i= 1,
size(contact%slave)
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
195 if( contact%smoothing ==
kcsnagata )
then
200 call update_surface_box_info( contact%master, currpos )
201 call update_surface_bucket_info( contact%master, contact%master_bktDB )
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)
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)
222 id = contact%states(i)%surface
223 nlforce = contact%states(i)%multiplier(1)
228 if (.not.is_init) cycle
231 if( nlforce < contact%cparam%TENSILE_FORCE )
then
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
239 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
241 if( is_implicit )
then
243 flag_ctalgo=flag_ctalgo )
248 id = contact%states(i)%surface
249 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
253 else if( contact%states(i)%state==
contactnear )
then
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)
260 distclr_use = distclr
263 contact%states(i), isin, distclr_use, &
264 contact%states(i)%lpos(1:2), contact%cparam%CLR_SAME_ELEM, smoothing=contact%smoothing )
266 if (contact%states(i)%distance <= distclr * contact%master(id)%reflen)
then
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
275 contact%states(i)%multiplier(:) = 0.d0
279 etype = contact%master(id)%etype
280 iss =
isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
283 contact%states(i)%lpos(1:2), contact%states(i)%direction(:) )
284 contact_surf(contact%slave(i)) = elemid(contact%master(id)%eid)
289 contact%states(i)%multiplier(:) = 0.d0
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)
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)
304 allocate(indexmaster(nmastermax))
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
314 deallocate(indexcand)
316 if(nmaster == 0)
then
317 deallocate(indexmaster)
322 id = indexmaster(idm)
324 if (effective_near_dist > 0.0d0)
then
325 distclr_use = max(distclr, effective_near_dist / contact%master(id)%reflen)
327 distclr_use = distclr
330 contact%states(i), isin, distclr_use, localclr=contact%cparam%CLEARANCE, smoothing=contact%smoothing )
331 if( .not. isin ) cycle
333 if (effective_near_dist > 0.0d0 .and. &
334 contact%states(i)%distance > distclr * contact%master(id)%reflen)
then
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 )
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)
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()
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()
359 deallocate(indexmaster)
364 if( contact%algtype ==
contacttied .and. .not. is_init )
then
365 deallocate(contact_surf)
366 deallocate(states_prev)
370 call hecmw_contact_comm_allreduce_i(contact%comm, contact_surf, hecmw_min)
372 do i = 1,
size(contact%slave)
374 id = contact%states(i)%surface
375 if (abs(contact_surf(contact%slave(i))) /= elemid(contact%master(id)%eid))
then
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"
382 nactive = nactive + 1
386 infoctchange%free2contact = infoctchange%free2contact + 1
388 infoctchange%contact2free = infoctchange%contact2free + 1
391 active = (nactive > 0)
392 deallocate(contact_surf)
393 deallocate(states_prev)
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
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(:)
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 )
418 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
420 integer,
pointer :: indexMaster(:),indexCand(:)
421 integer :: nMaster,idm,nMasterMax,bktID,nCand
422 logical :: is_present_B
423 real(kind=kreal),
pointer :: bp(:)
426 distclr = embed%cparam%DISTCLR_INIT
428 distclr = embed%cparam%DISTCLR_FREE
430 do i= 1,
size(embed%slave)
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
446 call update_surface_box_info( embed%master, currpos )
447 call update_surface_bucket_info( embed%master, embed%master_bktDB )
450 is_present_b =
present(b)
451 if( is_present_b ) bp => b
461 do i= 1,
size(embed%slave)
462 slave = embed%slave(i)
464 coord(:) = currpos(3*slave-2:3*slave)
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)
474 allocate(indexmaster(nmastermax))
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
484 deallocate(indexcand)
486 if(nmaster == 0)
then
487 deallocate(indexmaster)
492 id = indexmaster(idm)
493 etype = embed%master(id)%etype
494 if( mod(etype,10) == 2 ) etype = etype - 1
497 iss = embed%master(id)%nodes(j)
498 elem(1:3,j)=currpos(3*iss-2:3*iss)
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()
510 deallocate(indexmaster)
515 call hecmw_contact_comm_allreduce_i(embed%comm, contact_surf, hecmw_min)
517 do i = 1,
size(embed%slave)
519 id = embed%states(i)%surface
520 if (abs(contact_surf(embed%slave(i))) /= elemid(embed%master(id)%eid))
then
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"
525 nactive = nactive + 1
529 infoctchange%free2contact = infoctchange%free2contact + 1
531 infoctchange%contact2free = infoctchange%contact2free + 1
534 active = (nactive > 0)
535 deallocate(contact_surf)
536 deallocate(states_prev)
541 integer(kind=kint),
intent(in) :: cstep
542 type( hecmwst_local_mesh ),
intent(in) :: hecMESH
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(:)
551 allocate(states(hecmesh%n_node))
555 do ig0= 1, fstrsolid%BOUNDARY_ngrp_tot
556 grpid = fstrsolid%BOUNDARY_ngrp_GRPID(ig0)
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 )
562 iss = hecmesh%node_group%grp_item(k)
567 do i=1,fstrsolid%n_contacts
568 if( fstrsolid%contacts(i)%algtype /=
contacttied ) cycle
569 grpid = fstrsolid%contacts(i)%group
572 do j=1,
size(fstrsolid%contacts(i)%slave)
574 slave = fstrsolid%contacts(i)%slave(j)
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
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"
This module encapsulate the basic functions of all elements provide by this software.
integer(kind=kind(2)) function getnumberofnodes(etype)
Obtain number of nodes of the element.
integer function isinsideelement(fetype, localcoord, clearance)
if a point is inside a surface element -1: No; 0: Yes; >0: Node's (vertex) number
This module defines common data and basic structures for analysis.
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
logical function fstr_isboundaryactive(fstrSOLID, nbc, cstep)