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
14 
15  implicit none
16  private
18  public :: hecmwst_matrix_lagrange
20  public :: fstr_mat_con_contact
24 
25  integer(kind=kint), save :: NPL_org, NPU_org
26  type(nodeRelated), pointer, save :: list_nodeRelated_org(:) => null()
27 
28  type(nodeRelated), pointer :: list_nodeRelated(:) => null()
29 
30  logical :: permission = .false.
31 
32 contains
33 
34  integer(kind=kint) function fstr_get_num_lagrange_pernode(algtype)
35  integer(kind=kint) :: algtype
36  if( algtype == contactsslid .or. algtype == contactfslid ) then
38  else if( algtype == contacttied ) then
40  endif
41  end function
42 
45 
46  type(hecmwst_matrix) :: hecmat
47 
48  if( associated(list_noderelated_org) ) return
49  call hecmw_construct_noderelated_from_hecmat(hecmat, npl_org, npu_org, list_noderelated_org)
50 
52 
55  subroutine fstr_mat_con_contact(cstep,contact_algo,hecMAT,fstrSOLID,hecLagMAT,infoCTChange,conMAT,is_contact_active_flag)
56 
57  integer(kind=kint) :: cstep
58  integer(kind=kint) :: contact_algo
59  type(hecmwst_matrix) :: hecmat
60  type(fstr_solid) :: fstrsolid
61  type(hecmwst_matrix_lagrange) :: heclagmat
62  type(fstr_info_contactchange) :: infoctchange
63 
64  integer(kind=kint) :: num_lagrange
65  integer(kind=kint) :: countnon0lu_node, countnon0lu_lagrange
66  integer(kind=kint) :: numnon0_node, numnon0_lagrange
68  type (hecmwst_matrix) :: conmat
69  logical, intent(in) :: is_contact_active_flag
70 
71  integer(kind=kint) :: i, j, grpid
72  integer(kind=kint) :: nlag
73 
74  num_lagrange = 0
75  if( contact_algo == kcaslagrange ) then
76  do i = 1, fstrsolid%n_contacts
77  grpid = fstrsolid%contacts(i)%group
78  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
79  nlag = fstr_get_num_lagrange_pernode(fstrsolid%contacts(i)%algtype)
80  do j = 1, size(fstrsolid%contacts(i)%slave)
81  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
82  num_lagrange = num_lagrange + nlag
83  enddo
84  enddo
85 
86  do i = 1, fstrsolid%n_embeds
87  grpid = fstrsolid%embeds(i)%group
88  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
89  nlag = 3
90  do j = 1, size(fstrsolid%embeds(i)%slave)
91  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
92  num_lagrange = num_lagrange + nlag
93  enddo
94  enddo
95  endif
96 
97  ! Get original list of related nodes
98  call hecmw_init_noderelated_from_org(hecmat%NP,num_lagrange,is_contact_active_flag,list_noderelated_org,list_noderelated)
99 
100  ! Construct new list of related nodes and Lagrange multipliers
101  countnon0lu_node = npl_org + npu_org
102  countnon0lu_lagrange = 0
103  if( is_contact_active_flag ) call getnewlistofrelatednodesandlagrangemultipliers(cstep,contact_algo, &
104  & hecmat%NP,fstrsolid,countnon0lu_node,countnon0lu_lagrange,list_noderelated)
105 
106  ! Construct new matrix structure(hecMAT&hecLagMAT)
107  numnon0_node = countnon0lu_node/2
108  numnon0_lagrange = countnon0lu_lagrange/2
109  call hecmw_construct_hecmat_from_noderelated(hecmat%N, hecmat%NP, hecmat%NDOF, &
110  & numnon0_node, num_lagrange, list_noderelated, hecmat)
111  call hecmw_construct_hecmat_from_noderelated(hecmat%N, hecmat%NP, hecmat%NDOF, &
112  & numnon0_node, num_lagrange, list_noderelated, conmat)
113  if( contact_algo == kcaslagrange ) call hecmw_construct_heclagmat_from_noderelated(hecmat%NP, &
114  & hecmat%NDOF, num_lagrange, numnon0_lagrange, is_contact_active_flag, list_noderelated, heclagmat)
115  call hecmw_finalize_noderelated(list_noderelated)
116 
117  ! Copy Lagrange multipliers
118  if( is_contact_active_flag .and. contact_algo == kcaslagrange ) &
119  call fstr_copy_lagrange_contact(fstrsolid,heclagmat)
120 
121  end subroutine fstr_mat_con_contact
122 
124  subroutine getnewlistofrelatednodesandlagrangemultipliers( &
125  & cstep, contact_algo, np, fstrSOLID, countNon0LU_node, countNon0LU_lagrange, list_nodeRelated )
126  integer(kind=kint),intent(in) :: cstep
127  integer(kind=kint),intent(in) :: contact_algo
128  integer(kind=kint),intent(in) :: np
129  type(fstr_solid),intent(in) :: fstrsolid
130  integer(kind=kint), intent(inout) :: countnon0lu_node, countnon0lu_lagrange
131  type(noderelated), pointer, intent(inout) :: list_noderelated(:)
132 
133  integer(kind=kint) :: grpid
134  integer(kind=kint) :: count_lagrange
135  integer(kind=kint) :: ctsurf, etype, nnode, ndlocal(l_max_surface_node + 1)
136  integer(kind=kint) :: i, j, k, nlag, algtype
137  real(kind=kreal) :: fcoeff
138  logical :: necessary_to_insert_node, necessary_to_insert_node_pair
139  logical :: is_contact_active_flag, is_damping_active_flag
140 
141  count_lagrange = 0
142  do i = 1, fstrsolid%n_contacts
143 
144  grpid = fstrsolid%contacts(i)%group
145  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
146 
147  fcoeff = fstrsolid%contacts(i)%fcoeff
148  necessary_to_insert_node = ( fcoeff /= 0.0d0 .or. contact_algo == kcaalagrange )
149 
150  algtype = fstrsolid%contacts(i)%algtype
151  nlag = fstr_get_num_lagrange_pernode(algtype)
152  if( contact_algo == kcaalagrange ) nlag = 1
153  if( algtype == contacttied ) permission = .true.
154 
155  do j = 1, size(fstrsolid%contacts(i)%slave)
156  ! stick or sliding contact is active
157  is_contact_active_flag = is_contact_active(fstrsolid%contacts(i)%states(j)%state)
158  ! damping is active
159  is_damping_active_flag = fstrsolid%contacts(i)%states(j)%state == contactnear .and. &
160  & is_damping_enabled(fstrsolid%contacts(i))
161 
162  if( is_contact_active_flag .or. is_damping_active_flag ) then
163 
164  ctsurf = fstrsolid%contacts(i)%states(j)%surface
165  etype = fstrsolid%contacts(i)%master(ctsurf)%etype
166  if( etype/=fe_tri3n .and. etype/=fe_quad4n ) &
167  stop " ##Error: This element type is not supported in contact analysis !!! "
168  nnode = size(fstrsolid%contacts(i)%master(ctsurf)%nodes)
169  ndlocal(1) = fstrsolid%contacts(i)%slave(j)
170  ndlocal(2:nnode+1) = fstrsolid%contacts(i)%master(ctsurf)%nodes(1:nnode)
171 
172  ! For CONTACTNEAR damping (especially S-Lagrange + frictionless),
173  ! we still need slave-master connectivity to assemble damping terms.
174  necessary_to_insert_node_pair = necessary_to_insert_node .or. is_damping_active_flag
175 
176  if( is_contact_active_flag ) then
177  do k=1,nlag
178  if( contact_algo == kcaslagrange ) count_lagrange = count_lagrange + 1
179  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, count_lagrange, permission, &
180  & necessary_to_insert_node_pair, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
181  enddo
182  else
183  ! NEAR damping only: no Lagrange multiplier, insert connectivity once
184  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, 0, permission, &
185  & necessary_to_insert_node_pair, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
186  endif
187 
188  end if
189 
190  enddo
191 
192  enddo
193 
194  do i = 1, fstrsolid%n_embeds
195 
196  grpid = fstrsolid%embeds(i)%group
197  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) cycle
198 
199  necessary_to_insert_node = ( contact_algo == kcaalagrange )
200 
201  nlag = 3
202  if( contact_algo == kcaalagrange ) nlag = 1
203  permission = .true.
204 
205  do j = 1, size(fstrsolid%embeds(i)%slave)
206 
207  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
208  ctsurf = fstrsolid%embeds(i)%states(j)%surface
209  etype = fstrsolid%embeds(i)%master(ctsurf)%etype
210  nnode = size(fstrsolid%embeds(i)%master(ctsurf)%nodes)
211  ndlocal(1) = fstrsolid%embeds(i)%slave(j)
212  ndlocal(2:nnode+1) = fstrsolid%embeds(i)%master(ctsurf)%nodes(1:nnode)
213 
214  do k=1,nlag
215  if( contact_algo == kcaslagrange ) count_lagrange = count_lagrange + 1
216  call hecmw_ass_noderelated_from_contact_pair(np, nnode, ndlocal, count_lagrange, permission, &
217  & necessary_to_insert_node, list_noderelated_org, list_noderelated, countnon0lu_node, countnon0lu_lagrange )
218  enddo
219  enddo
220 
221  enddo
222 
223  end subroutine getnewlistofrelatednodesandlagrangemultipliers
224 
226  subroutine fstr_copy_lagrange_contact(fstrSOLID,hecLagMAT)
227 
228  type(fstr_solid) :: fstrsolid
229  type(hecmwst_matrix_lagrange) :: heclagmat
230  integer (kind=kint) :: id_lagrange, algtype, i, j, k, nlag, slave_node
231 
232  id_lagrange = 0
233 
234  do i = 1, fstrsolid%n_contacts
235 
236  algtype = fstrsolid%contacts(i)%algtype
237  nlag = fstr_get_num_lagrange_pernode(algtype)
238 
239  do j = 1, size(fstrsolid%contacts(i)%slave)
240  if( .not. is_contact_active(fstrsolid%contacts(i)%states(j)%state) ) cycle
241  slave_node = fstrsolid%contacts(i)%slave(j)
242  heclagmat%lag_node_table(slave_node) = id_lagrange + 1
243  do k=1,nlag
244  id_lagrange = id_lagrange + 1
245  heclagmat%Lagrange(id_lagrange)=fstrsolid%contacts(i)%states(j)%multiplier(k)
246  enddo
247  enddo
248  enddo
249 
250  do i = 1, fstrsolid%n_embeds
251  nlag = 3
252  do j = 1, size(fstrsolid%embeds(i)%slave)
253  if( .not. is_contact_active(fstrsolid%embeds(i)%states(j)%state) ) cycle
254  slave_node = fstrsolid%embeds(i)%slave(j)
255  heclagmat%lag_node_table(slave_node) = id_lagrange + 1
256  do k=1,nlag
257  id_lagrange = id_lagrange + 1
258  heclagmat%Lagrange(id_lagrange)=fstrsolid%embeds(i)%states(j)%multiplier(k)
259  enddo
260  enddo
261  enddo
262 
263  end subroutine fstr_copy_lagrange_contact
264 
266  logical function fstr_is_matrixstruct_symmetric(fstrSOLID,hecMESH)
267 
268  type(fstr_solid ) :: fstrsolid
269  type(hecmwst_local_mesh) :: hecmesh
270  integer (kind=kint) :: is_in_contact
271 
272  is_in_contact = 0
273  if( fstrsolid%n_contacts>0 ) then
274  if( any(fstrsolid%contacts(:)%fcoeff /= 0.0d0) ) is_in_contact = 1
275  endif
276  call hecmw_allreduce_i1(hecmesh, is_in_contact, hecmw_max)
277  if( is_in_contact == 0 .and. hecmesh%n_dof /= 4 ) then
279  else
281  endif
282 
283  end function fstr_is_matrixstruct_symmetric
284 
286  subroutine fstr_set_lagrange_diagonal(hecLagMAT, ilag, value)
287  type(hecmwst_matrix_lagrange), intent(inout) :: heclagmat
288  integer(kind=kint), intent(in) :: ilag
289  real(kind=kreal), intent(in) :: value
290 
291  if (ilag < 1 .or. ilag > heclagmat%num_lagrange) then
292  write(*,*) 'Error in fstr_set_lagrange_diagonal: invalid Lagrange multiplier index', ilag
293  stop
294  endif
295 
296  if (.not. associated(heclagmat%D_lagrange)) then
297  write(*,*) 'Error in fstr_set_lagrange_diagonal: D_lagrange not allocated'
298  stop
299  endif
300 
301  heclagmat%D_lagrange(ilag) = value
302 
303  end subroutine fstr_set_lagrange_diagonal
304 
306  real(kind=kreal) function fstr_get_lagrange_diagonal(hecLagMAT, ilag)
307  type(hecmwst_matrix_lagrange), intent(in) :: heclagmat
308  integer(kind=kint), intent(in) :: ilag
309 
310  if (ilag < 1 .or. ilag > heclagmat%num_lagrange) then
311  write(*,*) 'Error in fstr_get_lagrange_diagonal: invalid Lagrange multiplier index', ilag
313  return
314  endif
315 
316  if (.not. associated(heclagmat%D_lagrange)) then
317  write(*,*) 'Error in fstr_get_lagrange_diagonal: D_lagrange not allocated'
319  return
320  endif
321 
322  fstr_get_lagrange_diagonal = heclagmat%D_lagrange(ilag)
323 
324  end function fstr_get_lagrange_diagonal
325 
326 
327 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:69
integer, parameter fe_quad4n
Definition: element.f90:72
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)
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.
Contact damping module for CONTACTNEAR state.
pure logical function, public is_damping_enabled(contact)
Check if damping is enabled for a contact pair.
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:1087
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.F90:1077
integer(kind=kint), parameter kcaslagrange
contact analysis algorithm
Definition: m_fstr.F90:61
integer(kind=kint), parameter kcaalagrange
Definition: m_fstr.F90:62