23 include
'fstr_ctrl_util_f.inc'
28 character(len=HECMW_NAME_LEN) :: name
31 character(len=HECMW_NAME_LEN) :: pair_name
32 integer :: surf_id1, surf_id2
33 integer :: surf_id1_sgrp
35 integer,
pointer :: slave(:)=>null()
36 real(kind=kreal) :: fcoeff
37 real(kind=kreal) :: tpenalty
39 real(kind=kreal) :: ctime
40 integer(kind=kint) :: if_type
41 real(kind=kreal) :: if_etime
42 real(kind=kreal) :: initial_pos
43 real(kind=kreal) :: end_pos
58 type(hecmwst_contact_comm) :: comm
59 type(bucketdb) :: master_bktdb
61 type(tcontactparam),
pointer :: cparam=>null()
66 integer(kind=kint) :: contact2free
67 integer(kind=kint) :: contact2neighbor
68 integer(kind=kint) :: contact2difflpos
69 integer(kind=kint) :: free2contact
70 integer(kind=kint) :: contactnode_previous
71 integer(kind=kint) :: contactnode_current
74 private :: is_mpc_available
75 private :: is_active_contact
76 private :: cal_node_normal
77 private :: track_contact_position
78 private :: reset_contact_force
83 logical function is_mpc_available( contact )
84 type(
tcontact),
intent(in) :: contact
85 is_mpc_available = .true.
86 if( contact%fcoeff/=0.d0 ) is_mpc_available = .false.
91 integer(kind=kint),
intent(in) :: file
92 type(
tcontact),
intent(in) :: contact
94 write(file,*)
"CONTACT:", contact%ctype,contact%group,trim(contact%pair_name),contact%fcoeff
95 write(file,*)
"---Slave----"
96 write(file,*)
"num.slave",
size(contact%slave)
97 if(
associated(contact%slave) )
then
98 do i=1,
size(contact%slave)
99 write(file, *) contact%slave(i)
102 write(file,*)
"----master---"
103 write(file,*)
"num.master",
size(contact%master)
104 if(
associated(contact%master) )
then
105 do i=1,
size(contact%master)
115 if(
associated( contact%slave ) )
deallocate(contact%slave)
116 if(
associated( contact%master ) )
then
117 do i=1,
size( contact%master )
120 deallocate(contact%master)
122 if(
associated(contact%states) )
deallocate(contact%states)
130 type(hecmwst_local_mesh),
pointer :: hecmesh
139 do i=1,hecmesh%contact_pair%n_pair
140 if( hecmesh%contact_pair%name(i) == contact%pair_name )
then
141 contact%ctype = hecmesh%contact_pair%type(i)
142 contact%surf_id1 = hecmesh%contact_pair%slave_grp_id(i)
143 contact%surf_id2 = hecmesh%contact_pair%master_grp_id(i)
144 contact%surf_id1_sgrp = hecmesh%contact_pair%slave_orisgrp_id(i)
148 if( .not. isfind ) return;
149 if( contact%fcoeff<=0.d0 ) contact%fcoeff=0.d0
150 if( contact%ctype < 1 .and. contact%ctype > 3 )
return
151 if( contact%group<=0 )
return
159 type(hecmwst_local_mesh),
pointer :: hecmesh
160 type(tcontactparam),
target :: cparam
161 integer(kint),
intent(in),
optional ::
myrank
163 integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
164 integer :: count,nodeid
168 contact%cparam => cparam
171 cgrp = contact%surf_id2
173 is= hecmesh%surf_group%grp_index(cgrp-1) + 1
174 ie= hecmesh%surf_group%grp_index(cgrp )
180 ic = hecmesh%surf_group%grp_item(2*i-1)
181 if(hecmesh%elem_ID(ic*2) /=
myrank) cycle
184 allocate( contact%master(count) )
187 ic = hecmesh%surf_group%grp_item(2*i-1)
188 if(hecmesh%elem_ID(ic*2) /=
myrank) cycle
190 nsurf = hecmesh%surf_group%grp_item(2*i)
191 ic_type = hecmesh%elem_type(ic)
193 iss = hecmesh%elem_node_index(ic-1)
194 do j=1,
size( contact%master(count)%nodes )
195 nn = contact%master(count)%nodes(j)
196 contact%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
202 allocate( contact%master(ie-is+1) )
204 ic = hecmesh%surf_group%grp_item(2*i-1)
205 nsurf = hecmesh%surf_group%grp_item(2*i)
206 ic_type = hecmesh%elem_type(ic)
208 iss = hecmesh%elem_node_index(ic-1)
209 do j=1,
size( contact%master(i-is+1)%nodes )
210 nn = contact%master(i-is+1)%nodes(j)
211 contact%master(i-is+1)%nodes(j) = hecmesh%elem_node_item( iss+nn )
219 cgrp = contact%surf_id1
221 is= hecmesh%node_group%grp_index(cgrp-1) + 1
222 ie= hecmesh%node_group%grp_index(cgrp )
225 nodeid = hecmesh%global_node_ID(hecmesh%node_group%grp_item(i))
231 if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal)
then
236 allocate( contact%slave(nslave) )
237 allocate( contact%states(nslave) )
240 if(.not.
present(
myrank))
then
242 if( hecmesh%node_group%grp_item(i) > hecmesh%nn_internal) cycle
245 contact%slave(ii) = hecmesh%node_group%grp_item(i)
246 contact%states(ii)%state = -1
247 contact%states(ii)%multiplier(:) = 0.d0
248 contact%states(ii)%tangentForce(:) = 0.d0
249 contact%states(ii)%tangentForce1(:) = 0.d0
250 contact%states(ii)%tangentForce_trial(:) = 0.d0
251 contact%states(ii)%tangentForce_final(:) = 0.d0
252 contact%states(ii)%reldisp(:) = 0.d0
253 contact%states(ii)%time_factor = 0.d0
254 contact%states(ii)%interference_flag = 0
273 contact%symmetric = .true.
280 type(hecmwst_local_mesh),
pointer :: hecmesh
281 type(tcontactparam),
target :: cparam
282 integer(kint),
intent(in),
optional ::
myrank
284 integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
285 integer :: count,nodeid
289 embed%cparam => cparam
292 cgrp = embed%surf_id2
294 is= hecmesh%elem_group%grp_index(cgrp-1) + 1
295 ie= hecmesh%elem_group%grp_index(cgrp )
301 ic = hecmesh%elem_group%grp_item(i)
302 if(hecmesh%elem_ID(ic*2) /=
myrank) cycle
305 allocate( embed%master(count) )
308 ic = hecmesh%elem_group%grp_item(i)
309 if(hecmesh%elem_ID(ic*2) /=
myrank) cycle
311 ic_type = hecmesh%elem_type(ic)
313 iss = hecmesh%elem_node_index(ic-1)
314 do j=1,
size( embed%master(count)%nodes )
315 nn = embed%master(count)%nodes(j)
316 embed%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
322 allocate( embed%master(ie-is+1) )
324 ic = hecmesh%elem_group%grp_item(i)
325 ic_type = hecmesh%elem_type(ic)
327 iss = hecmesh%elem_node_index(ic-1)
328 do j=1,
size( embed%master(i-is+1)%nodes )
329 nn = embed%master(i-is+1)%nodes(j)
330 embed%master(i-is+1)%nodes(j) = hecmesh%elem_node_item( iss+nn )
340 cgrp = embed%surf_id1
342 is= hecmesh%node_group%grp_index(cgrp-1) + 1
343 ie= hecmesh%node_group%grp_index(cgrp )
346 nodeid = hecmesh%global_node_ID(hecmesh%node_group%grp_item(i))
352 if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal)
then
357 allocate( embed%slave(nslave) )
358 allocate( embed%states(nslave) )
361 if(.not.
present(
myrank))
then
363 if( hecmesh%node_group%grp_item(i) > hecmesh%nn_internal) cycle
366 embed%slave(ii) = hecmesh%node_group%grp_item(i)
367 embed%states(ii)%state = -1
368 embed%states(ii)%multiplier(:) = 0.d0
369 embed%states(ii)%tangentForce(:) = 0.d0
370 embed%states(ii)%tangentForce1(:) = 0.d0
371 embed%states(ii)%tangentForce_trial(:) = 0.d0
372 embed%states(ii)%tangentForce_final(:) = 0.d0
373 embed%states(ii)%reldisp(:) = 0.d0
392 embed%symmetric = .true.
397 type(tcontactinterference),
intent(inout) :: contact_if
407 do i = 1,
size(contacts)
408 if( contacts(i)%pair_name == contact_if%cp_name )
then
409 contacts(i)%if_type = contact_if%if_type
410 contacts(i)%if_etime = contact_if%etime
411 contacts(i)%initial_pos = contact_if%initial_pos
412 contacts(i)%end_pos = contact_if%end_pos
413 do j = 1,
size(contacts(i)%states)
414 contacts(i)%states(j)%interference_flag = contact_if%if_type
415 contacts(i)%states(j)%init_pos = contact_if%initial_pos
416 contacts(i)%states(j)%end_pos = contact_if%end_pos
418 contacts(i)%states(j)%time_factor = (contact_if%end_pos - contact_if%initial_pos) / contact_if%etime
420 contacts(i)%states(j)%time_factor = contact_if%etime
427 if( .not. isfind ) return;
436 if( .not.
associated(contact%states) )
return
437 do i=1,
size( contact%states )
438 contact%states(i)%state = -1
443 logical function is_active_contact( acgrp, contact )
444 integer,
intent(in) :: acgrp(:)
445 type(
tcontact),
intent(in) :: contact
446 if( any( acgrp==contact%group ) )
then
447 is_active_contact = .true.
449 is_active_contact = .false.
456 subroutine scan_contact_state( flag_ctAlgo, contact, currpos, currdisp, ndforce, infoCTChange, &
457 nodeID, elemID, is_init, active, mu, B )
458 character(len=9),
intent(in) :: flag_ctAlgo
459 type(
tcontact ),
intent(inout) :: contact
461 real(kind=kreal),
intent(in) :: currpos(:)
462 real(kind=kreal),
intent(in) :: currdisp(:)
463 real(kind=kreal),
intent(in) :: ndforce(:)
464 integer(kind=kint),
intent(in) :: nodeID(:)
465 integer(kind=kint),
intent(in) :: elemID(:)
466 logical,
intent(in) :: is_init
467 logical,
intent(out) :: active
468 real(kind=kreal),
intent(in) ::
mu
469 real(kind=kreal),
optional,
target :: b(:)
471 real(kind=kreal) :: distclr
472 integer(kind=kint) :: slave, id, etype
473 integer(kind=kint) :: nn, i, j, iSS, nactive
474 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
475 real(kind=kreal) :: nlforce, slforce(3)
477 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
479 integer,
pointer :: indexMaster(:),indexCand(:)
480 integer :: nMaster,idm,nMasterMax,bktID,nCand
481 logical :: is_cand, is_present_B
482 real(kind=kreal),
pointer :: bp(:)
485 distclr = contact%cparam%DISTCLR_INIT
487 distclr = contact%cparam%DISTCLR_FREE
490 do i= 1,
size(contact%slave)
499 allocate(contact_surf(
size(nodeid)))
500 allocate(states_prev(
size(contact%slave)))
501 contact_surf(:) = huge(0)
502 do i = 1,
size(contact%slave)
503 states_prev(i) = contact%states(i)%state
510 is_present_b =
present(b)
511 if( is_present_b ) bp => b
521 do i= 1,
size(contact%slave)
522 if(contact%if_type /= 0)
call set_shrink_factor(contact%ctime, contact%states(i), contact%if_etime, contact%if_type)
523 slave = contact%slave(i)
525 slforce(1:3)=ndforce(3*slave-2:3*slave)
526 id = contact%states(i)%surface
527 nlforce = contact%states(i)%multiplier(1)
532 if (.not.is_init) cycle
535 if( nlforce < contact%cparam%TENSILE_FORCE )
then
537 contact%states(i)%multiplier(:) = 0.d0
538 write(*,
'(A,i10,A,i10,A,e12.3)')
"Node",nodeid(slave),
" free from contact with element", &
539 elemid(contact%master(id)%eid),
" with tensile force ", nlforce
542 if( contact%algtype /=
contactfslid .or. (.not. is_present_b) )
then
543 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
545 call track_contact_position( flag_ctalgo, i, contact, currpos, currdisp,
mu, infoctchange, nodeid, elemid, bp )
547 id = contact%states(i)%surface
548 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
552 else if( contact%states(i)%state==
contactfree )
then
553 if( contact%algtype ==
contacttied .and. .not. is_init ) cycle
554 coord(:) = currpos(3*slave-2:3*slave)
559 if (ncand == 0) cycle
560 allocate(indexcand(ncand))
564 allocate(indexmaster(nmastermax))
570 if (.not.
is_in_surface_box( contact%master(id), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
571 nmaster = nmaster + 1
572 indexmaster(nmaster) = id
574 deallocate(indexcand)
576 if(nmaster == 0)
then
577 deallocate(indexmaster)
582 id = indexmaster(idm)
583 etype = contact%master(id)%etype
584 nn =
size( contact%master(id)%nodes )
586 iss = contact%master(id)%nodes(j)
587 elem(1:3,j)=currpos(3*iss-2:3*iss)
590 isin,distclr,localclr=contact%cparam%CLEARANCE )
591 if( .not. isin ) cycle
592 contact%states(i)%surface = id
593 contact%states(i)%multiplier(:) = 0.d0
594 iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
596 call cal_node_normal( id, iss, contact%master, currpos, contact%states(i)%lpos(1:2), &
597 contact%states(i)%direction(:) )
598 contact_surf(contact%slave(i)) = elemid(contact%master(id)%eid)
599 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3,A,3f7.3,A,i6)')
"Node",nodeid(slave),
" contact with element", &
600 elemid(contact%master(id)%eid), &
601 " with distance ", contact%states(i)%distance,
" at ",contact%states(i)%lpos(1:2), &
602 " along direction ", contact%states(i)%direction,
" rank=",hecmw_comm_get_rank()
605 deallocate(indexmaster)
610 if( contact%algtype ==
contacttied .and. .not. is_init )
then
611 deallocate(contact_surf)
612 deallocate(states_prev)
618 do i = 1,
size(contact%slave)
620 id = contact%states(i)%surface
621 if (abs(contact_surf(contact%slave(i))) /= elemid(contact%master(id)%eid))
then
623 write(*,
'(A,i10,A,i10,A,i6,A,i6,A)')
"Node",nodeid(contact%slave(i)),
" contact with element", &
624 & elemid(contact%master(id)%eid),
" in rank",hecmw_comm_get_rank(),
" freed due to duplication"
626 nactive = nactive + 1
630 infoctchange%free2contact = infoctchange%free2contact + 1
632 infoctchange%contact2free = infoctchange%contact2free + 1
635 active = (nactive > 0)
636 deallocate(contact_surf)
637 deallocate(states_prev)
643 subroutine scan_embed_state( flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, &
644 nodeID, elemID, is_init, active, mu, B )
645 character(len=9),
intent(in) :: flag_ctAlgo
646 type(
tcontact ),
intent(inout) :: embed
648 real(kind=kreal),
intent(in) :: currpos(:)
649 real(kind=kreal),
intent(in) :: currdisp(:)
650 real(kind=kreal),
intent(in) :: ndforce(:)
651 integer(kind=kint),
intent(in) :: nodeID(:)
652 integer(kind=kint),
intent(in) :: elemID(:)
653 logical,
intent(in) :: is_init
654 logical,
intent(out) :: active
655 real(kind=kreal),
intent(in) ::
mu
656 real(kind=kreal),
optional,
target :: b(:)
658 real(kind=kreal) :: distclr
659 integer(kind=kint) :: slave, id, etype
660 integer(kind=kint) :: nn, i, j, iSS, nactive
661 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
662 real(kind=kreal) :: nlforce, slforce(3)
664 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
666 integer,
pointer :: indexMaster(:),indexCand(:)
667 integer :: nMaster,idm,nMasterMax,bktID,nCand
668 logical :: is_cand, is_present_B
669 real(kind=kreal),
pointer :: bp(:)
672 distclr = embed%cparam%DISTCLR_INIT
674 distclr = embed%cparam%DISTCLR_FREE
676 do i= 1,
size(embed%slave)
685 allocate(contact_surf(
size(nodeid)))
686 allocate(states_prev(
size(embed%slave)))
687 contact_surf(:) = huge(0)
688 do i = 1,
size(embed%slave)
689 states_prev(i) = embed%states(i)%state
696 is_present_b =
present(b)
697 if( is_present_b ) bp => b
707 do i= 1,
size(embed%slave)
708 slave = embed%slave(i)
710 coord(:) = currpos(3*slave-2:3*slave)
715 if (ncand == 0) cycle
716 allocate(indexcand(ncand))
720 allocate(indexmaster(nmastermax))
726 if (.not.
is_in_surface_box( embed%master(id), coord(1:3), embed%cparam%BOX_EXP_RATE )) cycle
727 nmaster = nmaster + 1
728 indexmaster(nmaster) = id
730 deallocate(indexcand)
732 if(nmaster == 0)
then
733 deallocate(indexmaster)
738 id = indexmaster(idm)
739 etype = embed%master(id)%etype
740 if( mod(etype,10) == 2 ) etype = etype - 1
741 nn = getnumberofnodes(etype)
743 iss = embed%master(id)%nodes(j)
744 elem(1:3,j)=currpos(3*iss-2:3*iss)
747 isin,distclr,localclr=embed%cparam%CLEARANCE )
748 if( .not. isin ) cycle
749 embed%states(i)%surface = id
750 embed%states(i)%multiplier(:) = 0.d0
751 contact_surf(embed%slave(i)) = elemid(embed%master(id)%eid)
752 write(*,
'(A,i10,A,i10,A,3f7.3,A,i6)')
"Node",nodeid(slave),
" embeded to element", &
753 elemid(embed%master(id)%eid),
" at ",embed%states(i)%lpos(:),
" rank=",hecmw_comm_get_rank()
756 deallocate(indexmaster)
763 do i = 1,
size(embed%slave)
765 id = embed%states(i)%surface
766 if (abs(contact_surf(embed%slave(i))) /= elemid(embed%master(id)%eid))
then
768 write(*,
'(A,i10,A,i10,A,i6,A,i6,A)')
"Node",nodeid(embed%slave(i)),
" contact with element", &
769 & elemid(embed%master(id)%eid),
" in rank",hecmw_comm_get_rank(),
" freed due to duplication"
771 nactive = nactive + 1
775 infoctchange%free2contact = infoctchange%free2contact + 1
777 infoctchange%contact2free = infoctchange%contact2free + 1
780 active = (nactive > 0)
781 deallocate(contact_surf)
782 deallocate(states_prev)
787 subroutine cal_node_normal( csurf, isin, surf, currpos, lpos, normal )
789 integer,
intent(in) :: csurf
790 integer,
intent(in) :: isin
792 real(kind=kreal),
intent(in) :: currpos(:)
793 real(kind=kreal),
intent(in) :: lpos(:)
794 real(kind=kreal),
intent(out) :: normal(3)
795 integer(kind=kint) :: cnode, i, j, cnt, nd1, gn, etype, iSS, nn,cgn
796 real(kind=kreal) :: cnpos(2), elem(3, l_max_elem_node )
797 integer(kind=kint) :: cnode1, cnode2, gn1, gn2, nsurf, cgn1, cgn2, isin_n
798 real(kind=kreal) :: x=0, normal_n(3), lpos_n(2)
800 if( 1 <= isin .and. isin <= 4 )
then
802 gn = surf(csurf)%nodes(cnode)
803 etype = surf(csurf)%etype
805 nn =
size( surf(csurf)%nodes )
807 iss = surf(csurf)%nodes(j)
808 elem(1:3,j)=currpos(3*iss-2:3*iss)
812 do i=1,surf(csurf)%n_neighbor
813 nd1 = surf(csurf)%neighbor(i)
814 nn =
size( surf(nd1)%nodes )
815 etype = surf(nd1)%etype
818 iss = surf(nd1)%nodes(j)
819 elem(1:3,j)=currpos(3*iss-2:3*iss)
826 normal = normal+normal_n
831 elseif( 12 <= isin .and. isin <= 41 )
then
833 cnode2 = mod(isin, 10)
834 gn1 = surf(csurf)%nodes(cnode1)
835 gn2 = surf(csurf)%nodes(cnode2)
836 etype = surf(csurf)%etype
837 nn =
size( surf(csurf)%nodes )
839 iss = surf(csurf)%nodes(j)
840 elem(1:3,j)=currpos(3*iss-2:3*iss)
844 case (fe_tri3n, fe_tri6n, fe_tri6nc)
845 if ( isin==12 ) then; x=lpos(2)-lpos(1)
846 elseif( isin==23 ) then; x=1.d0-2.d0*lpos(2)
847 elseif( isin==31 ) then; x=2.d0*lpos(1)-1.d0
848 else; stop
"Error: cal_node_normal: invalid isin"
850 case (fe_quad4n, fe_quad8n)
851 if ( isin==12 ) then; x=lpos(1)
852 elseif( isin==23 ) then; x=lpos(2)
853 elseif( isin==34 ) then; x=-lpos(1)
854 elseif( isin==41 ) then; x=-lpos(2)
855 else; stop
"Error: cal_node_normal: invalid isin"
860 neib_loop:
do i=1, surf(csurf)%n_neighbor
861 nd1 = surf(csurf)%neighbor(i)
862 nn =
size( surf(nd1)%nodes )
863 etype = surf(nd1)%etype
867 iss = surf(nd1)%nodes(j)
868 elem(1:3,j)=currpos(3*iss-2:3*iss)
869 if( iss==gn1 ) cgn1=j
870 if( iss==gn2 ) cgn2=j
872 if( cgn1>0 .and. cgn2>0 )
then
874 isin_n = 10*cgn2 + cgn1
877 case (fe_tri3n, fe_tri6n, fe_tri6nc)
878 if ( isin_n==12 ) then; lpos_n(1)=0.5d0*(1.d0-x); lpos_n(2)=0.5d0*(1.d0+x)
879 elseif( isin_n==23 ) then; lpos_n(1)=0.d0; lpos_n(2)=0.5d0*(1.d0-x)
880 elseif( isin_n==31 ) then; lpos_n(1)=0.5d0*(1.d0+x); lpos_n(2)=0.d0
881 else; stop
"Error: cal_node_normal: invalid isin_n"
883 case (fe_quad4n, fe_quad8n)
884 if ( isin_n==12 ) then; lpos_n(1)= x; lpos_n(2)=-1.d0
885 elseif( isin_n==23 ) then; lpos_n(1)= 1.d0; lpos_n(2)= x
886 elseif( isin_n==34 ) then; lpos_n(1)=-x; lpos_n(2)= 1.d0
887 elseif( isin_n==41 ) then; lpos_n(1)=-1.d0; lpos_n(2)=-x
888 else; stop
"Error: cal_node_normal: invalid isin_n"
893 normal = normal+normal_n
900 normal = normal/ dsqrt( dot_product( normal, normal ) )
901 end subroutine cal_node_normal
904 subroutine track_contact_position( flag_ctAlgo, nslave, contact, currpos, currdisp, mu, infoCTChange, nodeID, elemID, B )
905 character(len=9),
intent(in) :: flag_ctAlgo
906 integer,
intent(in) :: nslave
907 type(
tcontact ),
intent(inout) :: contact
909 real(kind=kreal),
intent(in) :: currpos(:)
910 real(kind=kreal),
intent(in) :: currdisp(:)
911 real(kind=kreal),
intent(in) ::
mu
912 integer(kind=kint),
intent(in) :: nodeID(:)
913 integer(kind=kint),
intent(in) :: elemID(:)
914 real(kind=kreal),
intent(inout) :: b(:)
916 integer(kind=kint) :: slave, sid0, sid, etype
917 integer(kind=kint) :: nn, i, j, iSS
918 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
920 real(kind=kreal) :: opos(2), odirec(3)
921 integer(kind=kint) :: bktID, nCand, idm
922 integer(kind=kint),
allocatable :: indexCand(:)
926 slave = contact%slave(nslave)
927 coord(:) = currpos(3*slave-2:3*slave)
929 sid0 = contact%states(nslave)%surface
930 opos = contact%states(nslave)%lpos(1:2)
931 odirec = contact%states(nslave)%direction
932 etype = contact%master(sid0)%etype
933 nn = getnumberofnodes( etype )
935 iss = contact%master(sid0)%nodes(j)
936 elem(1:3,j)=currpos(3*iss-2:3*iss)
937 elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
939 call project_point2element( coord,etype,nn,elem,contact%master(sid0)%reflen,contact%states(nslave), &
940 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos(1:2),contact%cparam%CLR_SAME_ELEM )
941 if( .not. isin )
then
942 do i=1, contact%master(sid0)%n_neighbor
943 sid = contact%master(sid0)%neighbor(i)
944 etype = contact%master(sid)%etype
945 nn = getnumberofnodes( etype )
947 iss = contact%master(sid)%nodes(j)
948 elem(1:3,j)=currpos(3*iss-2:3*iss)
951 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
953 contact%states(nslave)%surface = sid
959 if( .not. isin )
then
960 write(*,*)
'Warning: contact moved beyond neighbor elements'
965 allocate(indexcand(ncand))
969 if( sid==sid0 ) cycle
970 if(
associated(contact%master(sid0)%neighbor) )
then
971 if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
973 if (.not.
is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
974 etype = contact%master(sid)%etype
975 nn =
size( contact%master(sid)%nodes )
977 iss = contact%master(sid)%nodes(j)
978 elem(1:3,j)=currpos(3*iss-2:3*iss)
981 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
983 contact%states(nslave)%surface = sid
987 deallocate(indexcand)
992 if( contact%states(nslave)%surface==sid0 )
then
993 if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS))
then
995 infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
998 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3)')
"Node",nodeid(slave),
" move to contact with", &
999 elemid(contact%master(sid)%eid),
" with distance ", &
1000 contact%states(nslave)%distance,
" at ",contact%states(nslave)%lpos(1:2)
1002 infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
1003 if( flag_ctalgo==
'ALagrange' ) &
1004 call reset_contact_force( contact, currpos, nslave, sid0, opos, odirec, b )
1006 if( flag_ctalgo==
'SLagrange' )
call update_tangentforce(etype,nn,elem0,elem,contact%states(nslave))
1007 iss = isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
1009 call cal_node_normal( contact%states(nslave)%surface, iss, contact%master, currpos, &
1010 contact%states(nslave)%lpos(1:2), contact%states(nslave)%direction(:) )
1011 else if( .not. isin )
then
1012 write(*,
'(A,i10,A)')
"Node",nodeid(slave),
" move out of contact"
1014 contact%states(nslave)%multiplier(:) = 0.d0
1017 end subroutine track_contact_position
1021 integer,
intent(in) :: nslave
1022 type(
tcontact ),
intent(inout) :: contact
1023 real(kind=kreal),
intent(in) :: currpos(:)
1025 integer(kind=kint) :: slave, sid0, sid, etype
1026 integer(kind=kint) :: nn, i, j, iSS
1027 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
1029 real(kind=kreal) :: opos(2), odirec(3)
1030 integer(kind=kint) :: bktID, nCand, idm
1031 integer(kind=kint),
allocatable :: indexCand(:)
1036 slave = contact%slave(nslave)
1037 coord(:) = currpos(3*slave-2:3*slave)
1039 sid0 = contact%states(nslave)%surface
1040 opos = contact%states(nslave)%lpos(1:2)
1041 odirec = contact%states(nslave)%direction
1042 etype = contact%master(sid0)%etype
1043 nn = getnumberofnodes( etype )
1045 iss = contact%master(sid0)%nodes(j)
1046 elem(1:3,j)=currpos(3*iss-2:3*iss)
1049 cstate_tmp%state = contact%states(nslave)%state
1050 cstate_tmp%surface = sid0
1052 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos,contact%cparam%CLR_SAME_ELEM )
1055 iss = isinsideelement( etype, cstate_tmp%lpos, contact%cparam%CLR_CAL_NORM )
1057 call cal_node_normal( cstate_tmp%surface, iss, contact%master, currpos, &
1058 cstate_tmp%lpos, cstate_tmp%direction(:) )
1061 contact%states(nslave)%direction = cstate_tmp%direction
1068 subroutine reset_contact_force( contact, currpos, lslave, omaster, opos, odirec, B )
1069 type(
tcontact ),
intent(inout) :: contact
1070 real(kind=kreal),
intent(in) :: currpos(:)
1071 integer,
intent(in) :: lslave
1072 integer,
intent(in) :: omaster
1073 real(kind=kreal),
intent(in) :: opos(2)
1074 real(kind=kreal),
intent(in) :: odirec(3)
1075 real(kind=kreal),
intent(inout) :: b(:)
1077 integer(kind=kint) :: slave, etype, master
1078 integer(kind=kint) :: nn, j, iSS
1079 real(kind=kreal) :: nrlforce, fcoeff, tangent(3,2)
1080 real(kind=kreal) :: elemcrd(3, l_max_elem_node )
1081 real(kind=kreal) :: shapefunc(l_max_surface_node)
1082 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1083 real(kind=kreal) :: fric(2), f3(l_max_elem_node*3+3)
1084 integer(kind=kint) :: i, idx0
1086 slave = contact%slave(lslave)
1087 fcoeff = contact%fcoeff
1089 nrlforce = contact%states(lslave)%multiplier(1)
1090 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)+nrlforce*odirec
1091 nn =
size( contact%master(omaster)%nodes )
1092 etype = contact%master(omaster)%etype
1093 call getshapefunc( etype, opos(:), shapefunc )
1095 iss = contact%master(omaster)%nodes(j)
1100 b(idx0+i) = b(idx0+i)-nrlforce*shapefunc(j)*odirec(i)
1103 if( fcoeff/=0.d0 )
then
1105 iss = contact%master(omaster)%nodes(j)
1106 elemcrd(:,j) = currpos(3*iss-2:3*iss)
1110 fric(1:2) = contact%states(lslave)%multiplier(2:3)
1111 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1112 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)+f3(1:3)
1114 iss = contact%master(omaster)%nodes(j)
1119 b(idx0+i) = b(idx0+i)+f3(3*j+i)
1125 master = contact%states(lslave)%surface
1126 nn =
size( contact%master(master)%nodes )
1127 etype = contact%master(master)%etype
1128 call getshapefunc( etype, contact%states(lslave)%lpos(1:2), shapefunc )
1129 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(lslave)%direction
1131 iss = contact%master(master)%nodes(j)
1137 b(idx0+i) = b(idx0+i)+nrlforce* &
1138 shapefunc(j)*contact%states(lslave)%direction(i)
1141 if( fcoeff/=0.d0 )
then
1143 iss = contact%master(master)%nodes(j)
1144 elemcrd(:,j) = currpos(3*iss-2:3*iss)
1146 call dispincrematrix( contact%states(lslave)%lpos(1:2), etype, nn, elemcrd, tangent, &
1148 fric(1:2) = contact%states(lslave)%multiplier(2:3)
1149 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1150 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1152 iss = contact%master(master)%nodes(j)
1157 b(idx0+i) = b(idx0+i)-f3(3*j+i)
1162 end subroutine reset_contact_force
1170 real(kind=kreal),
intent(in) :: coord(:)
1171 real(kind=kreal),
intent(in) :: disp(:)
1172 real(kind=kreal),
intent(in) :: ddisp(:)
1173 real(kind=kreal),
intent(in) :: fcoeff
1174 real(kind=kreal),
intent(in) ::
mu,
mut
1175 real(kind=kreal),
intent(inout) :: b(:)
1177 integer(kind=kint) :: slave, etype, master
1178 integer(kind=kint) :: nn, i, j, iSS
1179 real(kind=kreal) :: nrlforce, elemdisp(3,l_max_elem_node), tangent(3,2)
1180 real(kind=kreal) :: dg(3), elemg(3), elemcrd(3, l_max_elem_node )
1181 real(kind=kreal) :: dgn, dxi(2), dxy(2), shapefunc(l_max_surface_node)
1182 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1183 real(kind=kreal) :: fric(2), f3(3*l_max_elem_node+3), edisp(3*l_max_elem_node+3)
1185 do i= 1,
size(contact%slave)
1187 slave = contact%slave(i)
1188 edisp(1:3) = ddisp(3*slave-2:3*slave)
1189 master = contact%states(i)%surface
1191 nn =
size( contact%master(master)%nodes )
1192 etype = contact%master(master)%etype
1194 iss = contact%master(master)%nodes(j)
1195 elemdisp(:,j) = ddisp(3*iss-2:3*iss)
1196 edisp(3*j+1:3*j+3) = ddisp(3*iss-2:3*iss)
1197 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1199 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1204 elemg(:) = elemg(:)+shapefunc(j)*elemdisp(:,j)
1206 dg(:) = ddisp(3*slave-2:3*slave) - elemg(:)
1207 dgn = dot_product( contact%states(i)%direction, dg )
1208 nrlforce = contact%states(i)%multiplier(1)-
mu*(contact%states(i)%wkdist-dgn)
1209 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(i)%direction
1212 iss = contact%master(master)%nodes(j)
1213 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)+nrlforce* &
1214 shapefunc(j)*contact%states(i)%direction
1217 if( fcoeff==0.d0 ) cycle
1219 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1221 dxi(1) = dot_product( dispmat(1,1:nn*3+3), edisp(1:nn*3+3) )
1222 dxi(2) = dot_product( dispmat(2,1:nn*3+3), edisp(1:nn*3+3) )
1223 dxy(:) = matmul( metric, dxi )
1224 fric(1:2) = contact%states(i)%multiplier(2:3) +
mut*dxy(1:2)
1225 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1228 dgn = dsqrt( f3(1)*f3(1)+f3(2)*f3(2)+f3(3)*f3(3) )
1229 f3(:) = f3(:)*fcoeff*contact%states(i)%multiplier(1)/dgn
1231 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1233 iss = contact%master(master)%nodes(j)
1234 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)-f3(3*j+1:3*j+3)
1244 real(kind=kreal),
intent(in) :: disp(:)
1245 real(kind=kreal),
intent(in) :: ddisp(:)
1246 real(kind=kreal),
intent(in) ::
mu
1247 real(kind=kreal),
intent(inout) :: b(:)
1249 integer(kind=kint) :: slave, etype, master
1250 integer(kind=kint) :: nn, i, j, iss
1251 real(kind=kreal) :: nrlforce(3)
1252 real(kind=kreal) :: dg(3)
1253 real(kind=kreal) :: shapefunc(l_max_surface_node)
1254 real(kind=kreal) :: edisp(3*l_max_elem_node+3)
1256 do i= 1,
size(contact%slave)
1258 slave = contact%slave(i)
1259 edisp(1:3) = disp(3*slave-2:3*slave)+ddisp(3*slave-2:3*slave)
1260 master = contact%states(i)%surface
1262 nn =
size( contact%master(master)%nodes )
1263 etype = contact%master(master)%etype
1265 iss = contact%master(master)%nodes(j)
1266 edisp(3*j+1:3*j+3) = disp(3*iss-2:3*iss)+ddisp(3*iss-2:3*iss)
1268 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1271 dg(1:3) = edisp(1:3)
1273 dg(1:3) = dg(1:3)-shapefunc(j)*edisp(3*j+1:3*j+3)
1276 nrlforce(1:3) = contact%states(i)%multiplier(1:3)+
mu*dg(1:3)
1278 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce(1:3)
1280 iss = contact%master(master)%nodes(j)
1281 b(3*iss-2:3*iss) = b(3*iss-2:3*iss) + shapefunc(j)*nrlforce(1:3)
1292 real(kind=kreal),
intent(in) :: coord(:)
1293 real(kind=kreal),
intent(in) :: disp(:)
1294 real(kind=kreal),
intent(in) :: ddisp(:)
1295 real(kind=kreal),
intent(in) :: fcoeff
1296 real(kind=kreal),
intent(in) ::
mu,
mut
1297 real(kind=kreal),
intent(out) ::
gnt(2)
1298 logical,
intent(inout) :: ctchanged
1300 integer(kind=kint) :: slave, etype, master
1301 integer(kind=kint) :: nn, i, j, iss, cnt
1302 real(kind=kreal) :: elemdisp(3,l_max_elem_node), tangent(3,2)
1303 real(kind=kreal) :: dg(3), elemg(3), elemcrd(3, l_max_elem_node )
1304 real(kind=kreal) :: dgn, dxi(2), dxy(2), shapefunc(l_max_surface_node)
1305 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1306 real(kind=kreal) :: lgnt(2), fric(2), f3(3*l_max_elem_node+3), edisp(3*l_max_elem_node+3)
1308 cnt =0; lgnt(:)=0.d0
1309 do i= 1,
size(contact%slave)
1311 slave = contact%slave(i)
1312 edisp(1:3) = ddisp(3*slave-2:3*slave)
1313 master = contact%states(i)%surface
1315 nn =
size( contact%master(master)%nodes )
1316 etype = contact%master(master)%etype
1318 iss = contact%master(master)%nodes(j)
1319 elemdisp(:,j) = ddisp(3*iss-2:3*iss)
1320 edisp(3*j+1:3*j+3) = ddisp(3*iss-2:3*iss)
1321 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1323 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1328 elemg(:) = elemg(:)+shapefunc(j)*elemdisp(:,j)
1330 dg(:) = ddisp(3*slave-2:3*slave) - elemg(:)
1331 dgn = dot_product( contact%states(i)%direction, dg )
1332 contact%states(i)%wkdist = contact%states(i)%wkdist-dgn
1333 contact%states(i)%multiplier(1) = contact%states(i)%multiplier(1)-
mu*contact%states(i)%wkdist
1334 contact%states(i)%distance = contact%states(i)%distance - dgn
1336 lgnt(1) = lgnt(1)- contact%states(i)%wkdist
1338 if( fcoeff==0.d0 ) cycle
1340 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1342 dxi(1) = dot_product( dispmat(1,1:nn*3+3), edisp(1:nn*3+3) )
1343 dxi(2) = dot_product( dispmat(2,1:nn*3+3), edisp(1:nn*3+3) )
1344 dxy(:) = matmul( metric, dxi )
1345 fric(1:2) = contact%states(i)%multiplier(2:3) +
mut*dxy(1:2)
1346 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1347 dgn = dsqrt( f3(1)*f3(1)+f3(2)*f3(2)+f3(3)*f3(3) )
1348 if( contact%states(i)%multiplier(1)>0.d0 )
then
1349 if( dgn > fcoeff*contact%states(i)%multiplier(1) )
then
1352 print *,
"Node", slave,
"to slip state",dgn, fcoeff*contact%states(i)%multiplier(1)
1355 fric(:) = fric(:)*fcoeff*contact%states(i)%multiplier(1)/dgn
1359 print *,
"Node", slave,
"to stick state",dgn, fcoeff*contact%states(i)%multiplier(1)
1364 contact%states(i)%multiplier(2:3) = fric(:)
1365 dxy(:) = matmul( dg, tangent )
1366 lgnt(2) = lgnt(2)+dsqrt( dxy(1)*dxy(1)+dxy(2)*dxy(2) )
1368 if(cnt>0) lgnt(:) = lgnt(:)/cnt
1376 real(kind=kreal),
intent(in) :: disp(:)
1377 real(kind=kreal),
intent(in) :: ddisp(:)
1378 real(kind=kreal),
intent(in) ::
mu
1379 logical,
intent(inout) :: ctchanged
1381 integer(kind=kint) :: slave, etype, master
1382 integer(kind=kint) :: nn, i, j, iss, cnt
1383 real(kind=kreal) :: dg(3), dgmax
1384 real(kind=kreal) :: shapefunc(l_max_surface_node)
1385 real(kind=kreal) :: edisp(3*l_max_elem_node+3)
1387 do i= 1,
size(contact%slave)
1389 slave = contact%slave(i)
1390 edisp(1:3) = disp(3*slave-2:3*slave)+ddisp(3*slave-2:3*slave)
1391 master = contact%states(i)%surface
1393 nn =
size( contact%master(master)%nodes )
1394 etype = contact%master(master)%etype
1396 iss = contact%master(master)%nodes(j)
1397 edisp(3*j+1:3*j+3) = disp(3*iss-2:3*iss)+ddisp(3*iss-2:3*iss)
1399 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1402 dg(1:3) = edisp(1:3)
1404 dg(1:3) = dg(1:3)-shapefunc(j)*edisp(3*j+1:3*j+3)
1407 contact%states(i)%multiplier(1:3) = contact%states(i)%multiplier(1:3) +
mu*dg(1:3)
1412 dgmax = dgmax + dabs(edisp(j))
1414 dgmax = dgmax/dble((nn+1)*3)
1416 if( dabs(dg(j))/dmax1(1.d0,dgmax) > 1.d-3 ) ctchanged = .true.
1425 real(kind=kreal),
intent(in) :: coord(:)
1426 real(kind=kreal),
intent(in) :: disp(:)
1427 real(kind=kreal),
intent(inout) :: b(:)
1429 integer(kind=kint) :: slave, etype, master
1430 integer(kind=kint) :: nn, i, j, iss
1431 real(kind=kreal) :: fcoeff, nrlforce, tangent(3,2)
1432 real(kind=kreal) :: elemcrd(3, l_max_elem_node )
1433 real(kind=kreal) :: shapefunc(l_max_surface_node)
1434 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1435 real(kind=kreal) :: fric(2), f3(l_max_elem_node*3+3)
1436 fcoeff = contact%fcoeff
1437 do i= 1,
size(contact%slave)
1439 slave = contact%slave(i)
1440 master = contact%states(i)%surface
1442 nn =
size( contact%master(master)%nodes )
1443 etype = contact%master(master)%etype
1444 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1447 nrlforce = contact%states(i)%multiplier(1)
1448 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(i)%direction
1451 iss = contact%master(master)%nodes(j)
1452 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)+nrlforce* &
1453 shapefunc(j)*contact%states(i)%direction
1456 if( fcoeff==0.d0 ) cycle
1459 iss = contact%master(master)%nodes(j)
1460 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1462 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1465 fric(1:2) = contact%states(i)%multiplier(2:3)
1466 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1467 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1469 iss = contact%master(master)%nodes(j)
1470 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)-f3(3*j+1:3*j+3)
1479 real(kind=kreal),
intent(in) ::
dt
1480 real(kind=kreal),
intent(inout) :: relvel_vec(:)
1481 real(kind=kreal),
intent(inout) :: state_vec(:)
1483 integer(kind=kint) :: i, slave
1485 do i= 1,
size(contact%slave)
1486 slave = contact%slave(i)
1487 if( state_vec(slave) < 0.1d0 .or. contact%states(i)%state > 0 ) &
1488 & state_vec(slave) = dble(contact%states(i)%state)
1491 if(
dt < 1.d-16 ) cycle
1492 relvel_vec(3*slave-2:3*slave) = contact%states(i)%reldisp(1:3)/
dt
1500 integer(kind=kint) :: i
1502 do i= 1,
size(contact%slave)
1504 contact%states(i)%tangentForce(1:3) = 0.d0
1505 contact%states(i)%tangentForce_trial(1:3) = 0.d0
1506 contact%states(i)%tangentForce_final(1:3) = 0.d0
1508 contact%states(i)%tangentForce(1:3) = contact%states(i)%tangentForce_final(1:3)
1510 contact%states(i)%tangentForce1(1:3) = contact%states(i)%tangentForce(1:3)
1516 integer,
intent(in) :: nslave
1517 type(
tcontact ),
intent(inout) :: contact
1519 real(kind=kreal),
intent(in) :: currpos(:)
1520 real(kind=kreal),
intent(in) :: currdisp(:)
1521 integer(kind=kint),
intent(in) :: nodeID(:)
1522 integer(kind=kint),
intent(in) :: elemID(:)
1524 integer(kind=kint) :: slave, sid0, sid, etype
1525 integer(kind=kint) :: nn, i, j, iSS
1526 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
1528 real(kind=kreal) :: opos(2), odirec(3)
1529 integer(kind=kint) :: bktID, nCand, idm
1530 integer(kind=kint),
allocatable :: indexCand(:)
1534 slave = contact%slave(nslave)
1535 coord(:) = currpos(3*slave-2:3*slave)
1537 sid0 = contact%states(nslave)%surface
1538 opos = contact%states(nslave)%lpos(1:2)
1539 odirec = contact%states(nslave)%direction
1540 etype = contact%master(sid0)%etype
1541 nn = getnumberofnodes( etype )
1543 iss = contact%master(sid0)%nodes(j)
1544 elem(1:3,j)=currpos(3*iss-2:3*iss)
1545 elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
1547 call project_point2element( coord,etype,nn,elem,contact%master(sid0)%reflen,contact%states(nslave), &
1548 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos(1:2),contact%cparam%CLR_SAME_ELEM )
1549 if( .not. isin )
then
1550 do i=1, contact%master(sid0)%n_neighbor
1551 sid = contact%master(sid0)%neighbor(i)
1552 etype = contact%master(sid)%etype
1553 nn = getnumberofnodes( etype )
1555 iss = contact%master(sid)%nodes(j)
1556 elem(1:3,j)=currpos(3*iss-2:3*iss)
1558 call project_point2element( coord,etype,nn,elem,contact%master(sid)%reflen,contact%states(nslave), &
1559 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
1561 contact%states(nslave)%surface = sid
1567 if( .not. isin )
then
1568 write(*,*)
'Warning: contact moved beyond neighbor elements'
1573 allocate(indexcand(ncand))
1576 sid = indexcand(idm)
1577 if( sid==sid0 ) cycle
1578 if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
1579 if (.not.
is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
1580 etype = contact%master(sid)%etype
1581 nn =
size( contact%master(sid)%nodes )
1583 iss = contact%master(sid)%nodes(j)
1584 elem(1:3,j)=currpos(3*iss-2:3*iss)
1586 call project_point2element( coord,etype,nn,elem,contact%master(sid)%reflen,contact%states(nslave), &
1587 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
1589 contact%states(nslave)%surface = sid
1593 deallocate(indexcand)
1598 if( contact%states(nslave)%surface==sid0 )
then
1599 if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS))
then
1601 infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
1604 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3)')
"Node",nodeid(slave),
" move to contact with", &
1605 elemid(contact%master(sid)%eid),
" with distance ", &
1606 contact%states(nslave)%distance,
" at ",contact%states(nslave)%lpos(1:2)
1608 infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
1610 iss = isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
1612 call cal_node_normal( contact%states(nslave)%surface, iss, contact%master, currpos, &
1613 contact%states(nslave)%lpos(1:2), contact%states(nslave)%direction(:) )
1615 else if( .not. isin )
then
1616 write(*,
'(A,i10,A)')
"Node",nodeid(slave),
" move out of contact"
1618 contact%states(nslave)%multiplier(:) = 0.d0
1627 nodeID, elemID, is_init, active )
1630 real(kind=kreal),
intent(in) :: currpos(:)
1631 real(kind=kreal),
intent(in) :: currdisp(:)
1632 integer(kind=kint),
intent(in) :: nodeID(:)
1633 integer(kind=kint),
intent(in) :: elemID(:)
1634 logical,
intent(in) :: is_init
1635 logical,
intent(out) :: active
1637 real(kind=kreal) :: distclr
1638 integer(kind=kint) :: slave, id, etype
1639 integer(kind=kint) :: nn, i, j, iSS, nactive
1640 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
1641 real(kind=kreal) :: nlforce
1643 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
1645 integer,
pointer :: indexMaster(:),indexCand(:)
1646 integer :: nMaster,idm,nMasterMax,bktID,nCand
1650 distclr = contact%cparam%DISTCLR_INIT
1652 distclr = contact%cparam%DISTCLR_FREE
1655 do i= 1,
size(contact%slave)
1665 allocate(contact_surf(
size(nodeid)))
1666 allocate(states_prev(
size(contact%slave)))
1667 contact_surf(:) =
size(elemid)+1
1668 do i = 1,
size(contact%slave)
1669 states_prev(i) = contact%states(i)%state
1683 do i= 1,
size(contact%slave)
1684 slave = contact%slave(i)
1688 contact_surf(contact%slave(i)) = -contact%states(i)%surface
1690 else if( contact%states(i)%state==
contactfree )
then
1691 coord(:) = currpos(3*slave-2:3*slave)
1696 if (ncand == 0) cycle
1697 allocate(indexcand(ncand))
1701 allocate(indexmaster(nmastermax))
1707 if (.not.
is_in_surface_box( contact%master(id), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
1708 nmaster = nmaster + 1
1709 indexmaster(nmaster) = id
1711 deallocate(indexcand)
1713 if(nmaster == 0)
then
1714 deallocate(indexmaster)
1719 id = indexmaster(idm)
1720 etype = contact%master(id)%etype
1721 nn =
size( contact%master(id)%nodes )
1723 iss = contact%master(id)%nodes(j)
1724 elem(1:3,j)=currpos(3*iss-2:3*iss)
1727 isin,distclr,localclr=contact%cparam%CLEARANCE )
1728 if( .not. isin ) cycle
1729 contact%states(i)%surface = id
1730 contact%states(i)%multiplier(:) = 0.d0
1731 iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
1733 call cal_node_normal( id, iss, contact%master, currpos, contact%states(i)%lpos(1:2), &
1734 contact%states(i)%direction(:) )
1735 contact_surf(contact%slave(i)) = id
1736 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3,A,3f7.3)')
"Node",nodeid(slave),
" contact with element", &
1737 elemid(contact%master(id)%eid), &
1738 " with distance ", contact%states(i)%distance,
" at ",contact%states(i)%lpos(1:2), &
1739 " along direction ", contact%states(i)%direction
1742 deallocate(indexmaster)
1749 do i = 1,
size(contact%slave)
1751 if (abs(contact_surf(contact%slave(i))) /= contact%states(i)%surface)
then
1753 write(*,
'(A,i10,A,i6,A,i6,A)')
"Node",nodeid(contact%slave(i)), &
1754 " in rank",hecmw_comm_get_rank(),
" freed due to duplication"
1756 nactive = nactive + 1
1760 infoctchange%free2contact = infoctchange%free2contact + 1
1762 infoctchange%contact2free = infoctchange%contact2free + 1
1765 active = (nactive > 0)
1766 deallocate(contact_surf)
1767 deallocate(states_prev)