FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_contact_assembly.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 !-------------------------------------------------------------------------------
8  use hecmw
9  use m_fstr
10  use mcontactdef
16  implicit none
17 
19 
20 contains
21 
23  subroutine calc_contact_pair_refstiff(contact, diag, ndof, hecMESH)
24  type(tcontact), intent(inout) :: contact
25  real(kind=kreal), intent(in) :: diag(:)
26  integer(kind=kint), intent(in) :: ndof
27  type(hecmwst_local_mesh), intent(in) :: hecmesh
28 
29  integer(kind=kint) :: i, j, k, slave_node, master_node, nnode, ctsurf
30  integer(kind=kint) :: idx_start, idx_end, n_slave
31  integer(kind=kint) :: cgrp, ic, iss, outtype, fnodes(100)
32  real(kind=kreal) :: maxv
33  real(kind=kreal) :: a_rep, slave_reflen_sum
34  real(kind=kreal) :: elem(3, l_max_surface_node), r0(2)
35 
36  maxv = 0.0d0
37 
38  ! Loop over slave nodes
39  do j = 1, size(contact%slave)
40  slave_node = contact%slave(j)
41  ! The mortar refStiff must be partition-invariant: skip GHOST(external) rows, whose
42  ! diagonal is not fully assembled here. Every slave node is internal on exactly one
43  ! rank, so the allreduce-MAX below still sees every fully-assembled diagonal.
44  if( contact%method == contacts2s .and. slave_node > hecmesh%nn_internal ) cycle
45  idx_start = ndof * (slave_node - 1) + 1
46  idx_end = ndof * slave_node
47  maxv = max(maxv, maxval(diag(idx_start:idx_end)))
48  enddo
49 
50  ! Loop over master surfaces and nodes
51  if( contact%method == contacts2s ) then
52  ! Enumerate the master faces from the surface group instead of contact%master: with
53  ! !PARTITION, CONTACT_OWNER=SLAVE a rank that owns no slave node takes no master surface
54  ! at all (fstr_contact_init), so the diagonals of the master nodes it owns would never
55  ! enter the max and refStiff would depend on the partition. The surface group items are
56  ! present wherever the element is, so taking internal rows only on every rank lets the
57  ! allreduce-MAX reproduce the serial value.
58  cgrp = contact%surf_id2
59  if( cgrp > 0 ) then
60  do i = hecmesh%surf_group%grp_index(cgrp-1)+1, hecmesh%surf_group%grp_index(cgrp)
61  ic = hecmesh%surf_group%grp_item(2*i-1)
62  call getsubface( hecmesh%elem_type(ic), hecmesh%surf_group%grp_item(2*i), outtype, fnodes )
63  nnode = getnumberofnodes( outtype )
64  iss = hecmesh%elem_node_index(ic-1)
65  do j = 1, nnode
66  master_node = hecmesh%elem_node_item( iss + fnodes(j) )
67  if( master_node > hecmesh%nn_internal ) cycle
68  idx_start = ndof * (master_node - 1) + 1
69  idx_end = ndof * master_node
70  maxv = max(maxv, maxval(diag(idx_start:idx_end)))
71  enddo
72  enddo
73  endif
74  else
75  do ctsurf = 1, size(contact%master)
76  nnode = size(contact%master(ctsurf)%nodes)
77  do j = 1, nnode
78  master_node = contact%master(ctsurf)%nodes(j)
79  idx_start = ndof * (master_node - 1) + 1
80  idx_end = ndof * master_node
81  maxv = max(maxv, maxval(diag(idx_start:idx_end)))
82  enddo
83  enddo
84  endif
85 
86  ! Parallel reduction
87  call hecmw_allreduce_r1(hecmesh, maxv, hecmw_max)
88 
89  ! Set reference stiffness for this contact pair
90  contact%refStiff = maxv
91 
92  ! Mortar dimensional correction: the mortar penalty multiplies refStiff by the contact
93  ! area, so refStiff is divided by a representative tributary area A_rep = (slave reflen)^2
94  ! to make mu = nPenalty*refStiff a pressure density. The same nPenalty then gives the same
95  ! effective stiffness as the NODE-SURF per-node form. reflen is taken from the slave element
96  ! (the constraint is integrated on the slave surface). NODE-SURF pairs are left untouched.
97  if( contact%method == contacts2s ) then
98  ! Local slave reference-length sum and slave-face count (0 if this rank owns none).
99  slave_reflen_sum = 0.0d0
100  n_slave = 0
101  if( associated(contact%slave_surf) ) n_slave = size(contact%slave_surf)
102  do j = 1, n_slave
103  nnode = size(contact%slave_surf(j)%nodes)
104  do k = 1, nnode
105  ctsurf = contact%slave_surf(j)%nodes(k)
106  elem(1:3,k) = hecmesh%node(3*ctsurf-2:3*ctsurf)
107  enddo
108  call getelementcenter( contact%slave_surf(j)%etype, r0 )
109  slave_reflen_sum = slave_reflen_sum + &
110  getreferencelength( contact%slave_surf(j)%etype, nnode, r0, elem )
111  enddo
112  ! Reduced outside the slave_surf>0 gate (ranks owning no slave face must still join the
113  ! collective) but inside the method gate. Slave faces are owned by exactly one rank, so the
114  ! SUM reproduces the serial value on every rank.
115  call hecmw_allreduce_r1(hecmesh, slave_reflen_sum, hecmw_sum)
116  call hecmw_allreduce_i1(hecmesh, n_slave, hecmw_sum)
117  a_rep = 0.0d0
118  if( n_slave > 0 ) then
119  a_rep = ( slave_reflen_sum / dble(n_slave) ) ** 2
120  if( a_rep > 0.0d0 ) contact%refStiff = contact%refStiff / a_rep
121  endif
122  endif
123 
124  ! Report penalty settings
125  if (hecmw_comm_get_rank() == 0) then
126  write(*,'(A,A,A,1pE12.3,A,1pE12.3,A,1pE12.3)') " Contact [", &
127  trim(contact%pair_name), "] set penalty: normal & tied ", &
128  contact%nPenalty * contact%refStiff, ", tangential ", &
129  contact%tPenalty * contact%refStiff, ", refStiff ", contact%refStiff
130  endif
131 
132  end subroutine calc_contact_pair_refstiff
133 
135  subroutine assemble_contact_force_residual(nnode,ndLocal,id_lagrange,ctNForce,ctTForce,conMAT)
136  integer(kind=kint), intent(in) :: nnode
137  integer(kind=kint), intent(in) :: ndLocal(nnode + 1)
138  integer(kind=kint), intent(in) :: id_lagrange
139  real(kind=kreal), intent(in) :: ctnforce((nnode+1)*3+1)
140  real(kind=kreal), intent(in) :: cttforce((nnode+1)*3+1)
141  type(hecmwst_matrix), intent(inout) :: conmat
142 
143  integer(kind=kint) :: i, inod, idx
144 
145  do i = 1, nnode + 1
146  inod = ndlocal(i)
147  idx = (inod-1)*3+1
148  conmat%B(idx:idx+2) = conmat%B(idx:idx+2) + ctnforce((i-1)*3+1:(i-1)*3+3) + cttforce((i-1)*3+1:(i-1)*3+3)
149  enddo
150 
151  ! Accumulate: several contributions can target the same Lagrange row (the caller
152  ! zero-clears conMAT%B before the contact assembly).
153  if( id_lagrange > 0 ) then
154  conmat%B(conmat%NP*conmat%NDOF+id_lagrange) = &
155  conmat%B(conmat%NP*conmat%NDOF+id_lagrange) + ctnforce((nnode+1)*3+1) + cttforce((nnode+1)*3+1)
156  endif
157 
158  end subroutine assemble_contact_force_residual
159 
161  subroutine assemble_contact_force_output(nnode,ndLocal,ctNForce,ctTForce,cont_nforce,cont_fric)
162  integer(kind=kint), intent(in) :: nnode
163  integer(kind=kint), intent(in) :: ndlocal(nnode + 1)
164  real(kind=kreal), intent(in) :: ctnforce((nnode+1)*3+1)
165  real(kind=kreal), intent(in) :: cttforce((nnode+1)*3+1)
166  real(kind=kreal), pointer, intent(inout) :: cont_nforce(:)
167  real(kind=kreal), pointer, optional, intent(inout) :: cont_fric(:)
168 
169  integer(kind=kint) :: i, inod, idx
170 
171  do i = 1, nnode + 1
172  inod = ndlocal(i)
173  idx = (inod-1)*3+1
174  cont_nforce(idx:idx+2) = cont_nforce(idx:idx+2) + ctnforce((i-1)*3+1:(i-1)*3+3)
175  if( present(cont_fric) ) cont_fric(idx:idx+2) = cont_fric(idx:idx+2) + cttforce((i-1)*3+1:(i-1)*3+3)
176  enddo
177 
178  end subroutine assemble_contact_force_output
179 
182  subroutine update_contact_multiplier( ctAlgo, contact, coord, disp, ddisp, fcoeff, &
183  hecMESH, hecLagMAT, gnt, ctchanged )
184  integer(kind=kint), intent(in) :: ctAlgo
185  type( tcontact ), intent(inout) :: contact
186  real(kind=kreal), intent(in) :: coord(:)
187  real(kind=kreal), intent(in) :: disp(:)
188  real(kind=kreal), intent(in) :: ddisp(:)
189  real(kind=kreal), intent(in) :: fcoeff
190  type(hecmwst_local_mesh), intent(in) :: hecmesh
191  type(hecmwst_matrix_lagrange), intent(in) :: hecLagMAT
192  real(kind=kreal), intent(out) :: gnt(2)
193  logical, intent(inout) :: ctchanged
194 
195  integer(kind=kint) :: slave, etype, master
196  integer(kind=kint) :: nn, i, cnt
197  real(kind=kreal) :: lgnt(2)
198  integer(kind=kint) :: ndLocal(l_max_elem_node+1)
199  real(kind=kreal) :: ctnforce(l_max_elem_node*3+3)
200  real(kind=kreal) :: cttforce(l_max_elem_node*3+3)
201  real(kind=kreal) :: max_jump_ratio, jump_ratio_local
202  real(kind=kreal) :: mut_old, mut_new, threthold
203 
204  cnt = 0
205  lgnt(:) = 0.d0
206  max_jump_ratio = 0.0d0
207  ! ===== NODE-SURF multiplier update (per slave node) =====
208  do i = 1, size(contact%slave)
209  if(.not. is_contact_active(contact%states(i)%state)) cycle ! only STICK/SLIP
210 
211  slave = contact%slave(i)
212  master = contact%states(i)%surface
213  nn = size(contact%master(master)%nodes)
214  etype = contact%master(master)%etype
215 
216  ndlocal(1) = slave
217  ndlocal(2:nn+1) = contact%master(master)%nodes(1:nn)
218 
219  ! Update multiplier and calculate forces
220  call updatecontactmultiplier_alag(contact%states(i), ndlocal(1:nn+1), coord, disp, ddisp, &
221  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, &
222  fcoeff, contact%master(master), lgnt, ctchanged, ctnforce, cttforce, jump_ratio_local, contact%smoothing)
223 
224  ! Track maximum jump ratio
225  max_jump_ratio = max(max_jump_ratio, jump_ratio_local)
226 
227  cnt = cnt + 1
228  enddo
229 
230  if(cnt > 0) lgnt(:) = lgnt(:) / cnt
231  gnt = gnt + lgnt
232 
233  call hecmw_allreduce_r1(hecmesh, max_jump_ratio, hecmw_max)
234 
235  ! Adjust tPenalty
236  threthold = 100.d0
237  if (max_jump_ratio > threthold) then
238  mut_old = contact%tPenalty * contact%refStiff
239  contact%tPenalty = contact%tPenalty * max(1.d0/dsqrt(threthold), 1.0d0/dsqrt(max_jump_ratio))
240  mut_new = contact%tPenalty * contact%refStiff
241  if (hecmw_comm_get_rank() == 0) then
242  write(*,'(A,A,A,1pE12.3,A,1pE12.3,A)') " Contact [", trim(contact%pair_name), &
243  "] tangential penalty adjusted: ", mut_old, " -> ", mut_new, " (friction jump)"
244  endif
245  endif
246 
247  end subroutine update_contact_multiplier
248 
255  subroutine update_contact_multiplier_surfsurf( contact, coord, disp, ddisp, fcoeff )
256  type( tcontact ), intent(inout) :: contact
257  real(kind=kreal), intent(in) :: coord(:)
258  real(kind=kreal), intent(in) :: disp(:)
259  real(kind=kreal), intent(in) :: ddisp(:)
260  real(kind=kreal), intent(in) :: fcoeff
261 
262  integer(kind=kint) :: i, g, r, a, nnode_s, unique_count
263  integer(kind=kint) :: maplist(max_n_intp), master_idxs(MAX_N_INTP)
264  integer(kind=kint), allocatable :: sorted_idx(:)
265  ! per-node-within-group quantities; the per-node lambda_n drives the normal path
266  real(kind=kreal), allocatable :: snode(:,:), nsnode(:,:,:), gapwnode(:,:), lambda_node(:,:)
267  real(kind=kreal) :: mu, lambda_new
268  ! --- friction: per-node slip/normal, per-node basis, return mapping ---
269  real(kind=kreal), allocatable :: sigma_node(:,:,:), nacc_node(:,:,:)
270  real(kind=kreal), allocatable :: lam_t_cur(:,:,:)
271  integer(kind=kint), allocatable :: fric_state_cur(:,:)
272  real(kind=kreal) :: nhat(3), t1(3), t2(3), nrm, dxi(2)
273  real(kind=kreal) :: rho_t, alpha, that(2), lam_t_new(2)
274  integer(kind=kint) :: fstate
275 
276  ! ===== mortar multiplier update (per slave segment) =====
277  mu = contact%nPenalty * contact%refStiff
278  rho_t = contact%tPenalty * contact%refStiff ! tangential penalty, used only if fcoeff/=0
279  do i = 1, size(contact%slave_surf)
280  if( contact%slave_surf(i)%state == contactfree ) cycle
281 
282  call get_unique_map(contact%slave_surf(i), maplist, master_idxs, unique_count)
283  nnode_s = size(contact%slave_surf(i)%nodes)
284  allocate(snode(unique_count,nnode_s), nsnode(unique_count,nnode_s,24), gapwnode(unique_count,nnode_s))
285  call getintgap(contact%slave_surf(i), contact%master, coord, disp, ddisp, &
286  unique_count, maplist, master_idxs, &
287  snode, nsnode, gapwnode)
288 
289  allocate(sorted_idx(unique_count), lambda_node(nnode_s,unique_count))
290  if( fcoeff /= 0.d0 ) then
291  ! Resolve the tangent warm-start (working -> begin -> 0/STICK) before the working
292  ! buffer is rebuilt below. lambda_n resolution is identical to the fcoeff=0 path.
293  allocate(lam_t_cur(2,nnode_s,unique_count), fric_state_cur(nnode_s,unique_count))
294  call resolve_lambda_cur(contact%slave_surf(i), master_idxs, unique_count, nnode_s, sorted_idx, &
295  lambda_node, lam_t_cur, fric_state_cur)
296  else
297  call resolve_lambda_cur(contact%slave_surf(i), master_idxs, unique_count, nnode_s, sorted_idx, &
298  lambda_node)
299  endif
300 
301  ! Per-node augmented update: lambda_node(a,g) += mu*gapwnode(g,a), clamped at 0.
302  do g = 1, unique_count
303  do a = 1, nnode_s
304  lambda_new = lambda_node(a,g) + (mu * gapwnode(g,a))
305  if( lambda_new < 0.d0 ) lambda_new = 0.d0
306  lambda_node(a,g) = lambda_new
307  enddo
308  enddo
309 
310  ! Rebuild the working buffer from the active master set (ascending); BEGIN left it empty.
311  contact%slave_surf(i)%lam_work_n = unique_count
312  do r = 1, unique_count
313  contact%slave_surf(i)%lam_work_id(r) = master_idxs(sorted_idx(r))
314  contact%slave_surf(i)%lam_work_val(1:nnode_s,r) = lambda_node(1:nnode_s,sorted_idx(r))
315  enddo
316 
317  ! --- friction tangent update: per slave node, project the mortar slip onto the
318  ! per-node tangent frame, return-map with cone radius fcoeff*lambda_node(a,g),
319  ! and write lambda_t / fric_state into the working buffer. ---
320  if( fcoeff /= 0.d0 ) then
321  allocate(sigma_node(unique_count,nnode_s,3), nacc_node(unique_count,nnode_s,3))
322  call gettangentslip(contact%slave_surf(i), contact%master, coord, disp, ddisp, &
323  unique_count, maplist, master_idxs, sigma_node, nacc_node)
324  do g = 1, unique_count
325  do a = 1, nnode_s
326  nrm = sqrt( nacc_node(g,a,1)**2 + nacc_node(g,a,2)**2 + nacc_node(g,a,3)**2 )
327  ! Project the per-node slip onto the per-node orthonormal frame, then Coulomb
328  ! return-map. rho_t*Dxi matches the per-node mu*gapwnode area weighting (both
329  ! node-tributary integrated), so the averaged back-distribution cancels the area.
330  if( nrm < 1.d-30 ) then
331  dxi(1:2) = 0.d0
332  nhat(1:3) = 0.d0
333  else
334  nhat(1:3) = nacc_node(g,a,1:3) / nrm
335  call build_group_tangent_basis(nhat, t1, t2)
336  dxi(1) = dot_product(t1(1:3), sigma_node(g,a,1:3))
337  dxi(2) = dot_product(t2(1:3), sigma_node(g,a,1:3))
338  endif
339  fstate = fric_state_cur(a,g)
340  call group_return_mapping(lam_t_cur(1:2,a,g), rho_t, dxi, fcoeff, lambda_node(a,g), &
341  contact%eps_fric_band, lam_t_new, fstate, alpha, that, &
342  update_state=.true.)
343  lam_t_cur(1:2,a,g) = lam_t_new(1:2)
344  fric_state_cur(a,g) = fstate
345  enddo
346  enddo
347  ! Write the tangent working buffer parallel to the rebuilt lambda_n (ascending master order).
348  do r = 1, unique_count
349  contact%slave_surf(i)%lam_work_t(1:2,1:nnode_s,r) = lam_t_cur(1:2,1:nnode_s,sorted_idx(r))
350  contact%slave_surf(i)%lam_work_fstate(1:nnode_s,r) = fric_state_cur(1:nnode_s,sorted_idx(r))
351  enddo
352  deallocate(sigma_node, nacc_node, lam_t_cur, fric_state_cur)
353  endif
354 
355  deallocate(sorted_idx)
356  deallocate(snode, nsnode, gapwnode, lambda_node)
357  enddo
358 
360 
363  subroutine update_tied_multiplier( contact, disp, ddisp, ctchanged )
364  type( tcontact ), intent(inout) :: contact
365  real(kind=kreal), intent(in) :: disp(:)
366  real(kind=kreal), intent(in) :: ddisp(:)
367  logical, intent(inout) :: ctchanged
368 
369  integer(kind=kint) :: slave, etype, master
370  integer(kind=kint) :: nn, i, j, iSS
371  real(kind=kreal) :: dg(3), dgmax
372  real(kind=kreal) :: shapefunc(l_max_surface_node)
373  real(kind=kreal) :: edisp(3*l_max_elem_node+3)
374  real(kind=kreal) :: mu
375 
376  ! Calculate penalty from contact structure
377  mu = contact%nPenalty * contact%refStiff
378 
379  do i= 1, size(contact%slave)
380  if( .not. is_contact_active(contact%states(i)%state) ) cycle ! only STICK/SLIP
381  slave = contact%slave(i)
382  edisp(1:3) = disp(3*slave-2:3*slave)+ddisp(3*slave-2:3*slave)
383  master = contact%states(i)%surface
384 
385  nn = size( contact%master(master)%nodes )
386  etype = contact%master(master)%etype
387  do j=1,nn
388  iss = contact%master(master)%nodes(j)
389  edisp(3*j+1:3*j+3) = disp(3*iss-2:3*iss)+ddisp(3*iss-2:3*iss)
390  enddo
391  call getshapefunc( etype, contact%states(i)%lpos(1:2), shapefunc )
392 
393  ! normal component
394  dg(1:3) = edisp(1:3)
395  do j=1,nn
396  dg(1:3) = dg(1:3)-shapefunc(j)*edisp(3*j+1:3*j+3)
397  enddo
398 
399  contact%states(i)%multiplier(1:3) = contact%states(i)%multiplier(1:3) + mu*dg(1:3)
400 
401  ! check if tied constraint converged
402  dgmax = 0.d0
403  do j=1,(nn+1)*3
404  dgmax = dgmax + dabs(edisp(j))
405  enddo
406  dgmax = dgmax/dble((nn+1)*3)
407  do j=1,3
408  if( dabs(dg(j))/dmax1(1.d0,dgmax) > 1.d-3 ) ctchanged = .true.
409  enddo
410 
411  enddo
412  end subroutine
413 
414  subroutine update_contact_tangentforce( contact )
415  type( tcontact ), intent(inout) :: contact
416 
417  integer(kind=kint) :: i
418 
419  do i= 1, size(contact%slave)
420  if( .not. is_contact_active(contact%states(i)%state) ) then
421  contact%states(i)%tangentForce(1:3) = 0.d0
422  contact%states(i)%tangentForce_trial(1:3) = 0.d0
423  contact%states(i)%tangentForce_final(1:3) = 0.d0
424  else
425  contact%states(i)%tangentForce(1:3) = contact%states(i)%tangentForce_final(1:3)
426  end if
427  contact%states(i)%tangentForce1(1:3) = contact%states(i)%tangentForce(1:3)
428  enddo
429  end subroutine update_contact_tangentforce
430 
433  subroutine calcu_contact_stiffness_nodesurf( ctAlgo, contact, coord, disp, ddisp, iter, lagrange_array, &
434  conMAT, hecLagMAT)
435  integer(kind=kint), intent(in) :: ctalgo
436  type(tcontact), intent(inout) :: contact
437  real(kind=kreal), intent(in) :: coord(:)
438  real(kind=kreal), intent(in) :: disp(:)
439  real(kind=kreal), intent(in) :: ddisp(:)
440  integer(kind=kint), intent(in) :: iter
441  real(kind=kreal), intent(in) :: lagrange_array(:)
442  type(hecmwst_matrix), intent(inout) :: conmat
443  type(hecmwst_matrix_lagrange), intent(inout) :: hecLagMAT
444 
445  integer(kind=kint) :: ctsurf, nnode, ndLocal(21), etype
446  integer(kind=kint) :: j, k, algtype, id_lagrange
447  real(kind=kreal) :: lagrange
448  real(kind=kreal) :: stiffness((l_max_surface_node+1)*3+1, (l_max_surface_node+1)*3+1)
449  real(kind=kreal) :: elecoord(3, l_max_surface_node)
450  real(kind=kreal) :: eledisp(l_max_surface_node*3+3)
451  real(kind=kreal) :: force(l_max_surface_node*3+3)
452  logical :: is_contact_active_flag, is_damping_active_flag
453 
454  algtype = contact%algtype
455 
456  do j = 1, size(contact%slave)
457 
458  ! stick or sliding contact is active
459  is_contact_active_flag = is_contact_active(contact%states(j)%state)
460  ! damping is active
461  is_damping_active_flag = contact%states(j)%state == contactnear .and. &
462  & is_damping_enabled(contact)
463 
464  if( .not. is_contact_active_flag .and. .not. is_damping_active_flag ) cycle
465 
466  ctsurf = contact%states(j)%surface
467  etype = contact%master(ctsurf)%etype
468  nnode = size(contact%master(ctsurf)%nodes)
469  ndlocal(1) = contact%slave(j)
470  ndlocal(2:nnode+1) = contact%master(ctsurf)%nodes(1:nnode)
471 
472  ! Prepare master node coordinates for ALagrange (deformed configuration)
473  do k = 1, nnode
474  elecoord(1:3, k) = coord(3*ndlocal(k+1)-2:3*ndlocal(k+1)) + disp(3*ndlocal(k+1)-2:3*ndlocal(k+1))
475  enddo
476 
477  if( is_contact_active_flag ) then
478 
479  if( algtype == contactsslid .or. algtype == contactfslid ) then
480 
481  if( ctalgo == kcaslagrange ) then
482  id_lagrange = heclagmat%lag_node_table(ndlocal(1)) - 1
483  id_lagrange = id_lagrange + 1
484  lagrange = lagrange_array(id_lagrange)
485  call getcontactstiffness_slag(contact%states(j), contact%master(ctsurf), iter, &
486  contact%tPenalty, contact%fcoeff, lagrange, stiffness, smoothing_type=contact%smoothing)
487 
488  ! Assemble contact stiffness matrix of contact pair into global stiffness matrix
489  call hecmw_mat_ass_contactlag(nnode, ndlocal, id_lagrange, contact%fcoeff, stiffness, conmat, heclagmat)
490 
491  else if( ctalgo == kcaalagrange ) then
492  ! Build element displacement increment for consistent tangent evaluation
493  eledisp(1:3) = ddisp(3*ndlocal(1)-2:3*ndlocal(1))
494  do k = 1, nnode
495  eledisp(k*3+1:k*3+3) = ddisp(3*ndlocal(k+1)-2:3*ndlocal(k+1))
496  enddo
497  call getcontactstiffness_alag(contact%states(j), contact%master(ctsurf), elecoord(:,1:nnode), &
498  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, &
499  contact%fcoeff, contact%symmetric, stiffness, force, &
500  smoothing_type=contact%smoothing, edisp=eledisp(1:nnode*3+3), iter=iter, &
501  slvpos=coord(3*ndlocal(1)-2:3*ndlocal(1)) + disp(3*ndlocal(1)-2:3*ndlocal(1)))
502 
503  ! Assemble contact stiffness matrix into global stiffness matrix
504  call hecmw_mat_ass_elem(conmat, nnode+1, ndlocal, stiffness)
505 
506  end if
507 
508  else if( algtype == contacttied ) then
509 
510  if( ctalgo == kcaslagrange ) then
511  id_lagrange = heclagmat%lag_node_table(ndlocal(1)) - 1
512  do k = 1, 3
513  id_lagrange = id_lagrange + 1
514  lagrange = lagrange_array(id_lagrange)
515 
516  call gettiedstiffness_slag(contact%states(j), contact%master(ctsurf), k, stiffness, &
517  contact%smoothing)
518  ! Assemble contact stiffness matrix of contact pair into global stiffness matrix
519  call hecmw_mat_ass_contactlag(nnode, ndlocal, id_lagrange, 0.d0, stiffness, conmat, heclagmat)
520  enddo
521 
522  else if( ctalgo == kcaalagrange ) then
523  call gettiedstiffness_alag(contact%states(j), contact%master(ctsurf), &
524  contact%nPenalty * contact%refStiff, stiffness, force)
525 
526  ! Assemble contact stiffness matrix into global stiffness matrix
527  call hecmw_mat_ass_elem(conmat, nnode+1, ndlocal, stiffness)
528 
529  end if
530 
531  endif
532 
533  else if( is_damping_active_flag ) then
534  call getdampingstiffness(contact%states(j), contact%master(ctsurf), &
535  contact%damp_alpha * contact%refStiff, contact%damp_gact, &
536  stiffness, smoothing_type=contact%smoothing)
537 
538  ! Assemble full damping stiffness for slave+master contact element
539  call hecmw_mat_ass_elem(conmat, nnode+1, ndlocal, stiffness)
540 
541  endif
542 
543  enddo
544 
545  end subroutine calcu_contact_stiffness_nodesurf
546 
547  subroutine calcu_contact_stiffness_surfsurf( ctAlgo, contact, coord, disp, ddisp, hecMAT )
548  integer(kind=kint), intent(in) :: ctAlgo
549  type(tcontact), intent(inout) :: contact
550  real(kind=kreal), intent(in) :: coord(:)
551  real(kind=kreal), intent(in) :: disp(:)
552  real(kind=kreal), intent(in) :: ddisp(:)
553  type(hecmwst_matrix), intent(inout) :: hecmat
554 
555  integer(kind=kint) :: i, g, a, nnode_m, nnode_s, unique_count, ctsurf
556  integer(kind=kint) :: ndlocal(l_max_surface_node+1)
557  integer(kind=kint) :: maplist(MAX_N_INTP), master_idxs(MAX_N_INTP)
558  real(kind=kreal), allocatable :: stiff_n(:,:,:,:), stiff_t(:,:,:,:)
559  logical, allocatable :: active_n(:,:), active_t(:,:)
560 
561  do i = 1, size(contact%slave_surf)
562  if( contact%slave_surf(i)%state == contactfree ) cycle
563  if( ctalgo /= kcaalagrange ) cycle
564 
565  call get_unique_map( contact%slave_surf(i), maplist, master_idxs, unique_count )
566  nnode_s = size(contact%slave_surf(i)%nodes)
567  allocate(stiff_n(24,24,nnode_s,unique_count), active_n(nnode_s,unique_count))
568 
569  ! Element level: one stiffness block per (slave-surf node a, master group g) constraint.
570  if( contact%fcoeff /= 0.d0 ) then
571  allocate(stiff_t(24,24,nnode_s,unique_count), active_t(nnode_s,unique_count))
572  call getcontactstiffness_alag_surfsurf( contact%slave_surf(i), contact%master, coord, disp, ddisp, &
573  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, contact%fcoeff, &
574  contact%symmetric, contact%eps_fric_band, unique_count, maplist, master_idxs, &
575  stiff_n, active_n, stiff_t, active_t )
576  else
577  call getcontactstiffness_alag_surfsurf( contact%slave_surf(i), contact%master, coord, disp, ddisp, &
578  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, contact%fcoeff, &
579  contact%symmetric, contact%eps_fric_band, unique_count, maplist, master_idxs, &
580  stiff_n, active_n )
581  endif
582 
583  ! ===== Normal stiffness =====
584  do g = 1, unique_count
585  ctsurf = master_idxs(g)
586  nnode_m = size(contact%master(ctsurf)%nodes)
587  ndlocal(1:nnode_s) = contact%slave_surf(i)%nodes(1:nnode_s)
588  ndlocal(nnode_s+1:nnode_s+nnode_m) = contact%master(ctsurf)%nodes(1:nnode_m)
589  do a = 1, nnode_s
590  if( .not. active_n(a,g) ) cycle
591  call hecmw_mat_ass_elem(hecmat, nnode_s+nnode_m, ndlocal, stiff_n(:,:,a,g))
592  enddo
593  enddo
594 
595  ! ===== Friction consistent tangent, assembled in a second pass =====
596  if( contact%fcoeff /= 0.d0 ) then
597  do g = 1, unique_count
598  ctsurf = master_idxs(g)
599  nnode_m = size(contact%master(ctsurf)%nodes)
600  ndlocal(1:nnode_s) = contact%slave_surf(i)%nodes(1:nnode_s)
601  ndlocal(nnode_s+1:nnode_s+nnode_m) = contact%master(ctsurf)%nodes(1:nnode_m)
602  do a = 1, nnode_s
603  if( .not. active_t(a,g) ) cycle
604  call hecmw_mat_ass_elem(hecmat, nnode_s+nnode_m, ndlocal, stiff_t(:,:,a,g))
605  enddo
606  enddo
607  deallocate(stiff_t, active_t)
608  endif
609 
610  deallocate(stiff_n, active_n)
611  enddo
612 
613  end subroutine calcu_contact_stiffness_surfsurf
614 
619  subroutine calcu_contact_ndforce_nodesurf( purpose, ctAlgo, contact, coord, disp, ddisp, lagrange_array, &
620  conMAT, CONT_NFORCE, CONT_FRIC, hecLagMAT )
621  integer(kind=kint), intent(in) :: purpose
622  integer(kind=kint), intent(in) :: ctAlgo
623  type( tcontact ), intent(inout) :: contact
624  real(kind=kreal), intent(in) :: coord(:)
625  real(kind=kreal), intent(in) :: disp(:)
626  real(kind=kreal), intent(in) :: ddisp(:)
627  real(kind=kreal), intent(in) :: lagrange_array(:)
628  type(hecmwst_matrix), intent(inout) :: conmat
629  real(kind=kreal), pointer :: cont_nforce(:)
630  real(kind=kreal), pointer :: cont_fric(:)
631  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
632 
633  integer(kind=kint) :: ctsurf, nnode, ndlocal(21)
634  integer(kind=kint) :: j, k, algtype, id_lagrange
635  real(kind=kreal) :: ndcoord(21*3)
636  real(kind=kreal) :: ndu(21*3), nddu(21*3)
637  real(kind=kreal) :: lagrange
638  real(kind=kreal) :: ctnforce(21*3+1)
639  real(kind=kreal) :: cttforce(21*3+1)
640  real(kind=kreal) :: mu_n, mu_t
641  logical :: if_flag
642  logical :: is_contact_active_flag, is_damping_active_flag
643  real(kind=kreal) :: ctime, etime
644  integer(kind=kint) :: if_type
645 
646  algtype = contact%algtype
647  if_flag = (contact%if_type /= 0)
648  if(if_flag)then
649  ctime = contact%ctime
650  etime = contact%if_etime
651  if_type = contact%if_type
652  end if
653 
654  do j = 1, size(contact%slave)
655 
656  ! stick or sliding contact is active
657  is_contact_active_flag = is_contact_active(contact%states(j)%state)
658  ! damping is active (residual only)
659  is_damping_active_flag = (purpose == kctforresidual) .and. &
660  contact%states(j)%state == contactnear .and. is_damping_enabled(contact)
661 
662  if( .not. is_contact_active_flag .and. .not. is_damping_active_flag ) cycle
663 
664  ctsurf = contact%states(j)%surface
665  nnode = size(contact%master(ctsurf)%nodes)
666  ndlocal(1) = contact%slave(j)
667  ndlocal(2:nnode+1) = contact%master(ctsurf)%nodes(1:nnode)
668  do k = 1, nnode+1
669  nddu((k-1)*3+1:(k-1)*3+3) = ddisp((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3)
670  ndu((k-1)*3+1:(k-1)*3+3) = disp((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3) + nddu((k-1)*3+1:(k-1)*3+3)
671  ndcoord((k-1)*3+1:(k-1)*3+3) = coord((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3) + ndu((k-1)*3+1:(k-1)*3+3)
672  enddo
673 
674  if( is_contact_active_flag ) then
675 
676  if(if_flag) call set_shrink_factor(ctime, contact%states(j), etime, if_type)
677 
678  ! --- Determine penalty parameters: zero for output (multiplier-only)
679  if( ctalgo == kcaalagrange .and. purpose == kctforoutput ) then
680  mu_n = 0.0d0
681  mu_t = 0.0d0
682  else
683  mu_n = contact%nPenalty * contact%refStiff
684  mu_t = contact%tPenalty * contact%refStiff
685  endif
686 
687  if( algtype == contactsslid .or. algtype == contactfslid ) then
688  ! Obtain contact nodal force vector of contact pair
689  if(if_flag) call get_shrink_elemact_surf(contact%states(j),ndcoord, nnode)
690 
691  if( ctalgo == kcaslagrange ) then
692  id_lagrange = heclagmat%lag_node_table(ndlocal(1)) - 1
693  id_lagrange = id_lagrange + 1
694  lagrange = lagrange_array(id_lagrange)
695  call getcontactnodalforce_slag(contact%states(j),contact%master(ctsurf),ndcoord,nddu, &
696  contact%tPenalty,contact%fcoeff,lagrange,ctnforce,cttforce,.true.,contact%smoothing)
697 
698  else if( ctalgo == kcaalagrange ) then
699  id_lagrange = 0
700  lagrange = 0.d0
701  call getcontactnodalforce_alag(contact%states(j),contact%master(ctsurf),ndcoord,nddu, &
702  mu_n, mu_t, contact%fcoeff,contact%symmetric,lagrange,ctnforce,cttforce,.true.,contact%smoothing)
703 
704  end if
705 
706  ! Assemble contact force
707  if( purpose == kctforresidual ) then
708  call assemble_contact_force_residual(nnode,ndlocal,id_lagrange,ctnforce,cttforce,conmat)
709  else
710  call assemble_contact_force_output(nnode,ndlocal,ctnforce,cttforce,cont_nforce,cont_fric)
711  endif
712 
713  else if( algtype == contacttied ) then
714 
715  if( ctalgo == kcaslagrange ) then
716  id_lagrange = heclagmat%lag_node_table(ndlocal(1)) - 1
717  do k=1,3
718  id_lagrange = id_lagrange + 1
719  lagrange = lagrange_array(id_lagrange)
720  contact%states(j)%multiplier(k) = lagrange
721 
722  call gettiednodalforce_slag(contact%states(j),contact%master(ctsurf),k,ndu, &
723  & lagrange,ctnforce,cttforce,contact%smoothing)
724  if( purpose == kctforresidual ) then
725  call assemble_contact_force_residual(nnode,ndlocal,id_lagrange,ctnforce,cttforce,conmat)
726  else
727  call assemble_contact_force_output(nnode,ndlocal,ctnforce,cttforce,cont_nforce)
728  endif
729  end do
730 
731  else if( ctalgo == kcaalagrange ) then
732  id_lagrange = 0
733  call gettiednodalforce_alag(contact%states(j),contact%master(ctsurf),ndu, &
734  mu_n, ctnforce,cttforce)
735  if( purpose == kctforresidual ) then
736  call assemble_contact_force_residual(nnode,ndlocal,id_lagrange,ctnforce,cttforce,conmat)
737  else
738  call assemble_contact_force_output(nnode,ndlocal,ctnforce,cttforce,cont_nforce)
739  endif
740 
741  end if
742 
743  endif
744 
745  else if( is_damping_active_flag ) then
746 
747  call getdampingnodalforce(contact%states(j), contact%master(ctsurf), nddu, &
748  contact%damp_alpha * contact%refStiff, contact%damp_gact, &
749  ctnforce, cttforce, smoothing_type=contact%smoothing)
750 
751  ! Assemble damping force for slave+master contact element
752  call assemble_contact_force_residual(nnode,ndlocal,0,ctnforce,cttforce,conmat)
753 
754  endif
755 
756  enddo
757 
758  end subroutine calcu_contact_ndforce_nodesurf
759 
772  subroutine calcu_contact_ndforce_exp( contact, coord, disp, ddisp, CONT_NFORCE, CONT_FRIC )
773  type( tcontact ), intent(inout) :: contact
774  real(kind=kreal), intent(in) :: coord(:)
775  real(kind=kreal), intent(in) :: disp(:)
776  real(kind=kreal), intent(in) :: ddisp(:)
777  real(kind=kreal), pointer :: cont_nforce(:)
778  real(kind=kreal), pointer :: cont_fric(:)
779 
780  integer(kind=kint) :: ctsurf, nnode, ndLocal(21), j, k
781  real(kind=kreal) :: ndcoord(21*3), ndu(21*3), nddu(21*3)
782  real(kind=kreal) :: ctnforce(21*3+1), cttforce(21*3+1)
783  real(kind=kreal) :: tm(3,3*(l_max_surface_node+1)), tt(3,3*(l_max_surface_node+1))
784 
785  do j = 1, size(contact%slave)
786  if( .not. is_contact_active(contact%states(j)%state) ) cycle
787 
788  ctsurf = contact%states(j)%surface
789  nnode = size(contact%master(ctsurf)%nodes)
790  ndlocal(1) = contact%slave(j)
791  ndlocal(2:nnode+1) = contact%master(ctsurf)%nodes(1:nnode)
792  do k = 1, nnode+1
793  nddu((k-1)*3+1:(k-1)*3+3) = ddisp((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3)
794  ndu((k-1)*3+1:(k-1)*3+3) = disp((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3) + nddu((k-1)*3+1:(k-1)*3+3)
795  ndcoord((k-1)*3+1:(k-1)*3+3) = coord((ndlocal(k)-1)*3+1:(ndlocal(k)-1)*3+3) + ndu((k-1)*3+1:(k-1)*3+3)
796  enddo
797 
798  call getcontactnodalforce_slag( contact%states(j), contact%master(ctsurf), ndcoord, nddu, &
799  0.d0, 0.d0, contact%states(j)%multiplier(1), ctnforce, cttforce, .false., contact%smoothing )
800 
801  call computetm_tt( contact%states(j), contact%master(ctsurf), contact%fcoeff, &
802  tm, tt, contact%smoothing )
803  cttforce(:) = 0.d0
804  cttforce(1:3*(nnode+1)) = -matmul(transpose(tm(1:3,1:3*(nnode+1))), &
805  contact%states(j)%tangentForce_final)
806 
807  call assemble_contact_force_output( nnode, ndlocal, ctnforce, cttforce, cont_nforce, cont_fric )
808  enddo
809 
810  end subroutine calcu_contact_ndforce_exp
811 
812  subroutine calcu_contact_ndforce_surfsurf( purpose, ctAlgo, contact, coord, disp, ddisp, &
813  conMAT, CONT_NFORCE, CONT_FRIC )
814  integer(kind=kint), intent(in) :: purpose
815  integer(kind=kint), intent(in) :: ctAlgo
816  type( tcontact ), intent(inout) :: contact
817  real(kind=kreal), intent(in) :: coord(:)
818  real(kind=kreal), intent(in) :: disp(:)
819  real(kind=kreal), intent(in) :: ddisp(:)
820  type(hecmwst_matrix), intent(inout) :: conmat
821  real(kind=kreal), pointer :: cont_nforce(:)
822  real(kind=kreal), pointer :: cont_fric(:)
823 
824  integer(kind=kint) :: i, g, a, j, nd, nnode_m, nnode_s, unique_count, ctsurf
825  integer(kind=kint) :: ndlocal(l_max_surface_node+1)
826  integer(kind=kint) :: maplist(MAX_N_INTP), master_idxs(MAX_N_INTP)
827  real(kind=kreal), allocatable :: ctnforce(:,:,:), cttforce(:,:,:)
828  logical, allocatable :: active_n(:,:), active_t(:,:)
829 
830  do i = 1, size(contact%slave_surf)
831  if( contact%slave_surf(i)%state == contactfree ) cycle
832  if( ctalgo /= kcaalagrange ) cycle
833 
834  call get_unique_map( contact%slave_surf(i), maplist, master_idxs, unique_count )
835  nnode_s = size(contact%slave_surf(i)%nodes)
836  allocate(ctnforce(24,nnode_s,unique_count), active_n(nnode_s,unique_count))
837 
838  ! Element level: one force vector per (slave-surf node a, master group g) constraint,
839  ! already signed as the residual contribution.
840  if( contact%fcoeff /= 0.d0 ) then
841  allocate(cttforce(24,nnode_s,unique_count), active_t(nnode_s,unique_count))
842  call getcontactnodalforce_alag_surfsurf( purpose, contact%slave_surf(i), contact%master, coord, disp, ddisp, &
843  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, contact%fcoeff, &
844  contact%symmetric, contact%eps_fric_band, unique_count, maplist, master_idxs, &
845  ctnforce, active_n, cttforce, active_t )
846  else
847  call getcontactnodalforce_alag_surfsurf( purpose, contact%slave_surf(i), contact%master, coord, disp, ddisp, &
848  contact%nPenalty * contact%refStiff, contact%tPenalty * contact%refStiff, contact%fcoeff, &
849  contact%symmetric, contact%eps_fric_band, unique_count, maplist, master_idxs, &
850  ctnforce, active_n )
851  endif
852 
853  ! ===== Normal force =====
854  do g = 1, unique_count
855  ctsurf = master_idxs(g)
856  nnode_m = size(contact%master(ctsurf)%nodes)
857  ndlocal(1:nnode_s) = contact%slave_surf(i)%nodes(1:nnode_s)
858  ndlocal(nnode_s+1:nnode_s+nnode_m) = contact%master(ctsurf)%nodes(1:nnode_m)
859  do a = 1, nnode_s
860  if( .not. active_n(a,g) ) cycle
861  do j = 1, nnode_s + nnode_m
862  nd = ndlocal(j)
863  if( purpose == kctforresidual ) then
864  conmat%B(3*nd-2:3*nd) = conmat%B(3*nd-2:3*nd) + ctnforce(3*j-2:3*j,a,g)
865  else if ( purpose == kctforoutput ) then
866  cont_nforce(3*nd-2:3*nd) = cont_nforce(3*nd-2:3*nd) + ctnforce(3*j-2:3*j,a,g)
867  end if
868  enddo
869  enddo
870  enddo
871 
872  ! ===== Friction force, assembled in a second pass =====
873  if( contact%fcoeff /= 0.d0 ) then
874  do g = 1, unique_count
875  ctsurf = master_idxs(g)
876  nnode_m = size(contact%master(ctsurf)%nodes)
877  ndlocal(1:nnode_s) = contact%slave_surf(i)%nodes(1:nnode_s)
878  ndlocal(nnode_s+1:nnode_s+nnode_m) = contact%master(ctsurf)%nodes(1:nnode_m)
879  do a = 1, nnode_s
880  if( .not. active_t(a,g) ) cycle
881  do j = 1, nnode_s + nnode_m
882  nd = ndlocal(j)
883  if( purpose == kctforresidual ) then
884  conmat%B(3*nd-2:3*nd) = conmat%B(3*nd-2:3*nd) + cttforce(3*j-2:3*j,a,g)
885  else if( purpose == kctforoutput ) then
886  cont_fric(3*nd-2:3*nd) = cont_fric(3*nd-2:3*nd) + cttforce(3*j-2:3*j,a,g)
887  end if
888  enddo
889  enddo
890  enddo
891  deallocate(cttforce, active_t)
892  endif
893 
894  deallocate(ctnforce, active_n)
895  enddo
896 
897  end subroutine calcu_contact_ndforce_surfsurf
898 
899 end module m_fstr_contact_assembly
Definition: hecmw.f90:6
Contact processing at assembly level (all pairs in one tContact object)
subroutine calcu_contact_ndforce_nodesurf(purpose, ctAlgo, contact, coord, disp, ddisp, lagrange_array, conMAT, CONT_NFORCE, CONT_FRIC, hecLagMAT)
This subroutine calculates contact nodal force for each contact pair and assembles it into contact ma...
subroutine calcu_contact_stiffness_surfsurf(ctAlgo, contact, coord, disp, ddisp, hecMAT)
subroutine, public calc_contact_pair_refstiff(contact, diag, ndof, hecMESH)
Calculate reference stiffness for one contact pair.
subroutine assemble_contact_force_residual(nnode, ndLocal, id_lagrange, ctNForce, ctTForce, conMAT)
Assemble contact nodal force into residual vector (conMATB).
subroutine update_contact_multiplier(ctAlgo, contact, coord, disp, ddisp, fcoeff, hecMESH, hecLagMAT, gnt, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
subroutine calcu_contact_ndforce_surfsurf(purpose, ctAlgo, contact, coord, disp, ddisp, conMAT, CONT_NFORCE, CONT_FRIC)
subroutine calcu_contact_ndforce_exp(contact, coord, disp, ddisp, CONT_NFORCE, CONT_FRIC)
Compute contact nodal normal force for output from the stored contact multiplier, for the explicit dy...
subroutine calcu_contact_stiffness_nodesurf(ctAlgo, contact, coord, disp, ddisp, iter, lagrange_array, conMAT, hecLagMAT)
This subroutine calculates contact stiffness for each contact pair and assembles it into global stiff...
subroutine assemble_contact_force_output(nnode, ndLocal, ctNForce, ctTForce, cont_nforce, cont_fric)
Accumulate contact nodal force into output arrays (CONT_NFORCE/CONT_FRIC).
subroutine update_contact_tangentforce(contact)
subroutine update_tied_multiplier(contact, disp, ddisp, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
subroutine update_contact_multiplier_surfsurf(contact, coord, disp, ddisp, fcoeff)
This subroutine updates the lagrangian multiplier of a mortar (MORTAR=YES) contact pair....
Contact damping module for CONTACTNEAR state.
subroutine, public getdampingstiffness(cstate, surf, alpha, gact, stiff, smoothing_type)
Compute damping stiffness matrix K_damp = alpha * w(g) * Bn (x) Bn.
subroutine, public getdampingnodalforce(cstate, surf, ndDu, alpha, gact, ctNForce, ctTForce, smoothing_type)
Compute damping nodal force vector f_damp = alpha * w(g) * (Bn^T * ddu) * Bn.
pure logical function, public is_damping_enabled(contact)
Check if damping is enabled for a contact pair.
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 getcontactstiffness_alag_surfsurf(slave_surf, master, coord, disp, ddisp, mu, mut, fcoeff, symm, eps_fric_band, unique_count, maplist, master_idxs, stiff_n, active_n, stiff_t, active_t)
Mortar (SURF-SURF) ALag: contact stiffness of one slave segment.
subroutine, public getcontactstiffness_alag(cstate, tSurf, ele, mu, mut, fcoeff, symm, stiff, force, smoothing_type, edisp, iter, slvpos)
subroutine, public gettiedstiffness_alag(cstate, tSurf, mu, stiff, force)
subroutine, public getcontactnodalforce_alag(ctState, tSurf, ndCoord, ndDu, mu, mut, fcoeff, symm, lagrange, ctNForce, ctTForce, cflag, smoothing_type)
subroutine, public gettiednodalforce_alag(ctState, tSurf, ndu, mu, ctNForce, ctTForce)
subroutine, public group_return_mapping(lam_t_in, rho_t, Dxi, fcoeff, lam_n, eps_fric_band, lam_t_out, fric_state, alpha, that, update_state)
Group-level Coulomb return mapping for the tangent multiplier (metric = I).
subroutine, public get_unique_map(sSurf, maplist, master_idxs, unique_count)
subroutine, public build_group_tangent_basis(n_hat, t1, t2)
Build an orthonormal tangent basis (t1,t2) as the orthogonal complement of a group-representative sla...
subroutine, public gettangentslip(slave_surf, master, coord, disp, ddisp, unique_count, maplist, master_idxs, Sigma_node, nacc_node)
Aggregate, per master group g and slave-surf node a of one mortar slave segment, the mortar-weighted ...
subroutine, public getintgap(slave_surf, master, coord, disp, ddisp, unique_count, maplist, master_idxs, Snode, Nsnode, gapwnode)
Compute the per-node mortar constraint quantities of one slave segment.
subroutine, public getcontactnodalforce_alag_surfsurf(purpose, slave_surf, master, coord, disp, ddisp, mu, mut, fcoeff, symm, eps_fric_band, unique_count, maplist, master_idxs, ctNForce, active_n, ctTForce, active_t)
Mortar (SURF-SURF) ALag: contact nodal force of one slave segment.
subroutine, public resolve_lambda_cur(surf, master_idxs, unique_count, nnode_s, sorted_idx, lambda_node, lam_t_cur, fric_state_cur)
Mortar: resolve the current per-node lambda of each active group of one slave surf....
Common utilities for contact element calculations.
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...
Contact mechanics calculations at element level (single contact pair)
This module provides interference fit (shrink) functions for contact.
subroutine get_shrink_elemact_surf(cstate, coords, nnode)
subroutine, public set_shrink_factor(ctime, cstate, etime, if_type)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
real(kind=kreal) etime
Definition: m_fstr.F90:147
integer(kind=kint), parameter kcaslagrange
contact analysis algorithm
Definition: m_fstr.F90:62
integer(kind=kint), parameter kcaalagrange
Definition: m_fstr.F90:63
This module manages the data structure for contact calculation.
integer, parameter contactsslid
integer, parameter kctforresidual
purpose flag for contact force calculation
integer, parameter contacts2s
integer, parameter contactnear
near contact: projection info available, no LM constraint
real(kind=kreal), dimension(2), save gnt
1:current average penetration; 2:current relative tangent displacement
integer, parameter max_n_intp
upper bound of integration points per SURF-SURF slave segment
integer, parameter contacttied
contact type or algorithm definition
integer, parameter kctforoutput
compute contact force for output (CONT_NFORCE/CONT_FRIC)
pure logical function is_contact_active(state)
Whether the contact state has active LM constraint (STICK or SLIP)
integer, parameter contactfree
contact state definition
integer, parameter contactfslid
Structure to includes all info needed by contact calculation.