27 character(len=HECMW_NAME_LEN) :: name
30 character(len=HECMW_NAME_LEN) :: pair_name
31 integer :: surf_id1, surf_id2
32 integer :: surf_id1_sgrp
34 integer,
pointer :: slave(:)=>null()
35 real(kind=kreal) :: fcoeff
36 real(kind=kreal) :: tpenalty
38 real(kind=kreal) :: ctime
39 integer(kind=kint) :: if_type
40 real(kind=kreal) :: if_etime
41 real(kind=kreal) :: initial_pos
42 real(kind=kreal) :: end_pos
57 type(hecmwst_contact_comm) :: comm
58 type(bucketdb) :: master_bktdb
60 type(tcontactparam),
pointer :: cparam=>null()
65 integer(kind=kint) :: contact2free
66 integer(kind=kint) :: contact2neighbor
67 integer(kind=kint) :: contact2difflpos
68 integer(kind=kint) :: free2contact
69 integer(kind=kint) :: contactnode_previous
70 integer(kind=kint) :: contactnode_current
73 private :: is_mpc_available
74 private :: is_active_contact
75 private :: cal_node_normal
76 private :: track_contact_position
77 private :: reset_contact_force
82 logical function is_mpc_available( contact )
83 type(
tcontact),
intent(in) :: contact
84 is_mpc_available = .true.
85 if( contact%fcoeff/=0.d0 ) is_mpc_available = .false.
90 integer(kind=kint),
intent(in) :: file
91 type(
tcontact),
intent(in) :: contact
93 write(file,*)
"CONTACT:", contact%ctype,contact%group,trim(contact%pair_name),contact%fcoeff
94 write(file,*)
"---Slave----"
95 write(file,*)
"num.slave",
size(contact%slave)
96 if(
associated(contact%slave) )
then
97 do i=1,
size(contact%slave)
98 write(file, *) contact%slave(i)
101 write(file,*)
"----master---"
102 write(file,*)
"num.master",
size(contact%master)
103 if(
associated(contact%master) )
then
104 do i=1,
size(contact%master)
112 type(
tcontact),
intent(inout) :: contact
114 if(
associated( contact%slave ) )
deallocate(contact%slave)
115 if(
associated( contact%master ) )
then
116 do i=1,
size( contact%master )
119 deallocate(contact%master)
121 if(
associated(contact%states) )
deallocate(contact%states)
128 type(
tcontact),
intent(inout) :: contact
129 type(hecmwst_local_mesh),
pointer :: hecmesh
138 do i=1,hecmesh%contact_pair%n_pair
139 if( hecmesh%contact_pair%name(i) == contact%pair_name )
then
140 contact%ctype = hecmesh%contact_pair%type(i)
141 contact%surf_id1 = hecmesh%contact_pair%slave_grp_id(i)
142 contact%surf_id2 = hecmesh%contact_pair%master_grp_id(i)
143 contact%surf_id1_sgrp = hecmesh%contact_pair%slave_orisgrp_id(i)
147 if( .not. isfind ) return;
148 if( contact%fcoeff<=0.d0 ) contact%fcoeff=0.d0
149 if( contact%ctype < 1 .and. contact%ctype > 3 )
return
150 if( contact%group<=0 )
return
157 type(
tcontact),
intent(inout) :: contact
158 type(hecmwst_local_mesh),
pointer :: hecmesh
159 type(tcontactparam),
target :: cparam
160 integer(kint),
intent(in),
optional :: myrank
162 integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
163 integer :: count,nodeid
167 contact%cparam => cparam
170 cgrp = contact%surf_id2
172 is= hecmesh%surf_group%grp_index(cgrp-1) + 1
173 ie= hecmesh%surf_group%grp_index(cgrp )
175 if(
present(myrank))
then
179 ic = hecmesh%surf_group%grp_item(2*i-1)
180 if(hecmesh%elem_ID(ic*2) /= myrank) cycle
183 allocate( contact%master(count) )
186 ic = hecmesh%surf_group%grp_item(2*i-1)
187 if(hecmesh%elem_ID(ic*2) /= myrank) cycle
189 nsurf = hecmesh%surf_group%grp_item(2*i)
190 ic_type = hecmesh%elem_type(ic)
192 iss = hecmesh%elem_node_index(ic-1)
193 do j=1,
size( contact%master(count)%nodes )
194 nn = contact%master(count)%nodes(j)
195 contact%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
201 allocate( contact%master(ie-is+1) )
203 ic = hecmesh%surf_group%grp_item(2*i-1)
204 nsurf = hecmesh%surf_group%grp_item(2*i)
205 ic_type = hecmesh%elem_type(ic)
207 iss = hecmesh%elem_node_index(ic-1)
208 do j=1,
size( contact%master(i-is+1)%nodes )
209 nn = contact%master(i-is+1)%nodes(j)
210 contact%master(i-is+1)%nodes(j) = hecmesh%elem_node_item( iss+nn )
218 cgrp = contact%surf_id1
220 is= hecmesh%node_group%grp_index(cgrp-1) + 1
221 ie= hecmesh%node_group%grp_index(cgrp )
224 nodeid = hecmesh%global_node_ID(hecmesh%node_group%grp_item(i))
225 if(
present(myrank))
then
230 if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal)
then
235 allocate( contact%slave(nslave) )
238 if(.not.
present(myrank))
then
240 if( hecmesh%node_group%grp_item(i) > hecmesh%nn_internal) cycle
243 contact%slave(ii) = hecmesh%node_group%grp_item(i)
247 allocate( contact%states(nslave) )
261 contact%symmetric = .true.
267 type(
tcontact),
intent(inout) :: embed
268 type(hecmwst_local_mesh),
pointer :: hecmesh
269 type(tcontactparam),
target :: cparam
270 integer(kint),
intent(in),
optional :: myrank
272 integer :: i, j, is, ie, cgrp, nsurf, nslave, ic, ic_type, iss, nn, ii
273 integer :: count,nodeid
277 embed%cparam => cparam
280 cgrp = embed%surf_id2
282 is= hecmesh%elem_group%grp_index(cgrp-1) + 1
283 ie= hecmesh%elem_group%grp_index(cgrp )
285 if(
present(myrank))
then
289 ic = hecmesh%elem_group%grp_item(i)
290 if(hecmesh%elem_ID(ic*2) /= myrank) cycle
293 allocate( embed%master(count) )
296 ic = hecmesh%elem_group%grp_item(i)
297 if(hecmesh%elem_ID(ic*2) /= myrank) cycle
299 ic_type = hecmesh%elem_type(ic)
301 iss = hecmesh%elem_node_index(ic-1)
302 do j=1,
size( embed%master(count)%nodes )
303 nn = embed%master(count)%nodes(j)
304 embed%master(count)%nodes(j) = hecmesh%elem_node_item( iss+nn )
310 allocate( embed%master(ie-is+1) )
312 ic = hecmesh%elem_group%grp_item(i)
313 ic_type = hecmesh%elem_type(ic)
315 iss = hecmesh%elem_node_index(ic-1)
316 do j=1,
size( embed%master(i-is+1)%nodes )
317 nn = embed%master(i-is+1)%nodes(j)
318 embed%master(i-is+1)%nodes(j) = hecmesh%elem_node_item( iss+nn )
325 cgrp = embed%surf_id1
327 is= hecmesh%node_group%grp_index(cgrp-1) + 1
328 ie= hecmesh%node_group%grp_index(cgrp )
331 nodeid = hecmesh%global_node_ID(hecmesh%node_group%grp_item(i))
332 if(
present(myrank))
then
337 if( hecmesh%node_group%grp_item(i) <= hecmesh%nn_internal)
then
342 allocate( embed%slave(nslave) )
345 if(.not.
present(myrank))
then
347 if( hecmesh%node_group%grp_item(i) > hecmesh%nn_internal) cycle
350 embed%slave(ii) = hecmesh%node_group%grp_item(i)
354 allocate( embed%states(nslave) )
368 embed%symmetric = .true.
373 type(tcontactinterference),
intent(inout) :: contact_if
383 do i = 1,
size(contacts)
384 if( contacts(i)%pair_name == contact_if%cp_name )
then
385 contacts(i)%if_type = contact_if%if_type
386 contacts(i)%if_etime = contact_if%etime
387 contacts(i)%initial_pos = contact_if%initial_pos
388 contacts(i)%end_pos = contact_if%end_pos
389 do j = 1,
size(contacts(i)%states)
390 contacts(i)%states(j)%interference_flag = contact_if%if_type
391 contacts(i)%states(j)%init_pos = contact_if%initial_pos
392 contacts(i)%states(j)%end_pos = contact_if%end_pos
394 contacts(i)%states(j)%time_factor = (contact_if%end_pos - contact_if%initial_pos) / contact_if%etime
396 contacts(i)%states(j)%time_factor = contact_if%etime
403 if( .not. isfind ) return;
410 type(
tcontact),
intent(inout) :: contact
412 if( .not.
associated(contact%states) )
return
413 do i=1,
size( contact%states )
414 contact%states(i)%state = -1
419 logical function is_active_contact( acgrp, contact )
420 integer,
intent(in) :: acgrp(:)
421 type(
tcontact),
intent(in) :: contact
422 if( any( acgrp==contact%group ) )
then
423 is_active_contact = .true.
425 is_active_contact = .false.
433 nodeID, elemID, is_init, active, mu, B )
434 character(len=9),
intent(in) :: flag_ctAlgo
435 type(
tcontact ),
intent(inout) :: contact
437 real(kind=kreal),
intent(in) :: currpos(:)
438 real(kind=kreal),
intent(in) :: currdisp(:)
439 real(kind=kreal),
intent(in) :: ndforce(:)
440 integer(kind=kint),
intent(in) :: nodeID(:)
441 integer(kind=kint),
intent(in) :: elemID(:)
442 logical,
intent(in) :: is_init
443 logical,
intent(out) :: active
444 real(kind=kreal),
intent(in) :: mu
445 real(kind=kreal),
optional,
target :: b(:)
447 real(kind=kreal) :: distclr
448 integer(kind=kint) :: slave, id, etype
449 integer(kind=kint) :: nn, i, j, iSS, nactive
450 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
451 real(kind=kreal) :: nlforce, slforce(3)
453 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
455 integer,
pointer :: indexMaster(:),indexCand(:)
456 integer :: nMaster,idm,nMasterMax,bktID,nCand
457 logical :: is_cand, is_present_B
458 real(kind=kreal),
pointer :: bp(:)
461 distclr = contact%cparam%DISTCLR_INIT
463 distclr = contact%cparam%DISTCLR_FREE
466 do i= 1,
size(contact%slave)
475 allocate(contact_surf(
size(nodeid)))
476 allocate(states_prev(
size(contact%slave)))
477 contact_surf(:) = huge(0)
478 do i = 1,
size(contact%slave)
479 states_prev(i) = contact%states(i)%state
486 is_present_b =
present(b)
487 if( is_present_b ) bp => b
497 do i= 1,
size(contact%slave)
498 if(contact%if_type /= 0)
call set_shrink_factor(contact%ctime, contact%states(i), contact%if_etime, contact%if_type)
499 slave = contact%slave(i)
501 slforce(1:3)=ndforce(3*slave-2:3*slave)
502 id = contact%states(i)%surface
503 nlforce = contact%states(i)%multiplier(1)
508 if (.not.is_init) cycle
511 if( nlforce < contact%cparam%TENSILE_FORCE )
then
513 contact%states(i)%multiplier(:) = 0.d0
514 write(*,
'(A,i10,A,i10,A,e12.3)')
"Node",nodeid(slave),
" free from contact with element", &
515 elemid(contact%master(id)%eid),
" with tensile force ", nlforce
518 if( contact%algtype /=
contactfslid .or. (.not. is_present_b) )
then
519 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
521 call track_contact_position( flag_ctalgo, i, contact, currpos, currdisp, mu, infoctchange, nodeid, elemid, bp )
523 id = contact%states(i)%surface
524 contact_surf(contact%slave(i)) = -elemid(contact%master(id)%eid)
528 else if( contact%states(i)%state==
contactfree )
then
529 if( contact%algtype ==
contacttied .and. .not. is_init ) cycle
530 coord(:) = currpos(3*slave-2:3*slave)
535 if (ncand == 0) cycle
536 allocate(indexcand(ncand))
540 allocate(indexmaster(nmastermax))
546 if (.not.
is_in_surface_box( contact%master(id), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
547 nmaster = nmaster + 1
548 indexmaster(nmaster) = id
550 deallocate(indexcand)
552 if(nmaster == 0)
then
553 deallocate(indexmaster)
558 id = indexmaster(idm)
559 etype = contact%master(id)%etype
560 nn =
size( contact%master(id)%nodes )
562 iss = contact%master(id)%nodes(j)
563 elem(1:3,j)=currpos(3*iss-2:3*iss)
566 isin,distclr,localclr=contact%cparam%CLEARANCE )
567 if( .not. isin ) cycle
568 contact%states(i)%surface = id
569 contact%states(i)%multiplier(:) = 0.d0
570 iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
572 call cal_node_normal( id, iss, contact%master, currpos, contact%states(i)%lpos(1:2), &
573 contact%states(i)%direction(:) )
574 contact_surf(contact%slave(i)) = elemid(contact%master(id)%eid)
575 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3,A,3f7.3,A,i6)')
"Node",nodeid(slave),
" contact with element", &
576 elemid(contact%master(id)%eid), &
577 " with distance ", contact%states(i)%distance,
" at ",contact%states(i)%lpos(1:2), &
578 " along direction ", contact%states(i)%direction,
" rank=",hecmw_comm_get_rank()
581 deallocate(indexmaster)
586 if( contact%algtype ==
contacttied .and. .not. is_init )
then
587 deallocate(contact_surf)
588 deallocate(states_prev)
594 do i = 1,
size(contact%slave)
596 id = contact%states(i)%surface
597 if (abs(contact_surf(contact%slave(i))) /= elemid(contact%master(id)%eid))
then
599 write(*,
'(A,i10,A,i10,A,i6,A,i6,A)')
"Node",nodeid(contact%slave(i)),
" contact with element", &
600 & elemid(contact%master(id)%eid),
" in rank",hecmw_comm_get_rank(),
" freed due to duplication"
602 nactive = nactive + 1
606 infoctchange%free2contact = infoctchange%free2contact + 1
608 infoctchange%contact2free = infoctchange%contact2free + 1
611 active = (nactive > 0)
612 deallocate(contact_surf)
613 deallocate(states_prev)
619 subroutine scan_embed_state( flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, &
620 nodeID, elemID, is_init, active, mu, B )
621 character(len=9),
intent(in) :: flag_ctAlgo
622 type(
tcontact ),
intent(inout) :: embed
624 real(kind=kreal),
intent(in) :: currpos(:)
625 real(kind=kreal),
intent(in) :: currdisp(:)
626 real(kind=kreal),
intent(in) :: ndforce(:)
627 integer(kind=kint),
intent(in) :: nodeID(:)
628 integer(kind=kint),
intent(in) :: elemID(:)
629 logical,
intent(in) :: is_init
630 logical,
intent(out) :: active
631 real(kind=kreal),
intent(in) :: mu
632 real(kind=kreal),
optional,
target :: b(:)
634 real(kind=kreal) :: distclr
635 integer(kind=kint) :: slave, id, etype
636 integer(kind=kint) :: nn, i, j, iSS, nactive
637 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
638 real(kind=kreal) :: nlforce, slforce(3)
640 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
642 integer,
pointer :: indexMaster(:),indexCand(:)
643 integer :: nMaster,idm,nMasterMax,bktID,nCand
644 logical :: is_cand, is_present_B
645 real(kind=kreal),
pointer :: bp(:)
648 distclr = embed%cparam%DISTCLR_INIT
650 distclr = embed%cparam%DISTCLR_FREE
652 do i= 1,
size(embed%slave)
661 allocate(contact_surf(
size(nodeid)))
662 allocate(states_prev(
size(embed%slave)))
663 contact_surf(:) = huge(0)
664 do i = 1,
size(embed%slave)
665 states_prev(i) = embed%states(i)%state
672 is_present_b =
present(b)
673 if( is_present_b ) bp => b
683 do i= 1,
size(embed%slave)
684 slave = embed%slave(i)
686 coord(:) = currpos(3*slave-2:3*slave)
691 if (ncand == 0) cycle
692 allocate(indexcand(ncand))
696 allocate(indexmaster(nmastermax))
702 if (.not.
is_in_surface_box( embed%master(id), coord(1:3), embed%cparam%BOX_EXP_RATE )) cycle
703 nmaster = nmaster + 1
704 indexmaster(nmaster) = id
706 deallocate(indexcand)
708 if(nmaster == 0)
then
709 deallocate(indexmaster)
714 id = indexmaster(idm)
715 etype = embed%master(id)%etype
716 if( mod(etype,10) == 2 ) etype = etype - 1
717 nn = getnumberofnodes(etype)
719 iss = embed%master(id)%nodes(j)
720 elem(1:3,j)=currpos(3*iss-2:3*iss)
723 isin,distclr,localclr=embed%cparam%CLEARANCE )
724 if( .not. isin ) cycle
725 embed%states(i)%surface = id
726 embed%states(i)%multiplier(:) = 0.d0
727 contact_surf(embed%slave(i)) = elemid(embed%master(id)%eid)
728 write(*,
'(A,i10,A,i10,A,3f7.3,A,i6)')
"Node",nodeid(slave),
" embeded to element", &
729 elemid(embed%master(id)%eid),
" at ",embed%states(i)%lpos(:),
" rank=",hecmw_comm_get_rank()
732 deallocate(indexmaster)
739 do i = 1,
size(embed%slave)
741 id = embed%states(i)%surface
742 if (abs(contact_surf(embed%slave(i))) /= elemid(embed%master(id)%eid))
then
744 write(*,
'(A,i10,A,i10,A,i6,A,i6,A)')
"Node",nodeid(embed%slave(i)),
" contact with element", &
745 & elemid(embed%master(id)%eid),
" in rank",hecmw_comm_get_rank(),
" freed due to duplication"
747 nactive = nactive + 1
751 infoctchange%free2contact = infoctchange%free2contact + 1
753 infoctchange%contact2free = infoctchange%contact2free + 1
756 active = (nactive > 0)
757 deallocate(contact_surf)
758 deallocate(states_prev)
763 subroutine cal_node_normal( csurf, isin, surf, currpos, lpos, normal )
765 integer,
intent(in) :: csurf
766 integer,
intent(in) :: isin
768 real(kind=kreal),
intent(in) :: currpos(:)
769 real(kind=kreal),
intent(in) :: lpos(:)
770 real(kind=kreal),
intent(out) :: normal(3)
771 integer(kind=kint) :: cnode, i, j, cnt, nd1, gn, etype, iSS, nn,cgn
772 real(kind=kreal) :: cnpos(2), elem(3, l_max_elem_node )
773 integer(kind=kint) :: cnode1, cnode2, gn1, gn2, nsurf, cgn1, cgn2, isin_n
774 real(kind=kreal) :: x=0, normal_n(3), lpos_n(2)
776 if( 1 <= isin .and. isin <= 4 )
then
778 gn = surf(csurf)%nodes(cnode)
779 etype = surf(csurf)%etype
781 nn =
size( surf(csurf)%nodes )
783 iss = surf(csurf)%nodes(j)
784 elem(1:3,j)=currpos(3*iss-2:3*iss)
788 do i=1,surf(csurf)%n_neighbor
789 nd1 = surf(csurf)%neighbor(i)
790 nn =
size( surf(nd1)%nodes )
791 etype = surf(nd1)%etype
794 iss = surf(nd1)%nodes(j)
795 elem(1:3,j)=currpos(3*iss-2:3*iss)
802 normal = normal+normal_n
807 elseif( 12 <= isin .and. isin <= 41 )
then
809 cnode2 = mod(isin, 10)
810 gn1 = surf(csurf)%nodes(cnode1)
811 gn2 = surf(csurf)%nodes(cnode2)
812 etype = surf(csurf)%etype
813 nn =
size( surf(csurf)%nodes )
815 iss = surf(csurf)%nodes(j)
816 elem(1:3,j)=currpos(3*iss-2:3*iss)
820 case (fe_tri3n, fe_tri6n, fe_tri6nc)
821 if ( isin==12 ) then; x=lpos(2)-lpos(1)
822 elseif( isin==23 ) then; x=1.d0-2.d0*lpos(2)
823 elseif( isin==31 ) then; x=2.d0*lpos(1)-1.d0
824 else; stop
"Error: cal_node_normal: invalid isin"
826 case (fe_quad4n, fe_quad8n)
827 if ( isin==12 ) then; x=lpos(1)
828 elseif( isin==23 ) then; x=lpos(2)
829 elseif( isin==34 ) then; x=-lpos(1)
830 elseif( isin==41 ) then; x=-lpos(2)
831 else; stop
"Error: cal_node_normal: invalid isin"
836 neib_loop:
do i=1, surf(csurf)%n_neighbor
837 nd1 = surf(csurf)%neighbor(i)
838 nn =
size( surf(nd1)%nodes )
839 etype = surf(nd1)%etype
843 iss = surf(nd1)%nodes(j)
844 elem(1:3,j)=currpos(3*iss-2:3*iss)
845 if( iss==gn1 ) cgn1=j
846 if( iss==gn2 ) cgn2=j
848 if( cgn1>0 .and. cgn2>0 )
then
850 isin_n = 10*cgn2 + cgn1
853 case (fe_tri3n, fe_tri6n, fe_tri6nc)
854 if ( isin_n==12 ) then; lpos_n(1)=0.5d0*(1.d0-x); lpos_n(2)=0.5d0*(1.d0+x)
855 elseif( isin_n==23 ) then; lpos_n(1)=0.d0; lpos_n(2)=0.5d0*(1.d0-x)
856 elseif( isin_n==31 ) then; lpos_n(1)=0.5d0*(1.d0+x); lpos_n(2)=0.d0
857 else; stop
"Error: cal_node_normal: invalid isin_n"
859 case (fe_quad4n, fe_quad8n)
860 if ( isin_n==12 ) then; lpos_n(1)= x; lpos_n(2)=-1.d0
861 elseif( isin_n==23 ) then; lpos_n(1)= 1.d0; lpos_n(2)= x
862 elseif( isin_n==34 ) then; lpos_n(1)=-x; lpos_n(2)= 1.d0
863 elseif( isin_n==41 ) then; lpos_n(1)=-1.d0; lpos_n(2)=-x
864 else; stop
"Error: cal_node_normal: invalid isin_n"
869 normal = normal+normal_n
876 normal = normal/ dsqrt( dot_product( normal, normal ) )
877 end subroutine cal_node_normal
880 subroutine track_contact_position( flag_ctAlgo, nslave, contact, currpos, currdisp, mu, infoCTChange, nodeID, elemID, B )
881 character(len=9),
intent(in) :: flag_ctAlgo
882 integer,
intent(in) :: nslave
883 type(
tcontact ),
intent(inout) :: contact
885 real(kind=kreal),
intent(in) :: currpos(:)
886 real(kind=kreal),
intent(in) :: currdisp(:)
887 real(kind=kreal),
intent(in) :: mu
888 integer(kind=kint),
intent(in) :: nodeID(:)
889 integer(kind=kint),
intent(in) :: elemID(:)
890 real(kind=kreal),
intent(inout) :: b(:)
892 integer(kind=kint) :: slave, sid0, sid, etype
893 integer(kind=kint) :: nn, i, j, iSS
894 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
896 real(kind=kreal) :: opos(2), odirec(3)
897 integer(kind=kint) :: bktID, nCand, idm
898 integer(kind=kint),
allocatable :: indexCand(:)
902 slave = contact%slave(nslave)
903 coord(:) = currpos(3*slave-2:3*slave)
905 sid0 = contact%states(nslave)%surface
906 opos = contact%states(nslave)%lpos(1:2)
907 odirec = contact%states(nslave)%direction
908 etype = contact%master(sid0)%etype
909 nn = getnumberofnodes( etype )
911 iss = contact%master(sid0)%nodes(j)
912 elem(1:3,j)=currpos(3*iss-2:3*iss)
913 elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
915 call project_point2element( coord,etype,nn,elem,contact%master(sid0)%reflen,contact%states(nslave), &
916 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos(1:2),contact%cparam%CLR_SAME_ELEM )
917 if( .not. isin )
then
918 do i=1, contact%master(sid0)%n_neighbor
919 sid = contact%master(sid0)%neighbor(i)
920 etype = contact%master(sid)%etype
921 nn = getnumberofnodes( etype )
923 iss = contact%master(sid)%nodes(j)
924 elem(1:3,j)=currpos(3*iss-2:3*iss)
927 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
929 contact%states(nslave)%surface = sid
935 if( .not. isin )
then
936 write(*,*)
'Warning: contact moved beyond neighbor elements'
941 allocate(indexcand(ncand))
945 if( sid==sid0 ) cycle
946 if(
associated(contact%master(sid0)%neighbor) )
then
947 if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
949 if (.not.
is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
950 etype = contact%master(sid)%etype
951 nn =
size( contact%master(sid)%nodes )
953 iss = contact%master(sid)%nodes(j)
954 elem(1:3,j)=currpos(3*iss-2:3*iss)
957 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
959 contact%states(nslave)%surface = sid
963 deallocate(indexcand)
968 if( contact%states(nslave)%surface==sid0 )
then
969 if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS))
then
971 infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
974 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3)')
"Node",nodeid(slave),
" move to contact with", &
975 elemid(contact%master(sid)%eid),
" with distance ", &
976 contact%states(nslave)%distance,
" at ",contact%states(nslave)%lpos(1:2)
978 infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
979 if( flag_ctalgo==
'ALagrange' ) &
980 call reset_contact_force( contact, currpos, nslave, sid0, opos, odirec, b )
982 if( flag_ctalgo==
'SLagrange' )
call update_tangentforce(etype,nn,elem0,elem,contact%states(nslave))
983 iss = isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
985 call cal_node_normal( contact%states(nslave)%surface, iss, contact%master, currpos, &
986 contact%states(nslave)%lpos(1:2), contact%states(nslave)%direction(:) )
987 else if( .not. isin )
then
988 write(*,
'(A,i10,A)')
"Node",nodeid(slave),
" move out of contact"
990 contact%states(nslave)%multiplier(:) = 0.d0
993 end subroutine track_contact_position
997 integer,
intent(in) :: nslave
998 type(
tcontact ),
intent(inout) :: contact
999 real(kind=kreal),
intent(in) :: currpos(:)
1001 integer(kind=kint) :: slave, sid0, sid, etype
1002 integer(kind=kint) :: nn, i, j, iSS
1003 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
1005 real(kind=kreal) :: opos(2), odirec(3)
1006 integer(kind=kint) :: bktID, nCand, idm
1007 integer(kind=kint),
allocatable :: indexCand(:)
1012 slave = contact%slave(nslave)
1013 coord(:) = currpos(3*slave-2:3*slave)
1015 sid0 = contact%states(nslave)%surface
1016 opos = contact%states(nslave)%lpos(1:2)
1017 odirec = contact%states(nslave)%direction
1018 etype = contact%master(sid0)%etype
1019 nn = getnumberofnodes( etype )
1021 iss = contact%master(sid0)%nodes(j)
1022 elem(1:3,j)=currpos(3*iss-2:3*iss)
1025 cstate_tmp%state = contact%states(nslave)%state
1026 cstate_tmp%surface = sid0
1028 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos,contact%cparam%CLR_SAME_ELEM )
1031 iss = isinsideelement( etype, cstate_tmp%lpos, contact%cparam%CLR_CAL_NORM )
1033 call cal_node_normal( cstate_tmp%surface, iss, contact%master, currpos, &
1034 cstate_tmp%lpos, cstate_tmp%direction(:) )
1037 contact%states(nslave)%direction = cstate_tmp%direction
1044 subroutine reset_contact_force( contact, currpos, lslave, omaster, opos, odirec, B )
1045 type(
tcontact ),
intent(inout) :: contact
1046 real(kind=kreal),
intent(in) :: currpos(:)
1047 integer,
intent(in) :: lslave
1048 integer,
intent(in) :: omaster
1049 real(kind=kreal),
intent(in) :: opos(2)
1050 real(kind=kreal),
intent(in) :: odirec(3)
1051 real(kind=kreal),
intent(inout) :: b(:)
1053 integer(kind=kint) :: slave, etype, master
1054 integer(kind=kint) :: nn, j, iSS
1055 real(kind=kreal) :: nrlforce, fcoeff, tangent(3,2)
1056 real(kind=kreal) :: elemcrd(3, l_max_elem_node )
1057 real(kind=kreal) :: shapefunc(l_max_surface_node)
1058 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1059 real(kind=kreal) :: fric(2), f3(l_max_elem_node*3+3)
1060 integer(kind=kint) :: i, idx0
1062 slave = contact%slave(lslave)
1063 fcoeff = contact%fcoeff
1065 nrlforce = contact%states(lslave)%multiplier(1)
1066 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)+nrlforce*odirec
1067 nn =
size( contact%master(omaster)%nodes )
1068 etype = contact%master(omaster)%etype
1069 call getshapefunc( etype, opos(:), shapefunc )
1071 iss = contact%master(omaster)%nodes(j)
1076 b(idx0+i) = b(idx0+i)-nrlforce*shapefunc(j)*odirec(i)
1079 if( fcoeff/=0.d0 )
then
1081 iss = contact%master(omaster)%nodes(j)
1082 elemcrd(:,j) = currpos(3*iss-2:3*iss)
1086 fric(1:2) = contact%states(lslave)%multiplier(2:3)
1087 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1088 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)+f3(1:3)
1090 iss = contact%master(omaster)%nodes(j)
1095 b(idx0+i) = b(idx0+i)+f3(3*j+i)
1101 master = contact%states(lslave)%surface
1102 nn =
size( contact%master(master)%nodes )
1103 etype = contact%master(master)%etype
1104 call getshapefunc( etype, contact%states(lslave)%lpos(1:2), shapefunc )
1105 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(lslave)%direction
1107 iss = contact%master(master)%nodes(j)
1113 b(idx0+i) = b(idx0+i)+nrlforce* &
1114 shapefunc(j)*contact%states(lslave)%direction(i)
1117 if( fcoeff/=0.d0 )
then
1119 iss = contact%master(master)%nodes(j)
1120 elemcrd(:,j) = currpos(3*iss-2:3*iss)
1122 call dispincrematrix( contact%states(lslave)%lpos(1:2), etype, nn, elemcrd, tangent, &
1124 fric(1:2) = contact%states(lslave)%multiplier(2:3)
1125 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1126 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1128 iss = contact%master(master)%nodes(j)
1133 b(idx0+i) = b(idx0+i)-f3(3*j+i)
1138 end subroutine reset_contact_force
1145 type(
tcontact ),
intent(inout) :: contact
1146 real(kind=kreal),
intent(in) :: coord(:)
1147 real(kind=kreal),
intent(in) :: disp(:)
1148 real(kind=kreal),
intent(in) :: ddisp(:)
1149 real(kind=kreal),
intent(in) :: fcoeff
1150 real(kind=kreal),
intent(in) :: mu, mut
1151 real(kind=kreal),
intent(inout) :: b(:)
1153 integer(kind=kint) :: slave, etype, master
1154 integer(kind=kint) :: nn, i, j, iSS
1155 real(kind=kreal) :: nrlforce, elemdisp(3,l_max_elem_node), tangent(3,2)
1156 real(kind=kreal) :: dg(3), elemg(3), elemcrd(3, l_max_elem_node )
1157 real(kind=kreal) :: dgn, dxi(2), dxy(2), shapefunc(l_max_surface_node)
1158 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1159 real(kind=kreal) :: fric(2), f3(3*l_max_elem_node+3), edisp(3*l_max_elem_node+3)
1161 do i= 1,
size(contact%slave)
1163 slave = contact%slave(i)
1164 edisp(1:3) = ddisp(3*slave-2:3*slave)
1165 master = contact%states(i)%surface
1167 nn =
size( contact%master(master)%nodes )
1168 etype = contact%master(master)%etype
1170 iss = contact%master(master)%nodes(j)
1171 elemdisp(:,j) = ddisp(3*iss-2:3*iss)
1172 edisp(3*j+1:3*j+3) = ddisp(3*iss-2:3*iss)
1173 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1175 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1180 elemg(:) = elemg(:)+shapefunc(j)*elemdisp(:,j)
1182 dg(:) = ddisp(3*slave-2:3*slave) - elemg(:)
1183 dgn = dot_product( contact%states(i)%direction, dg )
1184 nrlforce = contact%states(i)%multiplier(1)- mu*(contact%states(i)%wkdist-dgn)
1185 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(i)%direction
1188 iss = contact%master(master)%nodes(j)
1189 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)+nrlforce* &
1190 shapefunc(j)*contact%states(i)%direction
1193 if( fcoeff==0.d0 ) cycle
1195 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1197 dxi(1) = dot_product( dispmat(1,1:nn*3+3), edisp(1:nn*3+3) )
1198 dxi(2) = dot_product( dispmat(2,1:nn*3+3), edisp(1:nn*3+3) )
1199 dxy(:) = matmul( metric, dxi )
1200 fric(1:2) = contact%states(i)%multiplier(2:3) + mut*dxy(1:2)
1201 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1204 dgn = dsqrt( f3(1)*f3(1)+f3(2)*f3(2)+f3(3)*f3(3) )
1205 f3(:) = f3(:)*fcoeff*contact%states(i)%multiplier(1)/dgn
1207 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1209 iss = contact%master(master)%nodes(j)
1210 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)-f3(3*j+1:3*j+3)
1219 type(
tcontact ),
intent(inout) :: contact
1220 real(kind=kreal),
intent(in) :: disp(:)
1221 real(kind=kreal),
intent(in) :: ddisp(:)
1222 real(kind=kreal),
intent(in) :: mu
1223 real(kind=kreal),
intent(inout) :: b(:)
1225 integer(kind=kint) :: slave, etype, master
1226 integer(kind=kint) :: nn, i, j, iss
1227 real(kind=kreal) :: nrlforce(3)
1228 real(kind=kreal) :: dg(3)
1229 real(kind=kreal) :: shapefunc(l_max_surface_node)
1230 real(kind=kreal) :: edisp(3*l_max_elem_node+3)
1232 do i= 1,
size(contact%slave)
1234 slave = contact%slave(i)
1235 edisp(1:3) = disp(3*slave-2:3*slave)+ddisp(3*slave-2:3*slave)
1236 master = contact%states(i)%surface
1238 nn =
size( contact%master(master)%nodes )
1239 etype = contact%master(master)%etype
1241 iss = contact%master(master)%nodes(j)
1242 edisp(3*j+1:3*j+3) = disp(3*iss-2:3*iss)+ddisp(3*iss-2:3*iss)
1244 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1247 dg(1:3) = edisp(1:3)
1249 dg(1:3) = dg(1:3)-shapefunc(j)*edisp(3*j+1:3*j+3)
1252 nrlforce(1:3) = contact%states(i)%multiplier(1:3)+mu*dg(1:3)
1254 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce(1:3)
1256 iss = contact%master(master)%nodes(j)
1257 b(3*iss-2:3*iss) = b(3*iss-2:3*iss) + shapefunc(j)*nrlforce(1:3)
1267 type(
tcontact ),
intent(inout) :: contact
1268 real(kind=kreal),
intent(in) :: coord(:)
1269 real(kind=kreal),
intent(in) :: disp(:)
1270 real(kind=kreal),
intent(in) :: ddisp(:)
1271 real(kind=kreal),
intent(in) :: fcoeff
1272 real(kind=kreal),
intent(in) :: mu, mut
1273 real(kind=kreal),
intent(out) :: gnt(2)
1274 logical,
intent(inout) :: ctchanged
1276 integer(kind=kint) :: slave, etype, master
1277 integer(kind=kint) :: nn, i, j, iss, cnt
1278 real(kind=kreal) :: elemdisp(3,l_max_elem_node), tangent(3,2)
1279 real(kind=kreal) :: dg(3), elemg(3), elemcrd(3, l_max_elem_node )
1280 real(kind=kreal) :: dgn, dxi(2), dxy(2), shapefunc(l_max_surface_node)
1281 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1282 real(kind=kreal) :: lgnt(2), fric(2), f3(3*l_max_elem_node+3), edisp(3*l_max_elem_node+3)
1284 cnt =0; lgnt(:)=0.d0
1285 do i= 1,
size(contact%slave)
1287 slave = contact%slave(i)
1288 edisp(1:3) = ddisp(3*slave-2:3*slave)
1289 master = contact%states(i)%surface
1291 nn =
size( contact%master(master)%nodes )
1292 etype = contact%master(master)%etype
1294 iss = contact%master(master)%nodes(j)
1295 elemdisp(:,j) = ddisp(3*iss-2:3*iss)
1296 edisp(3*j+1:3*j+3) = ddisp(3*iss-2:3*iss)
1297 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1299 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1304 elemg(:) = elemg(:)+shapefunc(j)*elemdisp(:,j)
1306 dg(:) = ddisp(3*slave-2:3*slave) - elemg(:)
1307 dgn = dot_product( contact%states(i)%direction, dg )
1308 contact%states(i)%wkdist = contact%states(i)%wkdist-dgn
1309 contact%states(i)%multiplier(1) = contact%states(i)%multiplier(1)- mu*contact%states(i)%wkdist
1310 contact%states(i)%distance = contact%states(i)%distance - dgn
1312 lgnt(1) = lgnt(1)- contact%states(i)%wkdist
1314 if( fcoeff==0.d0 ) cycle
1316 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1318 dxi(1) = dot_product( dispmat(1,1:nn*3+3), edisp(1:nn*3+3) )
1319 dxi(2) = dot_product( dispmat(2,1:nn*3+3), edisp(1:nn*3+3) )
1320 dxy(:) = matmul( metric, dxi )
1321 fric(1:2) = contact%states(i)%multiplier(2:3) + mut*dxy(1:2)
1322 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1323 dgn = dsqrt( f3(1)*f3(1)+f3(2)*f3(2)+f3(3)*f3(3) )
1324 if( contact%states(i)%multiplier(1)>0.d0 )
then
1325 if( dgn > fcoeff*contact%states(i)%multiplier(1) )
then
1328 print *,
"Node", slave,
"to slip state",dgn, fcoeff*contact%states(i)%multiplier(1)
1331 fric(:) = fric(:)*fcoeff*contact%states(i)%multiplier(1)/dgn
1335 print *,
"Node", slave,
"to stick state",dgn, fcoeff*contact%states(i)%multiplier(1)
1340 contact%states(i)%multiplier(2:3) = fric(:)
1341 dxy(:) = matmul( dg, tangent )
1342 lgnt(2) = lgnt(2)+dsqrt( dxy(1)*dxy(1)+dxy(2)*dxy(2) )
1344 if(cnt>0) lgnt(:) = lgnt(:)/cnt
1351 type(
tcontact ),
intent(inout) :: contact
1352 real(kind=kreal),
intent(in) :: disp(:)
1353 real(kind=kreal),
intent(in) :: ddisp(:)
1354 real(kind=kreal),
intent(in) :: mu
1355 logical,
intent(inout) :: ctchanged
1357 integer(kind=kint) :: slave, etype, master
1358 integer(kind=kint) :: nn, i, j, iss, cnt
1359 real(kind=kreal) :: dg(3), dgmax
1360 real(kind=kreal) :: shapefunc(l_max_surface_node)
1361 real(kind=kreal) :: edisp(3*l_max_elem_node+3)
1363 do i= 1,
size(contact%slave)
1365 slave = contact%slave(i)
1366 edisp(1:3) = disp(3*slave-2:3*slave)+ddisp(3*slave-2:3*slave)
1367 master = contact%states(i)%surface
1369 nn =
size( contact%master(master)%nodes )
1370 etype = contact%master(master)%etype
1372 iss = contact%master(master)%nodes(j)
1373 edisp(3*j+1:3*j+3) = disp(3*iss-2:3*iss)+ddisp(3*iss-2:3*iss)
1375 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1378 dg(1:3) = edisp(1:3)
1380 dg(1:3) = dg(1:3)-shapefunc(j)*edisp(3*j+1:3*j+3)
1383 contact%states(i)%multiplier(1:3) = contact%states(i)%multiplier(1:3) + mu*dg(1:3)
1388 dgmax = dgmax + dabs(edisp(j))
1390 dgmax = dgmax/dble((nn+1)*3)
1392 if( dabs(dg(j))/dmax1(1.d0,dgmax) > 1.d-3 ) ctchanged = .true.
1400 type(
tcontact ),
intent(in) :: contact
1401 real(kind=kreal),
intent(in) :: coord(:)
1402 real(kind=kreal),
intent(in) :: disp(:)
1403 real(kind=kreal),
intent(inout) :: b(:)
1405 integer(kind=kint) :: slave, etype, master
1406 integer(kind=kint) :: nn, i, j, iss
1407 real(kind=kreal) :: fcoeff, nrlforce, tangent(3,2)
1408 real(kind=kreal) :: elemcrd(3, l_max_elem_node )
1409 real(kind=kreal) :: shapefunc(l_max_surface_node)
1410 real(kind=kreal) :: metric(2,2), dispmat(2,l_max_elem_node*3+3)
1411 real(kind=kreal) :: fric(2), f3(l_max_elem_node*3+3)
1412 fcoeff = contact%fcoeff
1413 do i= 1,
size(contact%slave)
1415 slave = contact%slave(i)
1416 master = contact%states(i)%surface
1418 nn =
size( contact%master(master)%nodes )
1419 etype = contact%master(master)%etype
1420 call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
1423 nrlforce = contact%states(i)%multiplier(1)
1424 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-nrlforce*contact%states(i)%direction
1427 iss = contact%master(master)%nodes(j)
1428 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)+nrlforce* &
1429 shapefunc(j)*contact%states(i)%direction
1432 if( fcoeff==0.d0 ) cycle
1435 iss = contact%master(master)%nodes(j)
1436 elemcrd(:,j) = coord(3*iss-2:3*iss)+disp(3*iss-2:3*iss)
1438 call dispincrematrix( contact%states(i)%lpos(1:2), etype, nn, elemcrd, tangent, &
1441 fric(1:2) = contact%states(i)%multiplier(2:3)
1442 f3(:) = fric(1)*dispmat(1,:)+fric(2)*dispmat(2,:)
1443 b(3*slave-2:3*slave) = b(3*slave-2:3*slave)-f3(1:3)
1445 iss = contact%master(master)%nodes(j)
1446 b(3*iss-2:3*iss) = b(3*iss-2:3*iss)-f3(3*j+1:3*j+3)
1454 type(
tcontact ),
intent(in) :: contact
1455 real(kind=kreal),
intent(in) :: dt
1456 real(kind=kreal),
intent(inout) :: relvel_vec(:)
1457 real(kind=kreal),
intent(inout) :: state_vec(:)
1459 integer(kind=kint) :: i, slave
1461 do i= 1,
size(contact%slave)
1462 slave = contact%slave(i)
1463 if( state_vec(slave) < 0.1d0 .or. contact%states(i)%state > 0 ) &
1464 & state_vec(slave) = dble(contact%states(i)%state)
1467 if( dt < 1.d-16 ) cycle
1468 relvel_vec(3*slave-2:3*slave) = contact%states(i)%reldisp(1:3)/dt
1474 type(
tcontact ),
intent(inout) :: contact
1476 integer(kind=kint) :: i
1478 do i= 1,
size(contact%slave)
1480 contact%states(i)%tangentForce(1:3) = 0.d0
1481 contact%states(i)%tangentForce_trial(1:3) = 0.d0
1482 contact%states(i)%tangentForce_final(1:3) = 0.d0
1484 contact%states(i)%tangentForce(1:3) = contact%states(i)%tangentForce_final(1:3)
1486 contact%states(i)%tangentForce1(1:3) = contact%states(i)%tangentForce(1:3)
1492 integer,
intent(in) :: nslave
1493 type(
tcontact ),
intent(inout) :: contact
1495 real(kind=kreal),
intent(in) :: currpos(:)
1496 real(kind=kreal),
intent(in) :: currdisp(:)
1497 integer(kind=kint),
intent(in) :: nodeID(:)
1498 integer(kind=kint),
intent(in) :: elemID(:)
1500 integer(kind=kint) :: slave, sid0, sid, etype
1501 integer(kind=kint) :: nn, i, j, iSS
1502 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node ), elem0(3, l_max_elem_node )
1504 real(kind=kreal) :: opos(2), odirec(3)
1505 integer(kind=kint) :: bktID, nCand, idm
1506 integer(kind=kint),
allocatable :: indexCand(:)
1510 slave = contact%slave(nslave)
1511 coord(:) = currpos(3*slave-2:3*slave)
1513 sid0 = contact%states(nslave)%surface
1514 opos = contact%states(nslave)%lpos(1:2)
1515 odirec = contact%states(nslave)%direction
1516 etype = contact%master(sid0)%etype
1517 nn = getnumberofnodes( etype )
1519 iss = contact%master(sid0)%nodes(j)
1520 elem(1:3,j)=currpos(3*iss-2:3*iss)
1521 elem0(1:3,j)=currpos(3*iss-2:3*iss)-currdisp(3*iss-2:3*iss)
1523 call project_point2element( coord,etype,nn,elem,contact%master(sid0)%reflen,contact%states(nslave), &
1524 isin,contact%cparam%DISTCLR_NOCHECK,contact%states(nslave)%lpos(1:2),contact%cparam%CLR_SAME_ELEM )
1525 if( .not. isin )
then
1526 do i=1, contact%master(sid0)%n_neighbor
1527 sid = contact%master(sid0)%neighbor(i)
1528 etype = contact%master(sid)%etype
1529 nn = getnumberofnodes( etype )
1531 iss = contact%master(sid)%nodes(j)
1532 elem(1:3,j)=currpos(3*iss-2:3*iss)
1534 call project_point2element( coord,etype,nn,elem,contact%master(sid)%reflen,contact%states(nslave), &
1535 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
1537 contact%states(nslave)%surface = sid
1543 if( .not. isin )
then
1544 write(*,*)
'Warning: contact moved beyond neighbor elements'
1549 allocate(indexcand(ncand))
1552 sid = indexcand(idm)
1553 if( sid==sid0 ) cycle
1554 if( any(sid==contact%master(sid0)%neighbor(:)) ) cycle
1555 if (.not.
is_in_surface_box( contact%master(sid), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
1556 etype = contact%master(sid)%etype
1557 nn =
size( contact%master(sid)%nodes )
1559 iss = contact%master(sid)%nodes(j)
1560 elem(1:3,j)=currpos(3*iss-2:3*iss)
1562 call project_point2element( coord,etype,nn,elem,contact%master(sid)%reflen,contact%states(nslave), &
1563 isin,contact%cparam%DISTCLR_NOCHECK,localclr=contact%cparam%CLEARANCE )
1565 contact%states(nslave)%surface = sid
1569 deallocate(indexcand)
1574 if( contact%states(nslave)%surface==sid0 )
then
1575 if(any(dabs(contact%states(nslave)%lpos(1:2)-opos(:)) >= contact%cparam%CLR_DIFFLPOS))
then
1577 infoctchange%contact2difflpos = infoctchange%contact2difflpos + 1
1580 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3)')
"Node",nodeid(slave),
" move to contact with", &
1581 elemid(contact%master(sid)%eid),
" with distance ", &
1582 contact%states(nslave)%distance,
" at ",contact%states(nslave)%lpos(1:2)
1584 infoctchange%contact2neighbor = infoctchange%contact2neighbor + 1
1586 iss = isinsideelement( etype, contact%states(nslave)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
1588 call cal_node_normal( contact%states(nslave)%surface, iss, contact%master, currpos, &
1589 contact%states(nslave)%lpos(1:2), contact%states(nslave)%direction(:) )
1591 else if( .not. isin )
then
1592 write(*,
'(A,i10,A)')
"Node",nodeid(slave),
" move out of contact"
1594 contact%states(nslave)%multiplier(:) = 0.d0
1603 nodeID, elemID, is_init, active )
1604 type(
tcontact ),
intent(inout) :: contact
1606 real(kind=kreal),
intent(in) :: currpos(:)
1607 real(kind=kreal),
intent(in) :: currdisp(:)
1608 integer(kind=kint),
intent(in) :: nodeID(:)
1609 integer(kind=kint),
intent(in) :: elemID(:)
1610 logical,
intent(in) :: is_init
1611 logical,
intent(out) :: active
1613 real(kind=kreal) :: distclr
1614 integer(kind=kint) :: slave, id, etype
1615 integer(kind=kint) :: nn, i, j, iSS, nactive
1616 real(kind=kreal) :: coord(3), elem(3, l_max_elem_node )
1617 real(kind=kreal) :: nlforce
1619 integer(kind=kint),
allocatable :: contact_surf(:), states_prev(:)
1621 integer,
pointer :: indexMaster(:),indexCand(:)
1622 integer :: nMaster,idm,nMasterMax,bktID,nCand
1626 distclr = contact%cparam%DISTCLR_INIT
1628 distclr = contact%cparam%DISTCLR_FREE
1631 do i= 1,
size(contact%slave)
1641 allocate(contact_surf(
size(nodeid)))
1642 allocate(states_prev(
size(contact%slave)))
1643 contact_surf(:) =
size(elemid)+1
1644 do i = 1,
size(contact%slave)
1645 states_prev(i) = contact%states(i)%state
1659 do i= 1,
size(contact%slave)
1660 slave = contact%slave(i)
1664 contact_surf(contact%slave(i)) = -contact%states(i)%surface
1666 else if( contact%states(i)%state==
contactfree )
then
1667 coord(:) = currpos(3*slave-2:3*slave)
1672 if (ncand == 0) cycle
1673 allocate(indexcand(ncand))
1677 allocate(indexmaster(nmastermax))
1683 if (.not.
is_in_surface_box( contact%master(id), coord(1:3), contact%cparam%BOX_EXP_RATE )) cycle
1684 nmaster = nmaster + 1
1685 indexmaster(nmaster) = id
1687 deallocate(indexcand)
1689 if(nmaster == 0)
then
1690 deallocate(indexmaster)
1695 id = indexmaster(idm)
1696 etype = contact%master(id)%etype
1697 nn =
size( contact%master(id)%nodes )
1699 iss = contact%master(id)%nodes(j)
1700 elem(1:3,j)=currpos(3*iss-2:3*iss)
1703 isin,distclr,localclr=contact%cparam%CLEARANCE )
1704 if( .not. isin ) cycle
1705 contact%states(i)%surface = id
1706 contact%states(i)%multiplier(:) = 0.d0
1707 iss = isinsideelement( etype, contact%states(i)%lpos(1:2), contact%cparam%CLR_CAL_NORM )
1709 call cal_node_normal( id, iss, contact%master, currpos, contact%states(i)%lpos(1:2), &
1710 contact%states(i)%direction(:) )
1711 contact_surf(contact%slave(i)) = id
1712 write(*,
'(A,i10,A,i10,A,f7.3,A,2f7.3,A,3f7.3)')
"Node",nodeid(slave),
" contact with element", &
1713 elemid(contact%master(id)%eid), &
1714 " with distance ", contact%states(i)%distance,
" at ",contact%states(i)%lpos(1:2), &
1715 " along direction ", contact%states(i)%direction
1718 deallocate(indexmaster)
1725 do i = 1,
size(contact%slave)
1727 if (abs(contact_surf(contact%slave(i))) /= contact%states(i)%surface)
then
1729 write(*,
'(A,i10,A,i6,A,i6,A)')
"Node",nodeid(contact%slave(i)), &
1730 " in rank",hecmw_comm_get_rank(),
" freed due to duplication"
1732 nactive = nactive + 1
1736 infoctchange%free2contact = infoctchange%free2contact + 1
1738 infoctchange%contact2free = infoctchange%contact2free + 1
1741 active = (nactive > 0)
1742 deallocate(contact_surf)
1743 deallocate(states_prev)
This module provides bucket-search functionality It provides definition of bucket info and its access...
integer(kind=kint) function, public bucketdb_getbucketid(bktdb, x)
Get bucket ID that includes given point.
subroutine, public bucketdb_finalize(bktdb)
Finalizer.
integer(kind=kint) function, public bucketdb_getnumcand(bktdb, bid)
Get number of candidates within neighboring buckets of a given bucket Bucket ID has to be obtained wi...
subroutine, public bucketdb_init(bktdb)
Initializer.
subroutine, public bucketdb_getcand(bktdb, bid, ncand, cand)
Get candidates within neighboring buckets of a given bucket Number of candidates has to be obtained w...
This module encapsulate the basic functions of all elements provide by this software.
subroutine getvertexcoord(fetype, cnode, localcoord)
Get the natural coord of a vertex node.
real(kind=kreal) function, dimension(3) surfacenormal(fetype, nn, localcoord, elecoord)
Calculate normal of 3d-surface.
This module manages surface elements in 3D It provides basic definition of surface elements (triangla...
subroutine initialize_surf(eid, etype, nsurf, surf)
Initializer.
subroutine update_surface_reflen(surf, coord)
Compute reference length of surface elements.
subroutine write_surf(file, surf)
Write out elemental surface.
subroutine update_surface_box_info(surf, currpos)
Update info of cubic box including surface elements.
subroutine find_surface_neighbor(surf, bktDB)
Find neighboring surface elements.
subroutine update_surface_bucket_info(surf, bktDB)
Update bucket info for searching surface elements.
subroutine finalize_surf(surf)
Memory management subroutine.
logical function is_in_surface_box(surf, x0, exp_rate)
Check if given point is within cubic box including surface element.
Structure to define surface group.