FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
fstr_mat_con_contact.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 !-------------------------------------------------------------------------------
6 ! stiffness matrix structure for the contact analysis
7 ! employing standard Lagrange multiplier algorithm
8 
10 
11  use m_fstr
12  use elementinfo
16 
17  implicit none
18  private
20  public :: hecmwst_matrix_lagrange
22  public :: fstr_mat_con_contact
29 
30  integer(kind=kint), save :: NPL_org, NPU_org
31  type(nodeRelated), pointer, save :: list_nodeRelated_org(:) => null()
32 
33  type(nodeRelated), pointer :: list_nodeRelated(:) => null()
34 
35  logical :: permission = .false.
36 
37 contains
38 
39  integer(kind=kint) function fstr_get_num_lagrange_pernode(algtype)
40  integer(kind=kint) :: algtype
41  if( algtype == contactsslid .or. algtype == contactfslid ) then
43  else if( algtype == contacttied ) then
45  endif
46  end function
47 
50 
51  type(hecmwst_matrix) :: hecmat
52 
53  if( associated(list_noderelated_org) ) return
54  call hecmw_construct_noderelated_from_hecmat(hecmat, npl_org, npu_org, list_noderelated_org)
55 
57 
60  subroutine fstr_mat_con_contact(cstep,contact_algo,hecMAT,fstrSOLID,hecLagMAT,infoCTChange,conMAT,is_contact_active_flag)
61 
62  integer(kind=kint) :: cstep
63  integer(kind=kint) :: contact_algo
64  type(hecmwst_matrix) :: hecmat
65  type(fstr_solid) :: fstrsolid
66  type(hecmwst_matrix_lagrange) :: heclagmat
67  type(fstr_info_contactchange) :: infoctchange
68 
69  integer(kind=kint) :: num_lagrange
70  integer(kind=kint) :: countnon0lu_node, countnon0lu_lagrange
71  integer(kind=kint) :: numnon0_node, numnon0_lagrange
73  type (hecmwst_matrix) :: conmat
74  logical, intent(in) :: is_contact_active_flag
75 
76  integer(kind=kint) :: i, j, grpid
77  integer(kind=kint) :: count_n2s, count_s2s
78  integer(kind=kint) :: nlag
79 
80  count_n2s = 0
81  count_s2s = 0
82  do i = 1, fstrsolid%n_contacts
83  if( fstrsolid%contacts(i)%method == contactn2s ) count_n2s = count_n2s + 1
84  if( fstrsolid%contacts(i)%method == contacts2s ) count_s2s = count_s2s + 1
85  enddo
86  count_n2s = count_n2s + fstrsolid%n_embeds
87 
88  num_lagrange = 0
89  if( contact_algo == kcaslagrange ) then
90  do i = 1, fstrsolid%n_contacts
91  grpid = fstrsolid%contacts(i)%group
92  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
93  nlag = fstr_get_num_lagrange_pernode(fstrsolid%contacts(i)%algtype)
94  do j = 1, size(fstrsolid%contacts(i)%slave)
95  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
96  num_lagrange = num_lagrange + nlag
97  enddo
98  enddo
99 
100  do i = 1, fstrsolid%n_embeds
101  grpid = fstrsolid%embeds(i)%group
102  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
103  nlag = 3
104  do j = 1, size(fstrsolid%embeds(i)%slave)
105  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
106  num_lagrange = num_lagrange + nlag
107  enddo
108  enddo
109  endif
110 
111  ! Get original list of related nodes
112  call hecmw_init_noderelated_from_org(hecmat%NP,num_lagrange,is_contact_active_flag,list_noderelated_org,list_noderelated)
113 
114  ! Construct new list of related nodes and Lagrange multipliers
115  countnon0lu_node = npl_org + npu_org
116  countnon0lu_lagrange = 0
117  if( is_contact_active_flag )then
118  if( count_n2s > 0 ) &
119  call getnewlistofrelatednodesandlagrangemultipliers(cstep,contact_algo, &
120  & hecmat%NP,fstrsolid,countnon0lu_node,countnon0lu_lagrange,list_noderelated)
121  if( count_s2s > 0 ) &
122  call getnewlistofrelatednodesandlagrangemultipliers_ss(cstep,contact_algo, &
123  & hecmat%NP,fstrsolid,countnon0lu_node,countnon0lu_lagrange,list_noderelated)
124  endif
125 
126  ! Construct new matrix structure(hecMAT&hecLagMAT)
127  numnon0_node = countnon0lu_node/2
128  numnon0_lagrange = countnon0lu_lagrange/2
129  call hecmw_construct_hecmat_from_noderelated(hecmat%N, hecmat%NP, hecmat%NDOF, &
130  & numnon0_node, num_lagrange, list_noderelated, hecmat)
131  call hecmw_construct_hecmat_from_noderelated(hecmat%N, hecmat%NP, hecmat%NDOF, &
132  & numnon0_node, num_lagrange, list_noderelated, conmat)
133  if( contact_algo == kcaslagrange ) call hecmw_construct_heclagmat_from_noderelated(hecmat%NP, &
134  & hecmat%NDOF, num_lagrange, numnon0_lagrange, is_contact_active_flag, list_noderelated, heclagmat)
135  call hecmw_finalize_noderelated(list_noderelated)
136 
137  ! Copy Lagrange multipliers
138  if( is_contact_active_flag .and. contact_algo == kcaslagrange ) &
139  call fstr_copy_lagrange_contact(fstrsolid,heclagmat)
140 
141  end subroutine fstr_mat_con_contact
142 
144  subroutine getnewlistofrelatednodesandlagrangemultipliers( &
145  & cstep, contact_algo, np, fstrSOLID, countNon0LU_node, countNon0LU_lagrange, list_nodeRelated )
146  integer(kind=kint),intent(in) :: cstep
147  integer(kind=kint),intent(in) :: contact_algo
148  integer(kind=kint),intent(in) :: np
149  type(fstr_solid),intent(in) :: fstrsolid
150  integer(kind=kint), intent(inout) :: countnon0lu_node, countnon0lu_lagrange
151  type(noderelated), pointer, intent(inout) :: list_noderelated(:)
152 
153  integer(kind=kint) :: grpid
154  integer(kind=kint) :: count_lagrange
155  integer(kind=kint) :: ctsurf, etype, nnode, ndlocal(l_max_surface_node + 1)
156  integer(kind=kint) :: i, j, k, nlag, algtype
157  real(kind=kreal) :: fcoeff
158  logical :: necessary_to_insert_node, necessary_to_insert_node_pair
159  logical :: is_contact_active_flag, is_damping_active_flag
160 
161  count_lagrange = 0
162  do i = 1, fstrsolid%n_contacts
163  ! Process only NODE-SURF pairs here (mortar pairs are handled by getNewListOF..._ss).
164  ! For a mortar pair states(j)%surface is -1, so master(ctsurf)%etype below would be an
165  ! out-of-bounds read on a mixed deck.
166  if( fstrsolid%contacts(i)%method /= contactn2s ) cycle
167 
168  grpid = fstrsolid%contacts(i)%group
169  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
170 
171  fcoeff = fstrsolid%contacts(i)%fcoeff
172  necessary_to_insert_node = ( fcoeff /= 0.0d0 .or. contact_algo == kcaalagrange )
173 
174  algtype = fstrsolid%contacts(i)%algtype
175  nlag = fstr_get_num_lagrange_pernode(algtype)
176  if( contact_algo == kcaalagrange ) nlag = 1
177  if( algtype == contacttied ) permission = .true.
178 
179  do j = 1, size(fstrsolid%contacts(i)%slave)
180  ! stick or sliding contact is active
181  is_contact_active_flag = is_contact_active(fstrsolid%contacts(i)%states(j)%state)
182  ! damping is active
183  is_damping_active_flag = fstrsolid%contacts(i)%states(j)%state == contactnear .and. &
184  & is_damping_enabled(fstrsolid%contacts(i))
185 
186  if( is_contact_active_flag .or. is_damping_active_flag ) then
187 
188  ctsurf = fstrsolid%contacts(i)%states(j)%surface
189  etype = fstrsolid%contacts(i)%master(ctsurf)%etype
190  if( etype/=fe_tri3n .and. etype/=fe_quad4n ) &
191  stop " ##Error: This element type is not supported in contact analysis !!! "
192  nnode = size(fstrsolid%contacts(i)%master(ctsurf)%nodes)
193  ndlocal(1) = fstrsolid%contacts(i)%slave(j)
194  ndlocal(2:nnode+1) = fstrsolid%contacts(i)%master(ctsurf)%nodes(1:nnode)
195 
196  ! For CONTACTNEAR damping (especially S-Lagrange + frictionless),
197  ! we still need slave-master connectivity to assemble damping terms.
198  necessary_to_insert_node_pair = necessary_to_insert_node .or. is_damping_active_flag
199 
200  if( is_contact_active_flag ) then
201  do k=1,nlag
202  if( contact_algo == kcaslagrange ) count_lagrange = count_lagrange + 1
203  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, count_lagrange, permission, &
204  & necessary_to_insert_node_pair, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
205  enddo
206  else
207  ! NEAR damping only: no Lagrange multiplier, insert connectivity once
208  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, 0, permission, &
209  & necessary_to_insert_node_pair, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
210  endif
211 
212  end if
213 
214  enddo
215 
216  enddo
217 
218  do i = 1, fstrsolid%n_embeds
219 
220  grpid = fstrsolid%embeds(i)%group
221  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) cycle
222 
223  necessary_to_insert_node = ( contact_algo == kcaalagrange )
224 
225  nlag = 3
226  if( contact_algo == kcaalagrange ) nlag = 1
227  permission = .true.
228 
229  do j = 1, size(fstrsolid%embeds(i)%slave)
230 
231  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
232  ctsurf = fstrsolid%embeds(i)%states(j)%surface
233  etype = fstrsolid%embeds(i)%master(ctsurf)%etype
234  nnode = size(fstrsolid%embeds(i)%master(ctsurf)%nodes)
235  ndlocal(1) = fstrsolid%embeds(i)%slave(j)
236  ndlocal(2:nnode+1) = fstrsolid%embeds(i)%master(ctsurf)%nodes(1:nnode)
237 
238  do k=1,nlag
239  if( contact_algo == kcaslagrange ) count_lagrange = count_lagrange + 1
240  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, count_lagrange, permission, &
241  & necessary_to_insert_node, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
242  enddo
243  enddo
244 
245  enddo
246 
247  end subroutine getnewlistofrelatednodesandlagrangemultipliers
248 
250  subroutine fstr_copy_lagrange_contact(fstrSOLID,hecLagMAT)
251 
252  type(fstr_solid) :: fstrsolid
253  type(hecmwst_matrix_lagrange) :: heclagmat
254  integer (kind=kint) :: id_lagrange, algtype, i, j, k, nlag, slave_node
255 
256  id_lagrange = 0
257 
258  do i = 1, fstrsolid%n_contacts
259 
260  algtype = fstrsolid%contacts(i)%algtype
261  nlag = fstr_get_num_lagrange_pernode(algtype)
262 
263  do j = 1, size(fstrsolid%contacts(i)%slave)
264  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
265  slave_node = fstrsolid%contacts(i)%slave(j)
266  heclagmat%lag_node_table(slave_node) = id_lagrange + 1
267  do k=1,nlag
268  id_lagrange = id_lagrange + 1
269  heclagmat%Lagrange(id_lagrange)=fstrsolid%contacts(i)%states(j)%multiplier(k)
270  enddo
271  enddo
272  enddo
273 
274  do i = 1, fstrsolid%n_embeds
275  nlag = 3
276  do j = 1, size(fstrsolid%embeds(i)%slave)
277  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
278  slave_node = fstrsolid%embeds(i)%slave(j)
279  heclagmat%lag_node_table(slave_node) = id_lagrange + 1
280  do k=1,nlag
281  id_lagrange = id_lagrange + 1
282  heclagmat%Lagrange(id_lagrange)=fstrsolid%embeds(i)%states(j)%multiplier(k)
283  enddo
284  enddo
285  enddo
286 
287  end subroutine fstr_copy_lagrange_contact
288 
290  logical function fstr_is_matrixstruct_symmetric(fstrSOLID,hecMESH)
291 
292  type(fstr_solid ) :: fstrsolid
293  type(hecmwst_local_mesh) :: hecmesh
294  integer (kind=kint) :: is_in_contact
295 
296  is_in_contact = 0
297  if( fstrsolid%n_contacts>0 ) then
298  if( any(fstrsolid%contacts(:)%fcoeff /= 0.0d0) ) is_in_contact = 1
299  endif
300  call hecmw_allreduce_i1(hecmesh, is_in_contact, hecmw_max)
301  if( is_in_contact == 0 .and. hecmesh%n_dof /= 4 .and. fstr_is_material_symmetric(fstrsolid,hecmesh) ) then
303  else
305  endif
306 
307  end function fstr_is_matrixstruct_symmetric
308 
310  logical function fstr_is_contactalag_symmetric(fstrSOLID,hecMESH)
311 
312  type(fstr_solid ) :: fstrsolid
313  type(hecmwst_local_mesh) :: hecmesh
314  integer (kind=kint) :: is_unsymmetric
315 
316  ! the ALagrange contact terms are symmetric while the friction cone radius stays frozen
317  ! at the multiplier; !CONTACT_ALGO, FRICTION_CONE=FOLLOW clears contact%symmetric and
318  ! the tangent then carries the coupling block of getContactStiffness_Alag
319  is_unsymmetric = 0
320  if( fstrsolid%n_contacts>0 ) then
321  if( any( fstrsolid%contacts(:)%fcoeff /= 0.0d0 .and. .not.fstrsolid%contacts(:)%symmetric ) ) is_unsymmetric = 1
322  endif
323  call hecmw_allreduce_i1(hecmesh, is_unsymmetric, hecmw_max)
324  fstr_is_contactalag_symmetric = ( is_unsymmetric == 0 ) .and. fstr_is_material_symmetric(fstrsolid,hecmesh)
325 
326  end function fstr_is_contactalag_symmetric
327 
329  logical function fstr_is_material_symmetric(fstrSOLID,hecMESH)
330 
331  type(fstr_solid ) :: fstrsolid
332  type(hecmwst_local_mesh) :: hecmesh
333  integer (kind=kint) :: is_unsymmetric, i, ytype
334 
335  ! non-associated flow (dilatancy angle psi /= friction angle phi) makes the consistent
336  ! tangent unsymmetric; when psi is omitted the parser stores psi=phi, so the exact
337  ! comparison below classifies that case as associated (symmetric)
338  is_unsymmetric = 0
339  if( associated(fstrsolid%materials) ) then
340  do i = 1, size(fstrsolid%materials)
341  ytype = getyieldfunction( fstrsolid%materials(i)%mtype )
342  if( ytype == 1 ) then ! Mohr-Coulomb: PLCONST3=phi, PLCONST4=psi
343  if( fstrsolid%materials(i)%variables(m_plconst3) /= fstrsolid%materials(i)%variables(m_plconst4) ) &
344  is_unsymmetric = 1
345  elseif( ytype == 2 ) then ! Drucker-Prager: PLCONST3=eta(phi), PLCONST5=etabar(psi)
346  if( fstrsolid%materials(i)%variables(m_plconst3) /= fstrsolid%materials(i)%variables(m_plconst5) ) &
347  is_unsymmetric = 1
348  endif
349  enddo
350  endif
351  call hecmw_allreduce_i1(hecmesh, is_unsymmetric, hecmw_max)
352  fstr_is_material_symmetric = (is_unsymmetric == 0)
353 
354  end function fstr_is_material_symmetric
355 
357  subroutine fstr_set_lagrange_diagonal(hecLagMAT, ilag, value)
358  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
359  integer(kind=kint), intent(in) :: ilag
360  real(kind=kreal), intent(in) :: value
361 
362  if (ilag < 1 .or. ilag > heclagmat%num_lagrange) then
363  write(*,*) 'Error in fstr_set_lagrange_diagonal: invalid Lagrange multiplier index', ilag
364  stop
365  endif
366 
367  if (.not. associated(heclagmat%D_lagrange)) then
368  write(*,*) 'Error in fstr_set_lagrange_diagonal: D_lagrange not allocated'
369  stop
370  endif
371 
372  heclagmat%D_lagrange(ilag) = value
373 
374  end subroutine fstr_set_lagrange_diagonal
375 
377  real(kind=kreal) function fstr_get_lagrange_diagonal(hecLagMAT, ilag)
378  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
379  integer(kind=kint), intent(in) :: ilag
380 
381  if (ilag < 1 .or. ilag > heclagmat%num_lagrange) then
382  write(*,*) 'Error in fstr_get_lagrange_diagonal: invalid Lagrange multiplier index', ilag
384  return
385  endif
386 
387  if (.not. associated(heclagmat%D_lagrange)) then
388  write(*,*) 'Error in fstr_get_lagrange_diagonal: D_lagrange not allocated'
390  return
391  endif
392 
393  fstr_get_lagrange_diagonal = heclagmat%D_lagrange(ilag)
394 
395  end function fstr_get_lagrange_diagonal
396 
397 
398  subroutine getnewlistofrelatednodesandlagrangemultipliers_ss( &
399  & cstep, contact_algo, np, fstrSOLID, countNon0LU_node, countNon0LU_lagrange, list_nodeRelated )
400  integer(kind=kint),intent(in) :: cstep
401  integer(kind=kint),intent(in) :: contact_algo
402  integer(kind=kint),intent(in) :: np
403  type(fstr_solid),intent(in) :: fstrsolid
404  integer(kind=kint), intent(inout) :: countnon0lu_node, countnon0lu_lagrange
405  type(noderelated), pointer, intent(inout) :: list_noderelated(:)
406  integer(kind=kint) :: grpid
407  integer(kind=kint) :: ctsurf, nsurf
408  integer(kind=kint) :: i, j, m
409  integer(kind=kint) :: g, unique_count
410  integer(kind=kint) :: maplist(max_n_intp), master_idxs(max_n_intp)
411  real(kind=kreal) :: fcoeff
412  logical :: necessary_to_insert_node
413 
414  do i = 1, fstrsolid%n_contacts
415  if( fstrsolid%contacts(i)%method /= contacts2s ) cycle
416  grpid = fstrsolid%contacts(i)%group
417  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
418 
419  fcoeff = fstrsolid%contacts(i)%fcoeff
420  necessary_to_insert_node = ( fcoeff /= 0.0d0 .or. contact_algo == kcaalagrange )
421 
422  do j = 1, size(fstrsolid%contacts(i)%slave_surf)
423  if( fstrsolid%contacts(i)%slave_surf(j)%state == contactfree ) cycle
424 
425  if( contact_algo == kcaalagrange ) then
426  ! ALagrange SS: register sparsity once per unique (slave_surf, master) pair.
427  ! sparsity_expansion == SPARSITY_NONE: current master element only (matrix rebuilt on contact2neighbor)
428  ! sparsity_expansion == SPARSITY_NEIGHBOR: current + neighbor master elements (matrix rebuilt only on contact2beyond)
429  call get_unique_map( fstrsolid%contacts(i)%slave_surf(j), maplist, master_idxs, unique_count )
430  do g = 1, unique_count
431  ctsurf = master_idxs(g)
432  ! Register current master element
433  call register_pair_to_sparsity( np, fstrsolid%contacts(i)%slave_surf(j)%nodes, &
434  fstrsolid%contacts(i)%master(ctsurf), necessary_to_insert_node, &
435  countnon0lu_node, countnon0lu_lagrange, list_noderelated )
436 
437  ! SPARSITY_NEIGHBOR: also register neighbor master elements
438  if( fstrsolid%contacts(i)%sparsity_expansion == sparsity_neighbor ) then
439  do m = 1, fstrsolid%contacts(i)%master(ctsurf)%n_neighbor
440  nsurf = fstrsolid%contacts(i)%master(ctsurf)%neighbor(m)
441  call register_pair_to_sparsity( np, fstrsolid%contacts(i)%slave_surf(j)%nodes, &
442  fstrsolid%contacts(i)%master(nsurf), necessary_to_insert_node, &
443  countnon0lu_node, countnon0lu_lagrange, list_noderelated )
444  enddo
445  endif
446  enddo
447  endif
448  enddo
449  enddo
450 
451  end subroutine getnewlistofrelatednodesandlagrangemultipliers_ss
452 
456  subroutine register_pair_to_sparsity( np, slave_nodes, master_surf, &
457  & necessary_to_insert_node, countNon0LU_node, countNon0LU_lagrange, list_nodeRelated )
458  integer(kind=kint), intent(in) :: np
459  integer(kind=kint), intent(in) :: slave_nodes(:)
460  type(tsurfelement), intent(in) :: master_surf
461  logical, intent(in) :: necessary_to_insert_node
462  integer(kind=kint), intent(inout) :: countnon0lu_node, countnon0lu_lagrange
463  type(noderelated), pointer, intent(inout) :: list_noderelated(:)
464 
465  integer(kind=kint) :: nnode_s, nnode_m, l, m, idx, nnode_pair, etype
466  integer(kind=kint) :: ndlocal(2*l_max_surface_node + 1)
467 
468  etype = master_surf%etype
469  if( etype/=fe_tri3n .and. etype/=fe_quad4n ) stop " ##Error: This element type is not supported in contact analysis !!! "
470  nnode_s = size(slave_nodes)
471  nnode_m = size(master_surf%nodes)
472  do l = 1, nnode_s
473  ndlocal(1) = slave_nodes(l)
474  ! ndLocal: slave_l + other_slave_nodes + master_nodes
475  idx = 1
476  do m = 1, nnode_s
477  if( m == l ) cycle
478  idx = idx + 1
479  ndlocal(idx) = slave_nodes(m)
480  enddo
481  ndlocal(idx+1:idx+nnode_m) = master_surf%nodes(:)
482  nnode_pair = nnode_s - 1 + nnode_m
483  ! mortar pairs have no Lagrange row: 0 keeps insert_lagrange out of the reservation
484  call hecmw_ass_noderelated_from_contact_pair( np, nnode_pair, ndlocal, 0, permission, &
485  & necessary_to_insert_node, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
486  enddo
487  end subroutine register_pair_to_sparsity
488 
512  logical function fstr_s2s_profile_needs_refresh( cstep, contact_algo, fstrSOLID, conMAT )
513  integer(kind=kint), intent(in) :: cstep
514  integer(kind=kint), intent(in) :: contact_algo
515  type(fstr_solid), intent(in) :: fstrsolid
516  type(hecmwst_matrix), intent(in) :: conmat
517 
518  integer(kind=kint) :: i, j, g, ctsurf, grpid, unique_count
519  integer(kind=kint) :: maplist(max_n_intp), master_idxs(max_n_intp)
520 
522  if( contact_algo /= kcaalagrange ) return
523 
524  do i = 1, fstrsolid%n_contacts
525  if( fstrsolid%contacts(i)%method /= contacts2s ) cycle
526  grpid = fstrsolid%contacts(i)%group
527  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
528 
529  do j = 1, size(fstrsolid%contacts(i)%slave_surf)
530  if( fstrsolid%contacts(i)%slave_surf(j)%state == contactfree ) cycle
531 
532  call get_unique_map( fstrsolid%contacts(i)%slave_surf(j), maplist, master_idxs, unique_count )
533  do g = 1, unique_count
534  ctsurf = master_idxs(g)
535  if( .not. pair_cross_profile_complete( fstrsolid%contacts(i)%slave_surf(j)%nodes, &
536  & fstrsolid%contacts(i)%master(ctsurf), conmat ) ) then
538  return
539  endif
540  enddo
541  enddo
542  enddo
543  end function fstr_s2s_profile_needs_refresh
544 
548  logical function pair_cross_profile_complete( slave_nodes, master_surf, conMAT )
549  integer(kind=kint), intent(in) :: slave_nodes(:)
550  type(tsurfelement), intent(in) :: master_surf
551  type(hecmwst_matrix), intent(in) :: conmat
552 
553  integer(kind=kint) :: s, m
554 
555  pair_cross_profile_complete = .true.
556  do s = 1, size(slave_nodes)
557  do m = 1, size(master_surf%nodes)
558  if( .not. hecmw_mat_profile_has_node( conmat, slave_nodes(s), master_surf%nodes(m) ) ) then
559  pair_cross_profile_complete = .false.
560  return
561  endif
562  enddo
563  enddo
564  end function pair_cross_profile_complete
565 
566 end module fstr_matrix_con_contact
This module encapsulate the basic functions of all elements provide by this software.
Definition: element.f90:43
integer, parameter fe_tri3n
Definition: element.f90:70
integer, parameter fe_quad4n
Definition: element.f90:73
This module provides functions of reconstructing.
subroutine, public fstr_mat_con_contact(cstep, contact_algo, hecMAT, fstrSOLID, hecLagMAT, infoCTChange, conMAT, is_contact_active_flag)
this subroutine reconstructs node-based (stiffness) matrix structure \corresponding to contact state
subroutine, public fstr_set_lagrange_diagonal(hecLagMAT, ilag, value)
Set diagonal component value for specified Lagrange multiplier.
integer(kind=kint) function, public fstr_get_num_lagrange_pernode(algtype)
logical function, public fstr_s2s_profile_needs_refresh(cstep, contact_algo, fstrSOLID, conMAT)
S2S mortar profile-invariant check (read-only companion to the reservation in getNewListOFrelatednode...
logical function, public fstr_is_material_symmetric(fstrSOLID, hecMESH)
this function judges whether all materials yield a symmetric tangent stiffness
logical function, public fstr_is_contactalag_symmetric(fstrSOLID, hecMESH)
this function judges whether the ALagrange contact tangent is symmetric or not
subroutine, public fstr_save_originalmatrixstructure(hecMAT)
This subroutine saves original matrix structure constructed originally by hecMW_matrix.
logical function, public fstr_is_matrixstruct_symmetric(fstrSOLID, hecMESH)
this function judges whether sitiffness matrix is symmetric or not
real(kind=kreal) function, public fstr_get_lagrange_diagonal(hecLagMAT, ilag)
Get diagonal component value for specified Lagrange multiplier.
logical function, public hecmw_mat_profile_has_node(hecMAT, inod, jnod)
Read-only companion to hecmw_mat_add_node: report whether the (inod, jnod) block exists in the matrix...
Contact damping module for CONTACTNEAR state.
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 get_unique_map(sSurf, maplist, master_idxs, unique_count)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
logical function fstr_isembedactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1126
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1116
integer(kind=kint), parameter kcaslagrange
contact analysis algorithm
Definition: m_fstr.F90:62
integer(kind=kint), parameter kcaalagrange
Definition: m_fstr.F90:63