FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_contact_geom.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
7  use hecmw
8  use elementinfo
9  use mcontactdef
10  implicit none
11 
12  public :: cal_node_normal
13 
14 contains
15 
16  ! TODO: Move from fstr_contact_lib.f90
18  subroutine project_point2element(xyz,etype,nn,elemt,reflen,cstate,isin,distclr,ctpos,localclr)
19  real(kind=kreal),intent(in) :: xyz(3)
20  integer, intent(in) :: etype
21  integer, intent(in) :: nn
22  real(kind=kreal),intent(in) :: elemt(:,:)
23  real(kind=kreal),intent(in) :: reflen
24  type(tcontactstate),intent(inout) :: cstate
25  logical, intent(out) :: isin
26  real(kind=kreal), intent(in) :: distclr
27  real(kind=kreal), optional :: ctpos(2)
28  real(kind=kreal), optional :: localclr
29 
30  integer :: count,order, initstate
31  real(kind=kreal) :: determ, inverse(2,2)
32  real(kind=kreal) :: sfunc(nn), curv(3,2,2)
33  real(kind=kreal) :: r(2), dr(2), r_tmp(2) ! natural coordinate
34  real(kind=kreal) :: xyz_out(3) ! curr. projection position
35  real(kind=kreal) :: dist_last,dist_now, dxyz(3) ! dist between the point and its projection
36  real(kind=kreal) :: tangent(3,2) ! base vectors in tangent space
37  real(kind=kreal) :: df(2),d2f(2,2),normal(3)
38  real(kind=kreal),parameter :: eps = 1.0d-8
39  real(kind=kreal) :: clr, tol, factor
40 
41  initstate = cstate%state
42  clr = 1.d-4
43  if( present( localclr ) ) clr=localclr
44  if( present( ctpos ) ) then
45  r(:)= ctpos
46  else
47  call getelementcenter( etype, r(:) )
48  endif
49 
50  tol = 1.0d0
51  do count=1,100
52  call getshapefunc( etype, r, sfunc )
53  xyz_out = matmul( elemt(1:3,1:nn), sfunc )
54  dxyz(1:3) = xyz_out(1:3) - xyz(1:3)
55  dist_last = dot_product( dxyz, dxyz(:) )
56 
57  call tangentbase( etype, nn, r, elemt(1:3,1:nn), tangent )
58  call curvature( etype, nn, r, elemt(1:3,1:nn), curv )
59 
60  ! dF(1:2)
61  df(1:2) = -matmul( dxyz(:), tangent(:,:) )
62  ! d2F(1:2,1:2)
63  d2f(1,1)= dot_product( tangent(:,1), tangent(:,1) ) - dot_product( dxyz, curv(:,1,1) )
64  d2f(1,2)= dot_product( tangent(:,1), tangent(:,2) ) - dot_product( dxyz, curv(:,1,2) )
65  d2f(2,1)= dot_product( tangent(:,2), tangent(:,1) ) - dot_product( dxyz, curv(:,2,1) )
66  d2f(2,2)= dot_product( tangent(:,2), tangent(:,2) ) - dot_product( dxyz, curv(:,2,2) )
67 
68  ! inverse of d2F
69  determ = d2f(1,1)*d2f(2,2) - d2f(1,2)*d2f(2,1)
70  if( determ==0.d0 ) stop "Math error in contact searching"
71  inverse(1,1) = d2f(2,2) / determ
72  inverse(2,2) = d2f(1,1) / determ
73  inverse(1,2) = -d2f(1,2) / determ
74  inverse(2,1) = -d2f(2,1) / determ
75  dr=matmul(inverse,df)
76 
77  tol=dot_product(dr,dr)
78  if( dsqrt(tol)> 3.d0 ) then ! too far away
79  r= -100.d0; exit
80  endif
81 
82  factor = 1.d0
83  do order=1,10
84  r_tmp(1:2) = r(1:2) + factor*dr(1:2)
85  call getshapefunc( etype, r_tmp, sfunc )
86  xyz_out(1:3) = matmul( elemt(1:3,1:nn), sfunc(:) )
87  dxyz(1:3) = xyz(1:3)-xyz_out(:)
88  dist_now = dot_product( dxyz, dxyz )
89  if(dist_now <= dist_last) exit
90  factor = factor*0.7d0
91  enddo
92  r(1:2) = r_tmp(1:2)
93 
94  if( tol<eps ) exit
95  enddo
96 
97  isin = .false.
98  cstate%state = contactfree
99  if( isinsideelement( etype, r, clr )>=0 ) then
100  dxyz(:)=xyz_out(:)-xyz(:)
101  normal(:) = surfacenormal( etype, nn, r, elemt(1:3,1:nn) )
102  normal(:) = normal(:)/dsqrt( dot_product(normal, normal) )
103  do count = 1,3
104  if( dabs(normal(count))<1.d-10 ) normal(count) =0.d0
105  if( dabs(1.d0-dabs(normal(count)))<1.d-10 ) normal(count) =sign(1.d0, normal(count))
106  enddo
107  cstate%distance = dot_product( dxyz, normal )
108 
109  if( cstate%interference_flag == c_if_slave) then
110  if( cstate%init_pos == 0.d0 .and. cstate%distance < cstate%end_pos) then
111  cstate%init_pos = cstate%distance
112  cstate%time_factor = (cstate%end_pos - cstate%distance) / cstate%time_factor
113  cstate%shrink_factor = cstate%distance
114  end if
115  end if
116 
117  if( cstate%interference_flag == 0)then ! not shrink-node
118  if( cstate%distance < distclr*reflen .and. cstate%distance > -5.0d-01*reflen ) isin = .true.
119  else
120  if( cstate%distance < cstate%shrink_factor + distclr*reflen ) isin = .true.
121  end if
122 
123  if( isin ) then
124  if( initstate== contactfree ) then
125  cstate%state = contactstick
126  else
127  cstate%state = initstate
128  endif
129  cstate%gpos(:)=xyz_out(:)
130  cstate%lpos(1:2)=r(:)
131  cstate%direction(:) = normal(:)
132  cstate%wkdist = cstate%distance
133  endif
134  endif
135  end subroutine project_point2element
136 
138  subroutine project_point2solidelement(xyz,etype,nn,elemt,reflen,cstate,isin,distclr,ctpos,localclr)
139  use m_utilities
140  real(kind=kreal),intent(in) :: xyz(3)
141  integer, intent(in) :: etype
142  integer, intent(in) :: nn
143  real(kind=kreal),intent(in) :: elemt(:,:)
144  real(kind=kreal),intent(in) :: reflen
145  type(tcontactstate),intent(inout) :: cstate
146  logical, intent(out) :: isin
147  real(kind=kreal), intent(in) :: distclr
148  real(kind=kreal), optional :: ctpos(3)
149  real(kind=kreal), optional :: localclr
150 
151  integer :: count,order, initstate
152  real(kind=kreal) :: inverse(3,3)
153  real(kind=kreal) :: sfunc(nn), deriv(nn,3)
154  real(kind=kreal) :: r(3), dr(3), r_tmp(3) ! natural coordinate
155  real(kind=kreal) :: xyz_out(3) ! curr. projection position
156  real(kind=kreal) :: dist_last,dist_now, dxyz(3) ! dist between the point and its projection
157  real(kind=kreal),parameter :: eps = 1.0d-8
158  real(kind=kreal) :: clr, tol, factor
159 
160  initstate = cstate%state
161  clr = 1.d-4
162  if( present( localclr ) ) clr=localclr
163  if( present( ctpos ) ) then
164  r(:)= ctpos
165  else
166  call getelementcenter( etype, r(:) )
167  endif
168 
169  tol = 1.0d0
170  do count=1,100
171  call getshapefunc( etype, r, sfunc )
172  xyz_out = matmul( elemt(1:3,1:nn), sfunc(1:nn) )
173  dxyz(1:3) = xyz_out(1:3) - xyz(1:3)
174  dist_last = dot_product( dxyz, dxyz(:) )
175 
176  call getshapederiv( etype, r, deriv )
177  inverse(1:3,1:3) = matmul(elemt(1:3,1:nn),deriv(1:nn,1:3))
178  call calinverse(3, inverse(1:3,1:3))
179  dr(1:3) = -matmul(inverse(1:3,1:3),dxyz(1:3))
180 
181  tol=dot_product(dr,dr)
182  if( count > 1 .and. dsqrt(tol)> 3.d0 ) then ! too far away
183  r= -100.d0; exit
184  endif
185 
186  factor = 1.d0
187  do order=1,10
188  r_tmp(1:3) = r(1:3) + factor*dr(1:3)
189  call getshapefunc( etype, r_tmp, sfunc )
190  xyz_out(1:3) = matmul( elemt(1:3,1:nn), sfunc(1:nn) )
191  dxyz(1:3) = xyz(1:3)-xyz_out(1:3)
192  dist_now = dot_product( dxyz, dxyz )
193  if(dist_now <= dist_last) exit
194  factor = factor*0.7d0
195  enddo
196  r(1:3) = r_tmp(1:3)
197 
198  if( tol<eps ) exit
199  enddo
200 
201  isin = .false.
202  cstate%state = contactfree
203  if( isinside3delement( etype, r, clr )>=0 ) then
204  dxyz(:)=xyz_out(:)-xyz(:)
205  cstate%distance = dsqrt(dot_product( dxyz, dxyz ))
206 
207  if( cstate%distance < distclr ) isin = .true.
208 
209  if( isin ) then
210  if( initstate== contactfree ) then
211  cstate%state = contactstick
212  else
213  cstate%state = initstate
214  endif
215  cstate%gpos(:)=xyz_out(:)
216  cstate%direction(:) = (/1.d0,0.d0,0.d0/)
217  cstate%lpos(1:3)=r(:)
218  endif
219  endif
220  end subroutine
221 
224  subroutine project_point2surfelement(xyz, surf, currpos, cstate, isin, distclr, ctpos, localclr)
225  real(kind=kreal), intent(in) :: xyz(3)
226  type(tsurfelement), intent(in) :: surf
227  real(kind=kreal), intent(in) :: currpos(:)
228  type(tcontactstate), intent(inout) :: cstate
229  logical, intent(out) :: isin
230  real(kind=kreal), intent(in) :: distclr
231  real(kind=kreal), optional, intent(in) :: ctpos(2)
232  real(kind=kreal), optional, intent(in) :: localclr
233 
234  integer(kind=kint) :: nn, j, iss
235  real(kind=kreal) :: elem(3, l_max_elem_node)
236 
237  ! Extract element coordinates from surf structure
238  nn = size(surf%nodes)
239  do j = 1, nn
240  iss = surf%nodes(j)
241  elem(1:3, j) = currpos(3*iss-2:3*iss)
242  enddo
243 
244  call project_point2element(xyz, surf%etype, nn, elem, surf%reflen, cstate, &
245  isin, distclr, ctpos, localclr)
246 
247  end subroutine project_point2surfelement
248 
250  subroutine getmetrictensor( pos, etype, ele, tensor )
251  real(kind=kreal), intent(in) :: pos(2)
252  integer, intent(in) :: etype
253  real(kind=kreal), intent(in) :: ele(:,:)
254  real(kind=kreal), intent(out) :: tensor(2,2)
255 
256  integer :: nn
257  real(kind=kreal) :: tangent(3,2)
258  nn= getnumberofnodes(etype)
259  call tangentbase( etype, nn, pos, ele, tangent )
260  tensor(1,1)= dot_product( tangent(:,1), tangent(:,1) )
261  tensor(1,2)= dot_product( tangent(:,1), tangent(:,2) )
262  tensor(2,1)= dot_product( tangent(:,2), tangent(:,1) )
263  tensor(2,2)= dot_product( tangent(:,2), tangent(:,2) )
264  end subroutine
265 
268  subroutine dispincrematrix( pos, etype, nnode, ele, tangent, tensor, matrix )
269  real(kind=kreal), intent(in) :: pos(2)
270  integer, intent(in) :: etype
271  integer, intent(in) :: nnode
272  real(kind=kreal), intent(in) :: ele(3,nnode)
273  real(kind=kreal), intent(out) :: tangent(3,2)
274  real(kind=kreal), intent(out) :: tensor(2,2)
275  real(kind=kreal), intent(out) :: matrix(2,nnode*3+3)
276 
277  integer :: i,j
278  real(kind=kreal) :: det
279  real(kind=kreal) :: shapefunc(nnode), t1(nnode*3+3), t2(nnode*3+3)
280  call tangentbase( etype, nnode, pos, ele, tangent )
281  tensor(1,1)= dot_product( tangent(:,1), tangent(:,1) )
282  tensor(1,2)= dot_product( tangent(:,1), tangent(:,2) )
283  tensor(2,1)= dot_product( tangent(:,2), tangent(:,1) )
284  tensor(2,2)= dot_product( tangent(:,2), tangent(:,2) )
285  det = tensor(1,1)*tensor(2,2)-tensor(1,2)*tensor(2,1)
286  if( det==0.d0 ) stop "Error in calculate DispIncreMatrix"
287  ! inverse(1,1) = tensor(2,2)/det
288  ! inverse(1,2) = -tensor(1,2)/det
289  ! inverse(2,1) = -tensor(2,1)/det
290  ! inverse(2,2) = tensor(1,1)/det
291 
292  call getshapefunc( etype, pos(:), shapefunc )
293  forall( j=1:3 )
294  t1( j ) = tangent(j,1)
295  t2( j ) = tangent(j,2)
296  end forall
297  forall( i=1:nnode, j=1:3 )
298  t1( i*3+j ) = -tangent(j,1)*shapefunc(i)
299  t2( i*3+j ) = -tangent(j,2)*shapefunc(i)
300  end forall
301  !matrix( 1:2,: ) = matmul( inverse(:,:), matrix )
302  matrix(1,:) = (tensor(2,2)*t1(:)-tensor(1,2)*t2(:))/det
303  matrix(2,:) = (tensor(1,1)*t2(:)-tensor(2,1)*t1(:))/det
304  tangent(:,1) = tangent(:,1)/dsqrt(dot_product(tangent(:,1),tangent(:,1)))
305  tangent(:,2) = tangent(:,2)/dsqrt(dot_product(tangent(:,2),tangent(:,2)))
306  end subroutine
307 
309  subroutine update_direction( nslave, contact, currpos )
310  integer, intent(in) :: nslave
311  type( tcontact ), intent(inout) :: contact
312  real(kind=kreal), intent(in) :: currpos(:)
313 
314  integer(kind=kint) :: slave, sid0, etype, iSS
315  real(kind=kreal) :: coord(3)
316  logical :: isin
317  real(kind=kreal) :: opos(2), odirec(3)
318  type(tcontactstate) :: cstate_tmp
319 
320  slave = contact%slave(nslave)
321  coord(:) = currpos(3*slave-2:3*slave)
323  sid0 = contact%states(nslave)%surface
324  opos = contact%states(nslave)%lpos(1:2)
325  odirec = contact%states(nslave)%direction
326 
327  cstate_tmp%state = contact%states(nslave)%state
328  cstate_tmp%surface = sid0
329  call project_point2surfelement( coord, contact%master(sid0), currpos, &
330  cstate_tmp, isin, contact%cparam%DISTCLR_NOCHECK, &
331  contact%states(nslave)%lpos, contact%cparam%CLR_SAME_ELEM )
332 
333  if( isin ) then
334  etype = contact%master(sid0)%etype
335  iss = isinsideelement( etype, cstate_tmp%lpos, contact%cparam%CLR_CAL_NORM )
336  if( iss>0 ) &
337  call cal_node_normal( cstate_tmp%surface, iss, contact%master, currpos, &
338  cstate_tmp%lpos, cstate_tmp%direction(:) )
339  endif
340 
341  contact%states(nslave)%direction = cstate_tmp%direction
342 
343  end subroutine
344 
346  subroutine cal_node_normal( csurf, isin, surf, currpos, lpos, normal )
348  integer, intent(in) :: csurf
349  integer, intent(in) :: isin
350  type(tsurfelement), intent(in) :: surf(:)
351  real(kind=kreal), intent(in) :: currpos(:)
352  real(kind=kreal), intent(in) :: lpos(:)
353  real(kind=kreal), intent(out) :: normal(3)
354  integer(kind=kint) :: cnode, i, j, cnt, nd1, gn, etype, iss, nn,cgn
355  real(kind=kreal) :: cnpos(2), elem(3, l_max_elem_node)
356  integer(kind=kint) :: cnode1, cnode2, gn1, gn2, nsurf, cgn1, cgn2, isin_n
357  real(kind=kreal) :: x=0, normal_n(3), lpos_n(2)
358 
359  if( 1 <= isin .and. isin <= 4 ) then ! corner
360  cnode = isin
361  gn = surf(csurf)%nodes(cnode)
362  etype = surf(csurf)%etype
363  call getvertexcoord( etype, cnode, cnpos )
364  nn = size( surf(csurf)%nodes )
365  do j=1,nn
366  iss = surf(csurf)%nodes(j)
367  elem(1:3,j)=currpos(3*iss-2:3*iss)
368  enddo
369  normal = surfacenormal( etype, nn, cnpos, elem )
370  cnt = 1
371  do i=1,surf(csurf)%n_neighbor
372  nd1 = surf(csurf)%neighbor(i)
373  nn = size( surf(nd1)%nodes )
374  etype = surf(nd1)%etype
375  cgn = 0
376  do j=1,nn
377  iss = surf(nd1)%nodes(j)
378  elem(1:3,j)=currpos(3*iss-2:3*iss)
379  if( iss==gn ) cgn=j
380  enddo
381  if( cgn>0 ) then
382  call getvertexcoord( etype, cgn, cnpos )
383  !normal = normal+SurfaceNormal( etype, nn, cnpos, elem )
384  normal_n = surfacenormal( etype, nn, cnpos, elem )
385  normal = normal+normal_n
386  cnt = cnt+1
387  endif
388  enddo
389  !normal = normal/cnt !!-???
390  elseif( 12 <= isin .and. isin <= 41 ) then ! edge
391  cnode1 = isin / 10
392  cnode2 = mod(isin, 10)
393  gn1 = surf(csurf)%nodes(cnode1)
394  gn2 = surf(csurf)%nodes(cnode2)
395  etype = surf(csurf)%etype
396  nn = size( surf(csurf)%nodes )
397  do j=1,nn
398  iss = surf(csurf)%nodes(j)
399  elem(1:3,j)=currpos(3*iss-2:3*iss)
400  enddo
401  normal = surfacenormal( etype, nn, lpos, elem )
402  select case (etype)
403  case (fe_tri3n, fe_tri6n, fe_tri6nc)
404  if ( isin==12 ) then; x=lpos(2)-lpos(1)
405  elseif( isin==23 ) then; x=1.d0-2.d0*lpos(2)
406  elseif( isin==31 ) then; x=2.d0*lpos(1)-1.d0
407  else; stop "Error: cal_node_normal: invalid isin"
408  endif
409  case (fe_quad4n, fe_quad8n)
410  if ( isin==12 ) then; x=lpos(1)
411  elseif( isin==23 ) then; x=lpos(2)
412  elseif( isin==34 ) then; x=-lpos(1)
413  elseif( isin==41 ) then; x=-lpos(2)
414  else; stop "Error: cal_node_normal: invalid isin"
415  endif
416  end select
417  ! find neighbor surf that includes cnode1 and cnode2
418  nsurf = 0
419  neib_loop: do i=1, surf(csurf)%n_neighbor
420  nd1 = surf(csurf)%neighbor(i)
421  nn = size( surf(nd1)%nodes )
422  etype = surf(nd1)%etype
423  cgn1 = 0
424  cgn2 = 0
425  do j=1,nn
426  iss = surf(nd1)%nodes(j)
427  elem(1:3,j)=currpos(3*iss-2:3*iss)
428  if( iss==gn1 ) cgn1=j
429  if( iss==gn2 ) cgn2=j
430  enddo
431  if( cgn1>0 .and. cgn2>0 ) then
432  nsurf = nd1
433  isin_n = 10*cgn2 + cgn1
434  x = -x
435  select case (etype)
436  case (fe_tri3n, fe_tri6n, fe_tri6nc)
437  if ( isin_n==12 ) then; lpos_n(1)=0.5d0*(1.d0-x); lpos_n(2)=0.5d0*(1.d0+x)
438  elseif( isin_n==23 ) then; lpos_n(1)=0.d0; lpos_n(2)=0.5d0*(1.d0-x)
439  elseif( isin_n==31 ) then; lpos_n(1)=0.5d0*(1.d0+x); lpos_n(2)=0.d0
440  else; stop "Error: cal_node_normal: invalid isin_n"
441  endif
442  case (fe_quad4n, fe_quad8n)
443  if ( isin_n==12 ) then; lpos_n(1)= x; lpos_n(2)=-1.d0
444  elseif( isin_n==23 ) then; lpos_n(1)= 1.d0; lpos_n(2)= x
445  elseif( isin_n==34 ) then; lpos_n(1)=-x; lpos_n(2)= 1.d0
446  elseif( isin_n==41 ) then; lpos_n(1)=-1.d0; lpos_n(2)=-x
447  else; stop "Error: cal_node_normal: invalid isin_n"
448  endif
449  end select
450  !normal = normal + SurfaceNormal( etype, nn, lpos_n, elem )
451  normal_n = surfacenormal( etype, nn, lpos_n, elem )
452  normal = normal+normal_n
453  exit neib_loop
454  endif
455  enddo neib_loop
456  !if( nsurf==0 ) write(0,*) "Warning: cal_node_normal: neighbor surf not found"
457  !normal = normal/2
458  endif
459  normal = normal/ dsqrt( dot_product( normal, normal ) )
460  end subroutine cal_node_normal
461 
462 end module m_fstr_contact_geom
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
subroutine getshapefunc(fetype, localcoord, func)
Calculate the shape function in natural coordinate system.
Definition: element.f90:647
integer(kind=kind(2)) function getnumberofnodes(etype)
Obtain number of nodes of the element.
Definition: element.f90:131
integer function isinside3delement(fetype, localcoord, clearance)
if a point is inside a surface element -1: No; 0: Yes; >0: Node's (vertex) number
Definition: element.f90:1101
subroutine getelementcenter(fetype, localcoord)
Return natural coordinate of the center of element.
Definition: element.f90:1012
subroutine getshapederiv(fetype, localcoord, shapederiv)
Calculate derivatives of shape function in natural coordinate system.
Definition: element.f90:578
subroutine getvertexcoord(fetype, cnode, localcoord)
Get the natural coord of a vertex node.
Definition: element.f90:1143
subroutine tangentbase(fetype, nn, localcoord, elecoord, tangent)
Calculate base vector of tangent space of 3d surface.
Definition: element.f90:933
integer function isinsideelement(fetype, localcoord, clearance)
if a point is inside a surface element -1: No; 0: Yes; >0: Node's (vertex) number
Definition: element.f90:1036
real(kind=kreal) function, dimension(3) surfacenormal(fetype, nn, localcoord, elecoord)
Calculate normal of 3d-surface.
Definition: element.f90:870
subroutine curvature(fetype, nn, localcoord, elecoord, l2ndderiv, normal, curv)
Calculate curvature tensor at a point along 3d surface.
Definition: element.f90:967
Definition: hecmw.f90:6
This module provides geometric calculations for contact.
subroutine project_point2solidelement(xyz, etype, nn, elemt, reflen, cstate, isin, distclr, ctpos, localclr)
This subroutine find the projection of a slave point onto master surface.
subroutine update_direction(nslave, contact, currpos)
This subroutine tracks down next contact position after a finite slide.
subroutine, public cal_node_normal(csurf, isin, surf, currpos, lpos, normal)
Calculate averaged nodal normal.
subroutine dispincrematrix(pos, etype, nnode, ele, tangent, tensor, matrix)
This subroutine calculate the relation between global disp and displacement along natural coordinate ...
subroutine project_point2element(xyz, etype, nn, elemt, reflen, cstate, isin, distclr, ctpos, localclr)
This subroutine find the projection of a slave point onto master surface.
subroutine project_point2surfelement(xyz, surf, currpos, cstate, isin, distclr, ctpos, localclr)
Wrapper for project_Point2Element that takes tSurfElement structure This subroutine handles element c...
subroutine getmetrictensor(pos, etype, ele, tensor)
This subroutine calculate the metric tensor of a elemental surface.
This module provides aux functions.
Definition: utilities.f90:6
subroutine calinverse(NN, A)
calculate inverse of matrix a
Definition: utilities.f90:295
This module manages the data structure for contact calculation.
integer, parameter c_if_slave
contact interference type
real(kind=kreal), save cgn
convergent condition of penetration
integer, parameter contactfree
contact state definition
integer, parameter contactstick
Structure to includes all info needed by contact calculation.
This structure records contact status.