FrontISTR  5.7.0
Large-scale structural analysis program with finit element method
fstr_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 module mcontact
7 
8  use mcontactdef
9  use hecmw
10  use m_fstr
11  implicit none
12 
13  private :: l_contact2mpc, l_tied2mpc
14  integer(kind=kint), save :: n_contact_mpc
15  logical, private :: active
16 
17  real(kind=kreal), save :: mu=1.d10
18  real(kind=kreal), save :: mut=1.d6
19  real(kind=kreal), save :: cdotp=1.d3
20 
21  real(kind=kreal), save :: cgn=1.d-5
22  real(kind=kreal), save :: cgt=1.d-3
23 
24  real(kind=kreal), save :: gnt(2)
26  real(kind=kreal), save :: bakgnt(2)
28 
29 contains
30 
32  subroutine print_contatct_pair( file, pair )
33  integer(kind=kint), intent(in) :: file
34  type( hecmwst_contact_pair ), intent(in) :: pair
35 
36  integer(kind=kint) :: i
37  write(file,*) "Number of contact pair", pair%n_pair
38  do i=1,pair%n_pair
39  write(file,*) trim(pair%name(i)), pair%type(i), pair%slave_grp_id(i) &
40  ,pair%master_grp_id(i), pair%slave_orisgrp_id(i)
41  enddo
42  end subroutine
43 
44  subroutine fstr_set_contact_penalty( maxv )
45  real(kind=kreal), intent(in) :: maxv
46  mu = cdotp * maxv
47  if( gnt(1)<1.d-3 ) mu=cdotp*10.d0* maxv
48  bakgnt = 0.d0
49  end subroutine
50 
51  logical function fstr_is_contact_active()
53  end function
54 
55  subroutine fstr_set_contact_active( a )
56  logical, intent(in) :: a
57  active = a
58  end subroutine
59 
60  logical function fstr_is_contact_conv(ctAlgo,infoCTChange,hecMESH)
61  integer(kind=kint), intent(in) :: ctalgo
62  type (fstr_info_contactchange), intent(in) :: infoctchange
63  type (hecmwst_local_mesh), intent(in) :: hecmesh
64  integer(kind=kint) :: is_conv
65 
66  fstr_is_contact_conv = .false.
67  if( infoctchange%contact2free+infoctchange%contact2neighbor+ &
68  infoctchange%contact2difflpos+infoctchange%free2contact == 0 ) &
69  fstr_is_contact_conv = .true.
70 
71  is_conv = 0
72  if (fstr_is_contact_conv) is_conv = 1
73  call hecmw_allreduce_i1(hecmesh, is_conv, hecmw_min)
74  if (is_conv == 0) then
75  fstr_is_contact_conv = .false.
76  else
77  fstr_is_contact_conv = .true.
78  endif
79  end function
80 
81  logical function fstr_is_matrixstructure_changed(infoCTChange)
82  type (fstr_info_contactchange) :: infoctchange
84  if( infoctchange%contact2free+infoctchange%contact2neighbor+infoctchange%free2contact > 0 ) &
86  end function
87 
89  subroutine l_contact2mpc( contact, mpcs, nmpc )
91  type( tcontact ), intent(in) :: contact
92  type( hecmwst_mpc ), intent(inout) :: mpcs
93  integer(kind=kint), intent(out) :: nmpc
94  integer(kind=kint), parameter :: ndof = 3 ! 3D problem only, currently
95  real(kind=kreal), parameter :: tol =1.d-10
96  integer(kind=kint) :: i, j, k, nn, csurf, nenode, etype, tdof
97  integer(kind=kint) :: nodes(l_max_surface_node*ndof+ndof), dofs(l_max_surface_node*ndof+ndof)
98  real(kind=kreal) :: values(l_max_surface_node*ndof+ndof+1),val(l_max_surface_node*ndof+ndof+1)
99  nmpc=0
100  do i=1,size(contact%states)
101  if( contact%states(i)%state == -1 ) cycle ! in free
102  csurf = contact%states(i)%surface
103  if( csurf<=0 ) stop "error in contact state"
104  etype = contact%master(csurf)%etype
105  nenode = size(contact%master(csurf)%nodes)
106  tdof = nenode*ndof+ndof
107  call contact2mpcval( contact%states(i), etype, nenode, values(1:tdof+1) )
108  tdof = 0
109  do j=1,ndof
110  if( dabs(values(j))<tol ) cycle
111  tdof = tdof+1
112  nodes(tdof) = contact%slave(i)
113  dofs(tdof) = j
114  val(tdof) = values(j)
115  enddo
116  do j=1,nenode
117  nn = contact%master(csurf)%nodes(j)
118  nodes( j*ndof+1:j*ndof+ndof ) = nn
119  do k=1,ndof
120  if( dabs(values(j*ndof+k)) < tol ) cycle
121  tdof=tdof+1
122  nodes(tdof)=nn
123  dofs(tdof ) = k
124  val(tdof)=values(j*ndof+k)
125  enddo
126  enddo
127  val(tdof+1) = values(nenode*ndof+ndof+1)
128 
129  call fstr_append_mpc( tdof, nodes(1:tdof), dofs(1:tdof), val(1:tdof+1), mpcs )
130  nmpc=nmpc+1
131  enddo
132  end subroutine l_contact2mpc
133 
135  subroutine l_tied2mpc( contact, mpcs, nmpc )
137  type( tcontact ), intent(in) :: contact
138  type( hecmwst_mpc ), intent(inout) :: mpcs
139  integer(kind=kint), intent(out) :: nmpc
140  integer(kind=kint) :: i, j, csurf, nenode, etype, tdof
141  integer(kind=kint) :: nodes(l_max_surface_node+1), dofs(l_max_surface_node+1)
142  real(kind=kreal) :: values(l_max_surface_node+2)
143  nmpc=0
144  do i=1,size(contact%slave)
145  csurf = contact%states(i)%surface
146  if( csurf<=0 ) cycle ! contactor not exists
147  nenode = size(contact%master(csurf)%nodes)
148  tdof = nenode+1
149  nodes(1) = contact%slave(i)
150  nodes( 2:tdof ) = contact%master(csurf)%nodes(:)
151  values(1) = -1.d0
152  values(2:tdof) = 1.d0
153  values(tdof+1) = 0.d0
154  etype = contact%master(csurf)%etype
155  do j=1,3
156  dofs(1:tdof) = j
157  call fstr_append_mpc( tdof, nodes(1:tdof), dofs(1:tdof), values(1:tdof+1), mpcs )
158  nmpc=nmpc+1
159  enddo
160  enddo
161  end subroutine l_tied2mpc
162 
164  subroutine fstr_contact2mpc( contacts, mpcs )
165  type( tcontact ), intent(in) :: contacts(:)
166  type( hecmwst_mpc ), intent(inout) :: mpcs
167  integer(kind=kint) :: i, nmpc
168  n_contact_mpc = 0
169  do i=1,size(contacts)
170  if( contacts(i)%algtype == contactunknown ) cycle ! not initialized
171  if( contacts(i)%algtype == contactfslid ) then
172  print *, "Cannot deal with finit slip problems by MPC!"
173  cycle
174  endif
175  if( contacts(i)%algtype == contactsslid ) then
176  call l_contact2mpc( contacts(i), mpcs, nmpc )
178  elseif( contacts(i)%algtype == contacttied ) then
179  call l_tied2mpc( contacts(i), mpcs, nmpc )
181  endif
182  enddo
183  end subroutine
184 
186  subroutine fstr_del_contactmpc( mpcs )
188  type( hecmwst_mpc ), intent(inout) :: mpcs
189  call fstr_delete_mpc( n_contact_mpc, mpcs )
190  end subroutine
191 
193  subroutine fstr_write_mpc( file, mpcs )
194  integer(kind=kint), intent(in) :: file
195  type( hecmwst_mpc ), intent(in) :: mpcs
196 
197  integer(kind=kint) :: i,j,n0,n1
198  write(file, *) "Number of equation", mpcs%n_mpc
199  do i=1,mpcs%n_mpc
200  write(file,*) "--Equation",i
201  n0=mpcs%mpc_index(i-1)+1
202  n1=mpcs%mpc_index(i)
203  write(file, *) n0,n1
204  write(file,'(30i5)') (mpcs%mpc_item(j),j=n0,n1)
205  write(file,'(30i5)') (mpcs%mpc_dof(j),j=n0,n1)
206  write(file,'(30f7.2)') (mpcs%mpc_val(j),j=n0,n1),mpcs%mpc_const(i)
207  enddo
208  end subroutine
209 
211  subroutine fstr_scan_contact_state( cstep, sub_step, cont_step, dt, ctAlgo, hecMESH, fstrSOLID, infoCTChange, B )
212  integer(kind=kint), intent(in) :: cstep
213  integer(kind=kint), intent(in) :: sub_step
214  integer(kind=kint), intent(in) :: cont_step
215  real(kind=kreal), intent(in) :: dt
216  integer(kind=kint), intent(in) :: ctAlgo
217  type( hecmwst_local_mesh ), intent(in) :: hecMESH
218  type(fstr_solid), intent(inout) :: fstrSOLID
219  type(fstr_info_contactchange), intent(inout):: infoCTChange
220  ! logical, intent(inout) :: changed !< if contact state changed
221  real(kind=kreal), optional :: b(:)
222  character(len=9) :: flag_ctAlgo
223  integer(kind=kint) :: i, grpid
224  logical :: iactive, is_init
225 
226  if( associated( fstrsolid%CONT_RELVEL ) ) fstrsolid%CONT_RELVEL(:) = 0.d0
227  if( associated( fstrsolid%CONT_STATE ) ) fstrsolid%CONT_STATE(:) = 0.d0
228 
229  if( ctalgo == kcaslagrange ) then
230  flag_ctalgo = 'SLagrange'
231  elseif( ctalgo == kcaalagrange ) then
232  flag_ctalgo = 'ALagrange'
233  endif
234 
235  ! P.A. We redefine fstrSOLID%ddunode as current coordinate of every nodes
236  ! fstrSOLID%ddunode(:) = fstrSOLID%unode(:) + fstrSOLID%dunode(:)
237  do i = 1, size(fstrsolid%unode)
238  fstrsolid%ddunode(i) = hecmesh%node(i) + fstrsolid%unode(i) + fstrsolid%dunode(i)
239  enddo
240  active = .false.
241 
242  infoctchange%contact2free = 0
243  infoctchange%contact2neighbor = 0
244  infoctchange%contact2diffLpos = 0
245  infoctchange%free2contact = 0
246  infoctchange%contactNode_current = 0
247 
248  is_init = ( cstep == 1 .and. sub_step == 1 .and. cont_step == 0 )
249 
250  do i=1,fstrsolid%n_contacts
251  grpid = fstrsolid%contacts(i)%group
252  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) then
253  call clear_contact_state(fstrsolid%contacts(i)); cycle
254  endif
255  if( present(b) ) then
256  call scan_contact_state( flag_ctalgo, fstrsolid%contacts(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
257  & fstrsolid%QFORCE(:), infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive, mu, b )
258  else
259  call scan_contact_state( flag_ctalgo, fstrsolid%contacts(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
260  & fstrsolid%QFORCE(:), infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive, mu )
261  endif
262  if( .not. active ) active = iactive
263  enddo
264 
265  do i=1,fstrsolid%n_embeds
266  grpid = fstrsolid%embeds(i)%group
267  if( .not. fstr_isembedactive( fstrsolid, grpid, cstep ) ) then
268  call clear_contact_state(fstrsolid%embeds(i)); cycle
269  endif
270  call scan_embed_state( flag_ctalgo, fstrsolid%embeds(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
271  & fstrsolid%QFORCE(:), infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive, mu )
272  if( .not. active ) active = iactive
273  enddo
274 
275  if( is_init .and. ctalgo == kcaslagrange .and. fstrsolid%n_contacts > 0 ) &
276  & call remove_duplication_tiedcontact( cstep, hecmesh, fstrsolid, infoctchange )
277 
278  !for output contact state
279  do i=1,fstrsolid%n_contacts
280  call set_contact_state_vector( fstrsolid%contacts(i), dt, fstrsolid%CONT_RELVEL, fstrsolid%CONT_STATE )
281  enddo
282 
283  infoctchange%contactNode_current = infoctchange%contactNode_previous+infoctchange%free2contact-infoctchange%contact2free
284  infoctchange%contactNode_previous = infoctchange%contactNode_current
285 
286  if( .not. active ) then
287  if( associated( fstrsolid%CONT_NFORCE ) ) fstrsolid%CONT_NFORCE(:) = 0.d0
288  if( associated( fstrsolid%CONT_FRIC ) ) fstrsolid%CONT_FRIC(:) = 0.d0
289  end if
290 
291  end subroutine
292 
294  subroutine remove_duplication_tiedcontact( cstep, hecMESH, fstrSOLID, infoCTChange )
295  integer(kind=kint), intent(in) :: cstep
296  type( hecmwst_local_mesh ), intent(in) :: hecMESH
297  type(fstr_solid), intent(inout) :: fstrSOLID
298  type(fstr_info_contactchange), intent(inout):: infoCTChange
299 
300  integer(kind=kint) :: i, j, grpid, slave
301  integer(kind=kint) :: k, id, iSS
302  integer(kind=kint) :: ig0, ig, iS0, iE0
303  integer(kind=kint), allocatable :: states(:)
304 
305  allocate(states(hecmesh%n_node))
306  states(:) = contactfree
307 
308  ! if a boundary condition is given, the slave
309  do ig0= 1, fstrsolid%BOUNDARY_ngrp_tot
310  grpid = fstrsolid%BOUNDARY_ngrp_GRPID(ig0)
311  if( .not. fstr_isboundaryactive( fstrsolid, grpid, cstep ) ) cycle
312  ig= fstrsolid%BOUNDARY_ngrp_ID(ig0)
313  is0= hecmesh%node_group%grp_index(ig-1) + 1
314  ie0= hecmesh%node_group%grp_index(ig )
315  do k= is0, ie0
316  iss = hecmesh%node_group%grp_item(k)
317  !states(iSS) = CONTACTSTICK
318  enddo
319  enddo
320 
321  do i=1,fstrsolid%n_contacts
322  if( fstrsolid%contacts(i)%algtype /= contacttied ) cycle
323  grpid = fstrsolid%contacts(i)%group
324  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
325 
326  do j=1, size(fstrsolid%contacts(i)%slave)
327  if( fstrsolid%contacts(i)%states(j)%state==contactfree ) cycle ! free
328  slave = fstrsolid%contacts(i)%slave(j)
329  if( states(slave) == contactfree ) then
330  states(slave) = fstrsolid%contacts(i)%states(j)%state
331  id = fstrsolid%contacts(i)%states(j)%surface
332  do k=1,size( fstrsolid%contacts(i)%master(id)%nodes )
333  iss = fstrsolid%contacts(i)%master(id)%nodes(k)
334  states(iss) = fstrsolid%contacts(i)%states(j)%state
335  enddo
336  else !found duplicate tied contact slave node
337  fstrsolid%contacts(i)%states(j)%state = contactfree
338  infoctchange%free2contact = infoctchange%free2contact - 1
339  write(*,'(A,i10,A,i6,A,i6,A)') "Node",hecmesh%global_node_ID(slave), &
340  " in rank",hecmw_comm_get_rank()," freed due to duplication"
341  endif
342  enddo
343  enddo
344 
345  end subroutine
346 
347 
349  subroutine fstr_scan_contact_state_exp( cstep, hecMESH, fstrSOLID, infoCTChange )
350  integer(kind=kint), intent(in) :: cstep
351  type( hecmwst_local_mesh ), intent(in) :: hecMESH
352  type(fstr_solid), intent(inout) :: fstrSOLID
353  type(fstr_info_contactchange), intent(inout) :: infoCTChange
354 
355  integer(kind=kint) :: i
356  logical :: iactive, is_init
357 
358 
359  ! P.A. We redefine fstrSOLID%ddunode as current coordinate of every nodes
360  ! fstrSOLID%ddunode(:) = fstrSOLID%unode(:) + fstrSOLID%dunode(:)
361  do i = 1, size(fstrsolid%unode)
362  fstrsolid%ddunode(i) = hecmesh%node(i) + fstrsolid%unode(i) + fstrsolid%dunode(i)
363  enddo
364  infoctchange%active = .false.
365 
366  infoctchange%contact2free = 0
367  infoctchange%contact2neighbor = 0
368  infoctchange%contact2diffLpos = 0
369  infoctchange%free2contact = 0
370  infoctchange%contactNode_current = 0
371 
372  is_init = ( cstep == 1 )
373 
374  do i=1,fstrsolid%n_contacts
375  ! grpid = fstrSOLID%contacts(i)%group
376  ! if( .not. fstr_isContactActive( fstrSOLID, grpid, cstep ) ) then
377  ! call clear_contact_state(fstrSOLID%contacts(i)); cycle
378  ! endif
379 
380  call scan_contact_state_exp( fstrsolid%contacts(i), fstrsolid%ddunode(:), fstrsolid%dunode(:), &
381  & infoctchange, hecmesh%global_node_ID(:), hecmesh%global_elem_ID(:), is_init, iactive )
382 
383  infoctchange%active = infoctchange%active .or. iactive
384  enddo
385 
386  infoctchange%contactNode_current = infoctchange%contactNode_previous+infoctchange%free2contact-infoctchange%contact2free
387  infoctchange%contactNode_previous = infoctchange%contactNode_current
388  fstrsolid%ddunode = 0.d0
389  end subroutine
390 
392  subroutine fstr_update_contact0( hecMESH, fstrSOLID, B )
393  type( hecmwst_local_mesh ), intent(in) :: hecMESH
394  type(fstr_solid), intent(inout) :: fstrSOLID
395  real(kind=kreal), intent(inout) :: b(:)
396 
397  integer(kind=kint) :: i, algtype
398 
399  do i=1, fstrsolid%n_contacts
400  ! if( contacts(i)%mpced ) cycle
401  algtype = fstrsolid%contacts(i)%algtype
402  if( algtype == contactsslid .or. algtype == contactfslid ) then
403  call calcu_contact_force0( fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:) &
404  , fstrsolid%dunode(:), fstrsolid%contacts(i)%fcoeff, mu, mut, b )
405  else if( algtype == contacttied ) then
406  call calcu_tied_force0( fstrsolid%contacts(i), fstrsolid%unode(:), fstrsolid%dunode(:), mu, b )
407  endif
408  enddo
409 
410  do i=1, fstrsolid%n_embeds
411  call calcu_tied_force0( fstrsolid%embeds(i), fstrsolid%unode(:), fstrsolid%dunode(:), mu, b )
412  enddo
413 
414  end subroutine
415 
417  subroutine fstr_update_contact_multiplier( hecMESH, fstrSOLID, ctchanged )
418  type( hecmwst_local_mesh ), intent(in) :: hecMESH
419  type(fstr_solid), intent(inout) :: fstrSOLID
420  logical, intent(out) :: ctchanged
421 
422  integer(kind=kint) :: i, nc, algtype
423 
424  gnt = 0.d0; ctchanged = .false.
425  nc = fstrsolid%n_contacts+fstrsolid%n_embeds
426  do i=1, fstrsolid%n_contacts
427  algtype = fstrsolid%contacts(i)%algtype
428  if( algtype == contactsslid .or. algtype == contactfslid ) then
429  call update_contact_multiplier( fstrsolid%contacts(i), hecmesh%node(:), fstrsolid%unode(:) &
430  , fstrsolid%dunode(:), fstrsolid%contacts(i)%fcoeff, mu, mut, gnt, ctchanged )
431  else if( algtype == contacttied ) then
432  call update_tied_multiplier( fstrsolid%contacts(i), fstrsolid%unode(:), fstrsolid%dunode(:), &
433  & mu, ctchanged )
434  endif
435  enddo
436 
437  do i=1, fstrsolid%n_embeds
438  call update_tied_multiplier( fstrsolid%embeds(i), fstrsolid%unode(:), fstrsolid%dunode(:), &
439  & mu, ctchanged )
440  enddo
441 
442  if( nc>0 ) gnt = gnt/nc
443  end subroutine
444 
446  subroutine fstr_ass_load_contactalag( hecMESH, fstrSOLID, B )
447  type( hecmwst_local_mesh ), intent(in) :: hecMESH
448  type(fstr_solid), intent(inout) :: fstrSOLID
449  real(kind=kreal), intent(inout) :: b(:)
450 
451  integer(kind=kint) :: i, algtype
452 
453  do i = 1, fstrsolid%n_contacts
454  algtype = fstrsolid%contacts(i)%algtype
455  if( algtype == contactsslid .or. algtype == contactfslid ) then
456  call ass_contact_force( fstrsolid%contacts(i), hecmesh%node, fstrsolid%unode, b )
457  else if( algtype == contacttied ) then
458  call calcu_tied_force0( fstrsolid%contacts(i), fstrsolid%unode(:), fstrsolid%dunode(:), mu, b )
459  endif
460  enddo
461 
462  do i = 1, fstrsolid%n_embeds
463  call calcu_tied_force0( fstrsolid%embeds(i), fstrsolid%unode(:), fstrsolid%dunode(:), mu, b )
464  enddo
465  end subroutine
466 
468  subroutine fstr_update_contact_tangentforce( fstrSOLID )
469  type(fstr_solid), intent(inout) :: fstrSOLID
470 
471  integer(kind=kint) :: i
472 
473  do i=1, fstrsolid%n_contacts
474  call update_contact_tangentforce( fstrsolid%contacts(i) )
475  enddo
476  end subroutine
477 
479  subroutine fstr_contactbc( cstep, iter, hecMESH, hecMAT, fstrSOLID )
481  integer(kind=kint) :: cstep
482  integer(kind=kint), intent(in) :: iter
483  type (hecmwST_local_mesh), intent(inout) :: hecMESH
484  type (hecmwST_matrix), intent(inout) :: hecMAT
485  type(fstr_solid), intent(inout) :: fstrSOLID
486 
487  integer(kind=kint), parameter :: NDOF=3
488 
489  integer(kind=kint) :: i, j, k, m, nnode, nd, etype, grpid
490  integer(kind=kint) :: ctsurf, ndLocal(l_max_surface_node+1)
491  integer(kind=kint) :: algtype
492  real(kind=kreal) :: factor, elecoord( 3, l_max_surface_node)
493  real(kind=kreal) :: stiff(l_max_surface_node*3+3, l_max_surface_node*3+3)
494  real(kind=kreal) :: nrlforce, force(l_max_surface_node*3+3)
495 
496  factor = fstrsolid%FACTOR(2)
497 
498  do i=1,fstrsolid%n_contacts
499 
500  grpid = fstrsolid%contacts(i)%group
501  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
502 
503  algtype = fstrsolid%contacts(i)%algtype
504 
505  do j=1, size(fstrsolid%contacts(i)%slave)
506  if( fstrsolid%contacts(i)%states(j)%state==contactfree ) cycle ! free
507  ctsurf = fstrsolid%contacts(i)%states(j)%surface ! contacting surface
508  etype = fstrsolid%contacts(i)%master(ctsurf)%etype
509  nnode = size(fstrsolid%contacts(i)%master(ctsurf)%nodes)
510  ndlocal(1) = fstrsolid%contacts(i)%slave(j)
511  do k=1,nnode
512  ndlocal(k+1) = fstrsolid%contacts(i)%master(ctsurf)%nodes(k)
513  elecoord(1:3,k)=hecmesh%node(3*ndlocal(k+1)-2:3*ndlocal(k+1))
514  enddo
515  if( algtype == contactsslid .or. algtype == contactfslid ) then
516  call contact2stiff( algtype, fstrsolid%contacts(i)%states(j), &
517  etype, nnode, elecoord(:,:), mu, mut, fstrsolid%contacts(i)%fcoeff, &
518  fstrsolid%contacts(i)%symmetric, stiff(:,:), force(:) )
519  else if( algtype == contacttied ) then
520  call tied2stiff( algtype, fstrsolid%contacts(i)%states(j), &
521  etype, nnode, mu, mut, stiff(:,:), force(:) )
522  endif
523  ! ----- CONSTRUCT the GLOBAL MATRIX STARTED
524  call hecmw_mat_ass_elem(hecmat, nnode+1, ndlocal, stiff)
525 
526  if( iter>1 ) cycle
527  ! if( fstrSOLID%contacts(i)%states(j)%multiplier(1)/=0.d0 ) cycle
528  ! In case of new contact nodes, add enforced disp constraint
529  fstrsolid%contacts(i)%states(j)%wkdist = fstrsolid%contacts(i)%states(j)%distance
530  nrlforce = -mu*fstrsolid%contacts(i)%states(j)%distance
531  force(1:nnode*ndof+ndof) = force(1:nnode*ndof+ndof)*nrlforce
532  do m=1,nnode+1
533  nd = ndlocal(m)
534  do k=1,ndof
535  hecmat%B(ndof*(nd-1)+k)=hecmat%B(ndof*(nd-1)+k)-force((m-1)*ndof+k)
536  enddo
537  enddo
538 
539  enddo
540  enddo
541 
542  do i=1,fstrsolid%n_embeds
543  grpid = fstrsolid%embeds(i)%group
544  if( .not. fstr_iscontactactive( fstrsolid, grpid, cstep ) ) cycle
545  do j=1, size(fstrsolid%embeds(i)%slave)
546  if( fstrsolid%embeds(i)%states(j)%state==contactfree ) cycle ! free
547  ctsurf = fstrsolid%embeds(i)%states(j)%surface ! contacting surface
548  etype = fstrsolid%embeds(i)%master(ctsurf)%etype
549  nnode = size(fstrsolid%embeds(i)%master(ctsurf)%nodes)
550  ndlocal(1) = fstrsolid%embeds(i)%slave(j)
551  do k=1,nnode
552  ndlocal(k+1) = fstrsolid%embeds(i)%master(ctsurf)%nodes(k)
553  elecoord(1:3,k)=hecmesh%node(3*ndlocal(k+1)-2:3*ndlocal(k+1))
554  enddo
555  call tied2stiff( algtype, fstrsolid%embeds(i)%states(j), &
556  etype, nnode, mu, mut, stiff(:,:), force(:) )
557  ! ----- CONSTRUCT the GLOBAL MATRIX STARTED
558  call hecmw_mat_ass_elem(hecmat, nnode+1, ndlocal, stiff)
559  enddo
560  enddo
561 
562  end subroutine
563 
564  subroutine initialize_contact_output_vectors(fstrSOLID,hecMAT)
565  type(fstr_solid) :: fstrsolid
566  type(hecmwst_matrix) :: hecMAT
567 
568  if( .not. associated(fstrsolid%CONT_NFORCE) ) then
569  allocate( fstrsolid%CONT_NFORCE(hecmat%NP*3) )
570  fstrsolid%CONT_NFORCE(:) = 0.d0
571  end if
572 
573  if( .not. associated(fstrsolid%CONT_FRIC) ) then
574  allocate( fstrsolid%CONT_FRIC(hecmat%NP*3) )
575  fstrsolid%CONT_FRIC(:) = 0.d0
576  end if
577 
578  if( .not. associated(fstrsolid%CONT_RELVEL) ) then
579  allocate( fstrsolid%CONT_RELVEL(hecmat%NP*3) )
580  fstrsolid%CONT_RELVEL(:) = 0.d0
581  end if
582 
583  if( .not. associated(fstrsolid%CONT_STATE) ) then
584  allocate( fstrsolid%CONT_STATE(hecmat%NP*1) )
585  fstrsolid%CONT_STATE(:) = 0.d0
586  end if
587 
588  if( .not. associated(fstrsolid%CONT_AREA) ) then
589  allocate( fstrsolid%CONT_AREA(hecmat%NP) )
590  fstrsolid%CONT_AREA(:) = 0.d0
591  end if
592 
593  if( .not. associated(fstrsolid%CONT_NTRAC) ) then
594  allocate( fstrsolid%CONT_NTRAC(hecmat%NP*3) )
595  fstrsolid%CONT_NTRAC(:) = 0.d0
596  end if
597 
598  if( .not. associated(fstrsolid%CONT_FTRAC) ) then
599  allocate( fstrsolid%CONT_FTRAC(hecmat%NP*3) )
600  fstrsolid%CONT_FTRAC(:) = 0.d0
601  end if
602 
603  end subroutine
604 
605  subroutine initialize_embed_vectors(fstrSOLID,hecMAT)
606  type(fstr_solid) :: fstrSOLID
607  type(hecmwst_matrix) :: hecMAT
608 
609  if( .not. associated(fstrsolid%EMBED_NFORCE) ) then
610  allocate( fstrsolid%EMBED_NFORCE(hecmat%NP*3) )
611  fstrsolid%EMBED_NFORCE(:) = 0.d0
612  end if
613  end subroutine
614 
615  subroutine setup_contact_elesurf_for_area( cstep, hecMESH, fstrSOLID )
616  integer(kind=kint), intent(in) :: cstep
617  type( hecmwst_local_mesh ), intent(in) :: hecMESH
618  type(fstr_solid), intent(inout) :: fstrSOLID
619 
620  integer(kind=kint) :: i, j, k, sgrp_id, iS, iE, eid, sid, n_cdsurfs
621  logical, pointer :: cdef_surf(:,:)
622  real(kind=kreal), pointer :: coord(:)
623 
624  if( associated(fstrsolid%CONT_SGRP_ID) ) deallocate(fstrsolid%CONT_SGRP_ID)
625 
626  allocate(cdef_surf(l_max_elem_surf,hecmesh%n_elem))
627  cdef_surf(:,:) = .false.
628 
629  ! label contact defined surfaces
630  n_cdsurfs = 0
631  do i=1, fstrsolid%n_contacts
632  !grpid = fstrSOLID%contacts(i)%group
633  !if( .not. fstr_isContactActive( fstrSOLID, grpid, cstep ) ) then
634  ! call clear_contact_state(fstrSOLID%contacts(i)); cycle
635  !endif
636 
637  do k=1,2 !slave,master
638  if( k==1 ) then !slave
639  sgrp_id = fstrsolid%contacts(i)%surf_id1_sgrp
640  else if( k==2 ) then !master
641  sgrp_id = fstrsolid%contacts(i)%surf_id2
642  end if
643 
644  if( sgrp_id <= 0 ) cycle
645 
646  is = hecmesh%surf_group%grp_index(sgrp_id-1) + 1
647  ie = hecmesh%surf_group%grp_index(sgrp_id )
648  do j=is,ie
649  eid = hecmesh%surf_group%grp_item(2*j-1)
650  sid = hecmesh%surf_group%grp_item(2*j)
651  ! only internal and boundary element should be added
652  if( .not. cdef_surf(sid,eid) ) n_cdsurfs = n_cdsurfs + 1
653  cdef_surf(sid,eid) = .true.
654  enddo
655  end do
656  enddo
657 
658  !gather info of contact defined surfaces
659  allocate(fstrsolid%CONT_SGRP_ID(2*n_cdsurfs))
660  n_cdsurfs = 0
661  do i=1,hecmesh%n_elem
662  do j=1,l_max_elem_surf
663  if( cdef_surf(j,i) ) then
664  n_cdsurfs = n_cdsurfs + 1
665  fstrsolid%CONT_SGRP_ID(2*n_cdsurfs-1) = i
666  fstrsolid%CONT_SGRP_ID(2*n_cdsurfs ) = j
667  endif
668  end do
669  end do
670  deallocate(cdef_surf)
671 
672  end subroutine
673 
674  subroutine calc_contact_area( hecMESH, fstrSOLID, flag )
675  type( hecmwst_local_mesh ), intent(in) :: hecmesh
676  type(fstr_solid), intent(inout) :: fstrSOLID
677  integer(kind=kint), intent(in) :: flag
678 
679  integer(kind=kint), parameter :: NDOF=3
680  integer(kind=kint) :: i, isuf, icel, sid, etype, nn, iS, stype, idx
681  integer(kind=kint) :: ndlocal(l_max_elem_node)
682  real(kind=kreal), pointer :: coord(:)
683  real(kind=kreal) :: ecoord(ndof,l_max_elem_node), vect(l_max_elem_node)
684 
685  fstrsolid%CONT_AREA(:) = 0.d0
686 
687  if( .not. associated(fstrsolid%CONT_SGRP_ID) ) return
688 
689  allocate(coord(ndof*hecmesh%n_node))
690  do i=1,ndof*hecmesh%n_node
691  coord(i) = hecmesh%node(i)+fstrsolid%unode(i)
692  end do
693  if( flag == 1 ) then
694  do i=1,ndof*hecmesh%n_node
695  coord(i) = coord(i)+fstrsolid%dunode(i)
696  end do
697  end if
698 
699  do isuf=1,size(fstrsolid%CONT_SGRP_ID)/2
700  icel = fstrsolid%CONT_SGRP_ID(2*isuf-1)
701  sid = fstrsolid%CONT_SGRP_ID(2*isuf )
702 
703  etype = hecmesh%elem_type(icel)
704  nn = hecmw_get_max_node(etype)
705  is = hecmesh%elem_node_index(icel-1)
706  ndlocal(1:nn) = hecmesh%elem_node_item (is+1:is+nn)
707 
708  do i=1,nn
709  idx = ndof*(ndlocal(i)-1)
710  ecoord(1:ndof,i) = coord(idx+1:idx+ndof)
711  end do
712 
713  call calc_nodalarea_surfelement( etype, nn, ecoord, sid, vect )
714 
715  do i=1,nn
716  idx = ndlocal(i)
717  fstrsolid%CONT_AREA(idx) = fstrsolid%CONT_AREA(idx) + vect(i)
718  end do
719 
720  end do
721 
722  deallocate(coord)
723  end subroutine
724 
725  subroutine calc_nodalarea_surfelement( etype, nn, ecoord, sid, vect )
726  integer(kind=kint), intent(in) :: etype
727  integer(kind=kint), intent(in) :: nn
728  real(kind=kreal), intent(in) :: ecoord(:,:)
729  integer(kind=kint), intent(in) :: sid
730  real(kind=kreal), intent(out) :: vect(:)
731 
732  integer(kind=kint), parameter :: NDOF=3
733  integer(kind=kint) :: nod(l_max_surface_node)
734  integer(kind=kint) :: nsur, stype, ig0, i
735  real(kind=kreal) :: localcoord(2), normal(3), area, wg
736  real(kind=kreal) :: scoord(ndof,l_max_surface_node), h(l_max_surface_node)
737 
738  vect(:) = 0.d0
739 
740  call getsubface( etype, sid, stype, nod )
741  nsur = getnumberofnodes( stype )
742  do i=1,nsur
743  scoord(1:ndof,i) = ecoord(1:ndof,nod(i))
744  end do
745 
746  area = 0.d0
747  do ig0=1,numofquadpoints( stype )
748  call getquadpoint( stype, ig0, localcoord(1:2) )
749  call getshapefunc( stype, localcoord(1:2), h(1:nsur) )
750 
751  wg=getweight( stype, ig0 )
752  ! normal = dx/dr_1 \times dx/dr_2
753  normal(1:3) = surfacenormal( stype, nsur, localcoord(1:2), scoord(1:ndof,1:nsur) )
754  area = area + dsqrt(dot_product(normal,normal))*wg
755  enddo
756  area = area/dble(nsur)
757  do i=1,nsur
758  vect(nod(i)) = area
759  end do
760 
761  end subroutine
762 
763  subroutine fstr_setup_parancon_contactvalue(hecMESH,ndof,vec,vtype)
764  use m_fstr
765  implicit none
766  type(hecmwst_local_mesh), intent(in) :: hecmesh
767  integer(kind=kint), intent(in) :: ndof
768  real(kind=kreal), pointer, intent(inout) :: vec(:)
769  integer(kind=kint), intent(in) :: vtype !1:value, 2:state
770  !
771  real(kind=kreal) :: rhsb
772  integer(kind=kint) :: i,j,n,i0,n_loc,nndof
773  integer(kind=kint) :: offset, pid, lid
774  integer(kind=kint), allocatable :: displs(:)
775  real(kind=kreal), allocatable :: vec_all(:)
776 
777  !
778  n_loc = hecmesh%nn_internal
779  allocate(displs(0:nprocs))
780  displs(:) = 0
781  displs(myrank+1) = n_loc
782  call hecmw_allreduce_i(hecmesh, displs, nprocs+1, hecmw_sum)
783  do i=1,nprocs
784  displs(i) = displs(i-1) + displs(i)
785  end do
786  offset = displs(myrank)
787  n = displs(nprocs)
788 
789  allocate(vec_all(ndof*n))
790 
791  if( vtype == 1 ) then
792  vec_all(:) = 0.d0
793  do i= hecmesh%nn_internal+1,hecmesh%n_node
794  pid = hecmesh%node_ID(i*2)
795  lid = hecmesh%node_ID(i*2-1)
796  i0 = (displs(pid) + (lid-1))*ndof
797  vec_all(i0+1:i0+ndof) = vec((i-1)*ndof+1:i*ndof)
798  vec((i-1)*ndof+1:i*ndof) = 0.d0
799  enddo
800 
801  call hecmw_allreduce_r(hecmesh, vec_all, n*ndof, hecmw_sum)
802 
803  do i=1,ndof*n_loc
804  vec(i) = vec(i) + vec_all(offset*ndof+i)
805  end do
806  else if( vtype == 2 ) then
807  vec_all(:) = -1000.d0
808  do i= hecmesh%nn_internal+1,hecmesh%n_node
809  if( vec(i) == 0.d0 ) cycle
810  pid = hecmesh%node_ID(i*2)
811  lid = hecmesh%node_ID(i*2-1)
812  i0 = displs(pid) + lid
813  vec_all(i0) = vec(i)
814  enddo
815 
816  call hecmw_allreduce_r(hecmesh, vec_all, n, hecmw_max)
817 
818  do i=1,n_loc
819  if( vec_all(offset+i) == -1000.d0 ) cycle
820  if( vec(i) < vec_all(offset+i) ) vec(i) = vec_all(offset+i)
821  end do
822  end if
823 
824  deallocate(displs,vec_all)
825  end subroutine
826 
827 end module mcontact
fstr_ctrl_modifier
This module provides functions to modify MPC conditions.
Definition: fstr_ctrl_modifier.f90:6
mcontact::mu
real(kind=kreal), save mu
penalty, default value
Definition: fstr_contact.f90:17
mcontact::fstr_scan_contact_state
subroutine fstr_scan_contact_state(cstep, sub_step, cont_step, dt, ctAlgo, hecMESH, fstrSOLID, infoCTChange, B)
Scanning contact state.
Definition: fstr_contact.f90:212
mcontactdef::tcontact
Structure to includes all info needed by contact calculation.
Definition: fstr_contact_def.F90:26
mcontact::cgn
real(kind=kreal), save cgn
convergent condition of penetration
Definition: fstr_contact.f90:21
mcontactdef::update_contact_multiplier
subroutine update_contact_multiplier(contact, coord, disp, ddisp, fcoeff, mu, mut, gnt, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
Definition: fstr_contact_def.F90:1248
mcontact::initialize_embed_vectors
subroutine initialize_embed_vectors(fstrSOLID, hecMAT)
Definition: fstr_contact.f90:606
mcontact::fstr_contact2mpc
subroutine fstr_contact2mpc(contacts, mpcs)
Contact states to equation conditions.
Definition: fstr_contact.f90:165
m_fstr::myrank
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.f90:96
mcontactdef
This module manages the data structure for contact calculation.
Definition: fstr_contact_def.F90:12
mcontactdef::scan_embed_state
subroutine scan_embed_state(flag_ctAlgo, embed, currpos, currdisp, ndforce, infoCTChange, nodeID, elemID, is_init, active, mu, B)
This subroutine update contact states, which include.
Definition: fstr_contact_def.F90:602
mcontactdef::calcu_tied_force0
subroutine calcu_tied_force0(contact, disp, ddisp, mu, B)
This subroutine updates contact condition as follows:
Definition: fstr_contact_def.F90:1200
mcontact::calc_nodalarea_surfelement
subroutine calc_nodalarea_surfelement(etype, nn, ecoord, sid, vect)
Definition: fstr_contact.f90:726
mcontact::setup_contact_elesurf_for_area
subroutine setup_contact_elesurf_for_area(cstep, hecMESH, fstrSOLID)
Definition: fstr_contact.f90:616
mcontactdef::ass_contact_force
subroutine ass_contact_force(contact, coord, disp, B)
This subroutine assemble contact force into contacing nodes.
Definition: fstr_contact_def.F90:1381
mcontactdef::scan_contact_state
subroutine scan_contact_state(flag_ctAlgo, contact, currpos, currdisp, ndforce, infoCTChange, nodeID, elemID, is_init, active, mu, B)
This subroutine update contact states, which include.
Definition: fstr_contact_def.F90:416
mcontact::remove_duplication_tiedcontact
subroutine remove_duplication_tiedcontact(cstep, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
Definition: fstr_contact.f90:295
m_fstr::fstr_solid
Definition: m_fstr.f90:238
mcontact::cdotp
real(kind=kreal), save cdotp
mu=cdotp*maxval
Definition: fstr_contact.f90:19
m_fstr::fstr_iscontactactive
logical function fstr_iscontactactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.f90:1052
mcontact::bakgnt
real(kind=kreal), dimension(2), save bakgnt
1:current average penetration; 2:current relative tangent displacement!
Definition: fstr_contact.f90:26
mcontact::fstr_contactbc
subroutine fstr_contactbc(cstep, iter, hecMESH, hecMAT, fstrSOLID)
Introduce contact stiff into global stiff matrix or mpc conditions into hecMESH.
Definition: fstr_contact.f90:480
fstr_ctrl_modifier::fstr_append_mpc
subroutine fstr_append_mpc(np, nodes, dofs, values, mpcs)
Append new equation condition at end of existing mpc conditions.
Definition: fstr_ctrl_modifier.f90:16
mcontactdef::update_tied_multiplier
subroutine update_tied_multiplier(contact, disp, ddisp, mu, ctchanged)
This subroutine update lagrangian multiplier and the distance between contacting nodes.
Definition: fstr_contact_def.F90:1332
mcontact::fstr_update_contact0
subroutine fstr_update_contact0(hecMESH, fstrSOLID, B)
Update lagrangian multiplier.
Definition: fstr_contact.f90:393
mcontact::fstr_is_matrixstructure_changed
logical function fstr_is_matrixstructure_changed(infoCTChange)
Definition: fstr_contact.f90:82
fstr_ctrl_modifier::fstr_delete_mpc
subroutine fstr_delete_mpc(np, mpcs)
Delete last n equation conditions from current mpc condition.
Definition: fstr_ctrl_modifier.f90:45
m_fstr::kcaalagrange
integer(kind=kint), parameter kcaalagrange
Definition: m_fstr.f90:60
mcontact::fstr_set_contact_penalty
subroutine fstr_set_contact_penalty(maxv)
Definition: fstr_contact.f90:45
m_fstr::dt
real(kind=kreal) dt
ANALYSIS CONTROL for NLGEOM and HEAT.
Definition: m_fstr.f90:139
mcontactdef::fstr_info_contactchange
Definition: fstr_contact_def.F90:59
m_fstr::fstr_isboundaryactive
logical function fstr_isboundaryactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.f90:1028
m_fstr::kcaslagrange
integer(kind=kint), parameter kcaslagrange
contact analysis algorithm
Definition: m_fstr.f90:59
mcontact::fstr_setup_parancon_contactvalue
subroutine fstr_setup_parancon_contactvalue(hecMESH, ndof, vec, vtype)
Definition: fstr_contact.f90:764
mcontact::fstr_is_contact_conv
logical function fstr_is_contact_conv(ctAlgo, infoCTChange, hecMESH)
Definition: fstr_contact.f90:61
mcontactdef::scan_contact_state_exp
subroutine scan_contact_state_exp(contact, currpos, currdisp, infoCTChange, nodeID, elemID, is_init, active)
This subroutine update contact states, which include.
Definition: fstr_contact_def.F90:1585
m_fstr
This module defines common data and basic structures for analysis.
Definition: m_fstr.f90:15
m_fstr::nprocs
integer(kind=kint) nprocs
Definition: m_fstr.f90:97
mcontact::gnt
real(kind=kreal), dimension(2), save gnt
1:current average penetration; 2:current relative tangent displacement
Definition: fstr_contact.f90:24
mcontact::initialize_contact_output_vectors
subroutine initialize_contact_output_vectors(fstrSOLID, hecMAT)
Definition: fstr_contact.f90:565
mcontact::cgt
real(kind=kreal), save cgt
convergent condition of relative tangent disp
Definition: fstr_contact.f90:22
mcontact::fstr_is_contact_active
logical function fstr_is_contact_active()
Definition: fstr_contact.f90:52
hecmw
Definition: hecmw.f90:6
mcontact::fstr_ass_load_contactalag
subroutine fstr_ass_load_contactalag(hecMESH, fstrSOLID, B)
Update lagrangian multiplier.
Definition: fstr_contact.f90:447
mcontactdef::update_contact_tangentforce
subroutine update_contact_tangentforce(contact)
Definition: fstr_contact_def.F90:1455
mcontactdef::set_contact_state_vector
subroutine set_contact_state_vector(contact, dt, relvel_vec, state_vec)
This subroutine setup contact output nodal vectors.
Definition: fstr_contact_def.F90:1435
mcontact::n_contact_mpc
integer(kind=kint), save n_contact_mpc
Definition: fstr_contact.f90:14
mcontact::fstr_del_contactmpc
subroutine fstr_del_contactmpc(mpcs)
Delete mpcs derived from contact conditions.
Definition: fstr_contact.f90:187
mcontact::print_contatct_pair
subroutine print_contatct_pair(file, pair)
Write out the contact definition read from mesh file.
Definition: fstr_contact.f90:33
mcontactdef::clear_contact_state
subroutine clear_contact_state(contact)
Reset contact state all to free.
Definition: fstr_contact_def.F90:392
mcontactdef::calcu_contact_force0
subroutine calcu_contact_force0(contact, coord, disp, ddisp, fcoeff, mu, mut, B)
This subroutine updates contact condition as follows:
Definition: fstr_contact_def.F90:1126
mcontact::calc_contact_area
subroutine calc_contact_area(hecMESH, fstrSOLID, flag)
Definition: fstr_contact.f90:675
mcontact::mut
real(kind=kreal), save mut
penalty along tangent direction
Definition: fstr_contact.f90:18
mcontact::fstr_write_mpc
subroutine fstr_write_mpc(file, mpcs)
Print out mpc conditions.
Definition: fstr_contact.f90:194
mcontact::fstr_set_contact_active
subroutine fstr_set_contact_active(a)
Definition: fstr_contact.f90:56
mcontact::fstr_scan_contact_state_exp
subroutine fstr_scan_contact_state_exp(cstep, hecMESH, fstrSOLID, infoCTChange)
Scanning contact state.
Definition: fstr_contact.f90:350
m_fstr::fstr_isembedactive
logical function fstr_isembedactive(fstrSOLID, nbc, cstep)
Definition: m_fstr.f90:1062
mcontact::fstr_update_contact_multiplier
subroutine fstr_update_contact_multiplier(hecMESH, fstrSOLID, ctchanged)
Update lagrangian multiplier.
Definition: fstr_contact.f90:418
mcontact::fstr_update_contact_tangentforce
subroutine fstr_update_contact_tangentforce(fstrSOLID)
Update tangent force.
Definition: fstr_contact.f90:469
mcontact
This module provides functions to calculate contact stiff matrix.
Definition: fstr_contact.f90:6