FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_contact_elem_alag.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  use msurfelement
14  implicit none
15 
16  public :: getcontactstiffness_alag
18  public :: gettiedstiffness_alag
19  public :: gettiednodalforce_alag
21 
22 contains
23 
24  subroutine getcontactstiffness_alag(cstate, tSurf, ele, mu, mut, fcoeff, symm, stiff, force, smoothing_type, edisp, iter)
25 
26  type(tcontactstate), intent(inout) :: cstate
27  type(tsurfelement), intent(in) :: tsurf
28  real(kind=kreal), intent(in) :: ele(:,:)
29  real(kind=kreal), intent(in) :: mu, mut
30  real(kind=kreal), intent(in) :: fcoeff
31  logical, intent(in) :: symm
32  real(kind=kreal), intent(out) :: stiff(:,:)
33  real(kind=kreal), intent(out) :: force(:)
34  integer(kind=kint), optional, intent(in) :: smoothing_type
35  real(kind=kreal), optional, intent(in) :: edisp(:)
36  integer(kind=kint), intent(in) :: iter
37 
38  integer :: i, j, nnode
39  real(kind=kreal) :: bn(size(tsurf%nodes)*3+3), ht(2,size(tsurf%nodes)*3+3), gt(2,size(tsurf%nodes)*3+3)
40  real(kind=kreal) :: metric(2,2)
41  real(kind=kreal) :: a(2,2)
42  real(kind=kreal) :: alpha_proj, that_dir(2)
43  real(kind=kreal) :: k_fric(size(tsurf%nodes)*3+3,size(tsurf%nodes)*3+3)
44  real(kind=kreal) :: tmp_vec(2)
45  real(kind=kreal) :: dummy_force(size(tsurf%nodes)*3+3)
46  real(kind=kreal) :: eval_disp(size(tsurf%nodes)*3+3)
47 
48  nnode = size(tsurf%nodes)
49 
50  ! Use common mapping routine to compute Bn, metric, Ht, Gt
51  call computecontactmaps_alag(cstate, tsurf, ele, bn, metric, ht, gt, smoothing_type)
52 
53  ! Normal stiffness: stiff = mu * Bn * Bn^T
54  do j = 1, nnode*3+3
55  do i = 1, nnode*3+3
56  stiff(i,j) = mu * bn(i) * bn(j)
57  enddo
58  enddo
59  force(1:nnode*3+3) = bn(:)
60 
61  ! frictional component
62  if( fcoeff /= 0.d0 ) then
63  ! Evaluate trial friction at current displacement for consistent tangent
64  if( present(edisp) ) then
65  eval_disp(1:nnode*3+3) = edisp(1:nnode*3+3)
66  else
67  eval_disp = 0.0d0
68  endif
69  call computefrictionforce_alag(cstate, fcoeff, cstate%multiplier(1), metric, &
70  ht, gt, eval_disp, nnode*3+3, dummy_force, &
71  mut, alpha=alpha_proj, that=that_dir)
72 
73  ! Friction tangent operator A in 2D metric space: K_fric = Ht^T * A * Ht
74  if( cstate%multiplier(1) <= 0.0d0 .or. alpha_proj <= 1.0d-20 ) then
75  ! No normal contact force: no friction contribution
76  a = 0.0d0
77  else if( alpha_proj >= 0.999d0 ) then
78  ! Stick: A = mu_t * M (exact)
79  a(1,1) = mut * metric(1,1)
80  a(1,2) = mut * metric(1,2)
81  a(2,1) = mut * metric(2,1)
82  a(2,2) = mut * metric(2,2)
83  else
84  ! Slip: switch tangent by NR iteration count for stability.
85  ! iter <= 2: A = alpha*mu_t*M (stable, no directional correction)
86  ! iter >= 3: A = alpha*mu_t*(M - t_hat x t_hat) (consistent tangent)
87  ! The first two NR steps use M to let t_hat stabilize; after that the consistent tangent is used to regain quadratic convergence.
88  if( iter <= 2 ) then
89  a(1,1) = alpha_proj * mut * metric(1,1)
90  a(1,2) = alpha_proj * mut * metric(1,2)
91  a(2,1) = alpha_proj * mut * metric(2,1)
92  a(2,2) = alpha_proj * mut * metric(2,2)
93  else
94  a(1,1) = alpha_proj * mut * (metric(1,1) - that_dir(1)*that_dir(1))
95  a(1,2) = alpha_proj * mut * (metric(1,2) - that_dir(1)*that_dir(2))
96  a(2,1) = alpha_proj * mut * (metric(2,1) - that_dir(2)*that_dir(1))
97  a(2,2) = alpha_proj * mut * (metric(2,2) - that_dir(2)*that_dir(2))
98  endif
99  endif
100 
101  ! Compute friction stiffness: K_fric = Ht^T * A * Ht (consistent tangent)
102  do j = 1, nnode*3+3
103  tmp_vec = matmul(a, ht(1:2,j))
104  do i = 1, nnode*3+3
105  k_fric(i,j) = dot_product(ht(1:2,i), tmp_vec)
106  enddo
107  enddo
108 
109  stiff(1:nnode*3+3,1:nnode*3+3) = stiff(1:nnode*3+3,1:nnode*3+3) + k_fric(1:nnode*3+3,1:nnode*3+3)
110  endif
111 
112  end subroutine getcontactstiffness_alag
113 
114  subroutine getcontactnodalforce_alag(ctState,tSurf,ndCoord,ndDu,mu,mut,fcoeff,lagrange,ctNForce,ctTForce,cflag,smoothing_type)
115 
116  use msurfelement
117  type(tcontactstate) :: ctstate
118  type(tsurfelement) :: tsurf
119  integer(kind=kint) :: nnode
120  integer(kind=kint) :: j
121  real(kind=kreal), intent(in) :: mu, mut
122  real(kind=kreal) :: fcoeff
123  real(kind=kreal) :: lagrange
124  real(kind=kreal) :: ndcoord(:), nddu(:)
125  real(kind=kreal) :: ctnforce(:)
126  real(kind=kreal) :: cttforce(:)
127  logical :: cflag
128  integer(kind=kint), optional, intent(in) :: smoothing_type
129 
130  real(kind=kreal) :: normal(3)
131  real(kind=kreal) :: bn(3*l_max_elem_node+3)
132  real(kind=kreal) :: ht(2,3*l_max_elem_node+3), gt(2,3*l_max_elem_node+3)
133  real(kind=kreal) :: elemcrd(3, l_max_elem_node)
134  real(kind=kreal) :: edisp(3*l_max_elem_node+3)
135  real(kind=kreal) :: dgn, nrlforce
136  real(kind=kreal) :: metric(2,2)
137  integer(kind=kint) :: edof
138 
139  nnode = size(tsurf%nodes)
140  edof = nnode*3+3
141 
142  ctnforce = 0.0d0
143  cttforce = 0.0d0
144 
145  normal(1:3) = ctstate%direction(1:3)
146 
147  ! Prepare elemcrd = ndCoord - ndDu (i.e., coord + disp) for computeContactMaps_ALag
148  do j = 1, nnode
149  elemcrd(1:3, j) = ndcoord(j*3+1:j*3+3) - nddu(j*3+1:j*3+3)
150  enddo
151 
152  ! Use common mapping routine to compute Bn, metric, Ht, Gt
153  call computecontactmaps_alag(ctstate, tsurf, elemcrd(:,1:nnode), &
154  bn, metric, ht, gt, smoothing_type)
155 
156  ! Normal gap: dgn = Bn^T * ndCoord (using normal distribution vector)
157  dgn = dot_product( bn(1:edof), ndcoord(1:edof) )
158 
159  ! Normal force: multiplier + penalty * gap
160  nrlforce = ctstate%multiplier(1) + mu*dgn
161 
162  ! Distribute normal force using Bn: ctNForce = -nrlforce * Bn
163  ctnforce(1:edof) = -nrlforce * bn(1:edof)
164 
165  ! Lagrange row (not used in ALagrange, set to 0)
166  ctnforce((nnode+1)*3+1) = 0.d0
167 
168  if( fcoeff == 0.d0 ) return
169 
170  ! --- Tangent component ---
171 
172  ! Prepare edisp from ndDu
173  edisp(1:3) = nddu(1:3) ! slave
174  do j = 1, nnode
175  edisp(j*3+1:j*3+3) = nddu(j*3+1:j*3+3) ! master nodes
176  enddo
177 
178  ! Compute friction force using common routine
179  call computefrictionforce_alag(ctstate, fcoeff, ctstate%multiplier(1), metric, &
180  ht, gt, edisp, edof, cttforce, &
181  mut)
182 
183  ! Lagrange row (not used in ALagrange, set to 0)
184  cttforce((nnode+1)*3+1) = 0.d0
185 
186  end subroutine getcontactnodalforce_alag
187 
188  subroutine updatecontactmultiplier_alag(ctState,ndLocal,coord,disp,ddisp,&
189  & mu,mut,fcoeff,tSurf,lgnt,ctchanged,ctNForce,ctTForce,jump_ratio,smoothing_type)
190 
191  type(tcontactstate), intent(inout) :: ctstate
192  integer(kind=kint), intent(in) :: ndlocal(:)
193  real(kind=kreal), intent(in) :: coord(:)
194  real(kind=kreal), intent(in) :: disp(:)
195  real(kind=kreal), intent(in) :: ddisp(:)
196  real(kind=kreal), intent(in) :: mu, mut
197  real(kind=kreal), intent(in) :: fcoeff
198  type(tsurfelement), intent(in) :: tsurf
199  real(kind=kreal), intent(inout) :: lgnt(2)
200  logical, intent(inout) :: ctchanged
201  real(kind=kreal), intent(out) :: ctnforce(:)
202  real(kind=kreal), intent(out) :: cttforce(:)
203  real(kind=kreal), intent(out) :: jump_ratio
204  integer(kind=kint), optional, intent(in) :: smoothing_type
205 
206  integer(kind=kint) :: nnode
207  integer(kind=kint) :: slave, j
208  real(kind=kreal) :: bn(3*l_max_elem_node+3)
209  real(kind=kreal) :: ht(2,3*l_max_elem_node+3), gt(2,3*l_max_elem_node+3)
210  real(kind=kreal) :: elemcrd(3,l_max_elem_node)
211  real(kind=kreal) :: curpos(3*l_max_elem_node+3)
212  real(kind=kreal) :: edisp(3*l_max_elem_node+3)
213  real(kind=kreal) :: dgn, nrlforce
214  real(kind=kreal) :: metric(2,2)
215  real(kind=kreal) :: dxy(2)
216  integer(kind=kint) :: edof
217 
218  nnode = size(ndlocal) - 1
219  slave = ndlocal(1)
220  edof = nnode*3+3
221 
222  ctnforce = 0.0d0
223  cttforce = 0.0d0
224 
225  ! Prepare elemcrd (coord+disp) and current positions (coord+disp+ddisp)
226  curpos(1:3) = coord(3*slave-2:3*slave) + disp(3*slave-2:3*slave) + ddisp(3*slave-2:3*slave)
227  edisp(1:3) = ddisp(3*slave-2:3*slave)
228  do j = 1, nnode
229  elemcrd(1:3,j) = coord(3*ndlocal(j+1)-2:3*ndlocal(j+1)) + disp(3*ndlocal(j+1)-2:3*ndlocal(j+1))
230  curpos(j*3+1:j*3+3) = elemcrd(1:3,j) + ddisp(3*ndlocal(j+1)-2:3*ndlocal(j+1))
231  edisp(j*3+1:j*3+3) = ddisp(3*ndlocal(j+1)-2:3*ndlocal(j+1))
232  enddo
233 
234  ! Use common mapping routine to compute Bn, metric, Ht, Gt
235  call computecontactmaps_alag(ctstate, tsurf, elemcrd(:,1:nnode), &
236  bn, metric, ht, gt, smoothing_type)
237 
238  ! Normal gap: dgn = Bn^T * curpos (using normal distribution vector)
239  dgn = dot_product( bn(1:edof), curpos(1:edof) )
240 
241  ! Update multiplier and working distance
242  ctstate%wkdist = -dgn
243  ctstate%multiplier(1) = ctstate%multiplier(1) - mu*ctstate%wkdist
244  ctstate%distance = ctstate%wkdist
245  lgnt(1) = lgnt(1) - ctstate%wkdist
246 
247  ! Normal force: use updated multiplier
248  nrlforce = ctstate%multiplier(1)
249 
250  ! Distribute normal force using Bn: ctNForce = -nrlforce * Bn
251  ctnforce(1:edof) = -nrlforce * bn(1:edof)
252 
253  if( fcoeff == 0.d0 ) return
254 
255  ! --- Tangent component ---
256 
257  ! Compute friction force with multiplier update and state check
258  call computefrictionforce_alag(ctstate, fcoeff, ctstate%multiplier(1), metric, &
259  ht, gt, edisp, edof, cttforce, &
260  mut, &
261  update_multiplier=.true., slave_id=slave, ctchanged=ctchanged, &
262  jump_ratio=jump_ratio)
263 
264  ! Tangent displacement for convergence check: use Gt to project curpos directly
265  dxy = matmul( gt(:,1:edof), curpos(1:edof) )
266  lgnt(2) = lgnt(2) + dsqrt( dxy(1)*dxy(1) + dxy(2)*dxy(2) )
267 
268  end subroutine updatecontactmultiplier_alag
269 
270  subroutine gettiedstiffness_alag(cstate, tSurf, mu, stiff, force)
271 
272  type(tcontactstate), intent(in) :: cstate
273  type(tsurfelement), intent(in) :: tsurf
274  real(kind=kreal), intent(in) :: mu
275  real(kind=kreal), intent(out) :: stiff(:,:)
276  real(kind=kreal), intent(out) :: force(:)
277 
278  integer :: i, j, nnode, edof
279  real(kind=kreal) :: tm(3, 3*(l_max_surface_node+1))
280  real(kind=kreal) :: tt(3, 3*(l_max_surface_node+1))
281 
282  nnode = size(tsurf%nodes)
283  edof = nnode*3+3
284 
285  stiff = 0.d0
286 
287  ! Use common mapping routine to compute Tm
288  call computetm_tt(cstate, tsurf, 0.0d0, tm, tt)
289 
290  ! Tied stiffness: stiff = mu * Tm^T * Tm
291  do j = 1, edof
292  do i = 1, edof
293  stiff(i,j) = mu * dot_product(tm(1:3,i), tm(1:3,j))
294  enddo
295  enddo
296  force(1:edof) = 0.d0 ! not used for tied (3-direction constraint)
297 
298  end subroutine gettiedstiffness_alag
299 
300  subroutine gettiednodalforce_alag(ctState,tSurf,ndu,mu,ctNForce,ctTForce)
301 
302  use msurfelement
303  type(tcontactstate) :: ctstate
304  type(tsurfelement) :: tsurf
305  integer(kind=kint) :: nnode
306  real(kind=kreal) :: ndu(:)
307  real(kind=kreal), intent(in) :: mu
308  real(kind=kreal) :: ctnforce(:)
309  real(kind=kreal) :: cttforce(:)
310 
311  integer(kind=kint) :: edof
312  real(kind=kreal) :: tm(3, 3*(l_max_surface_node+1))
313  real(kind=kreal) :: tt(3, 3*(l_max_surface_node+1))
314  real(kind=kreal) :: dg(3)
315  real(kind=kreal) :: nrlforce(3)
316 
317  nnode = size(tsurf%nodes)
318  edof = nnode*3+3
319 
320  ctnforce = 0.0d0
321  cttforce = 0.0d0
322 
323  ! Use common mapping routine to compute Tm
324  call computetm_tt(ctstate, tsurf, 0.0d0, tm, tt)
325 
326  ! Gap vector: dg = Tm * ndu (3-component relative displacement)
327  dg(1:3) = matmul(tm(1:3, 1:edof), ndu(1:edof))
328 
329  ! Force: multiplier + penalty * gap (3 components)
330  nrlforce(1:3) = ctstate%multiplier(1:3) + mu*dg(1:3)
331 
332  ! Distribute force: ctNForce = -Tm^T * nrlforce
333  ctnforce(1:edof) = -matmul(transpose(tm(1:3, 1:edof)), nrlforce(1:3))
334 
335  ! Lagrange row (not used in ALagrange, set to 0)
336  ctnforce((nnode+1)*3+1) = 0.d0
337  cttforce((nnode+1)*3+1) = 0.d0
338 
339  end subroutine gettiednodalforce_alag
340 
341 end module m_fstr_contact_elem_alag
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
Definition: hecmw.f90:6
Alag method implementations for contact element calculations.
subroutine, public updatecontactmultiplier_alag(ctState, ndLocal, coord, disp, ddisp, mu, mut, fcoeff, tSurf, lgnt, ctchanged, ctNForce, ctTForce, jump_ratio, smoothing_type)
subroutine, public gettiedstiffness_alag(cstate, tSurf, mu, stiff, force)
subroutine, public getcontactstiffness_alag(cstate, tSurf, ele, mu, mut, fcoeff, symm, stiff, force, smoothing_type, edisp, iter)
subroutine, public gettiednodalforce_alag(ctState, tSurf, ndu, mu, ctNForce, ctTForce)
subroutine, public getcontactnodalforce_alag(ctState, tSurf, ndCoord, ndDu, mu, mut, fcoeff, lagrange, ctNForce, ctTForce, cflag, smoothing_type)
Common utilities for contact element calculations.
subroutine, public computefrictionforce_alag(ctState, fcoeff, lambda_n, metric, Ht, Gt, edisp, edof, ctTForce, mut, update_multiplier, slave_id, ctchanged, norm_trial, alpha, that, jump_ratio)
Compute friction force for ALag method Given tangent maps Ht, Gt and displacement increment,...
subroutine, public computecontactmaps_alag(ctState, tSurf, ele, Bn, metric, Ht, Gt, smoothing_type)
Compute contact maps for ALag method (normal distribution and tangential displacement maps) This subr...
subroutine, public computetm_tt(ctState, tSurf, fcoeff, Tm, Tt, smoothing_type, Bn)
Compute Tm (relative displacement mapping) and optionally Tt (tangential mapping) This subroutine con...
This module provides geometric calculations for contact.
Contact surface smoothing using Nagata patch interpolation.
This module manages the data structure for contact calculation.
This module manages surface elements in 3D It provides basic definition of surface elements (triangla...
Definition: surf_ele.f90:8
integer(kind=kint), parameter l_max_elem_node
Definition: surf_ele.f90:17
integer(kind=kint), parameter l_max_surface_node
Definition: surf_ele.f90:16
This structure records contact status.
Structure to define surface group.
Definition: surf_ele.f90:23