FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
fstr_contact_output.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 !-------------------------------------------------------------------------------
12  use hecmw
13  use m_fstr
14  use mcontactdef
16  implicit none
17 
19  public :: initialize_embed_vectors
21  public :: calc_contact_area
24 
25  private :: calc_nodalarea_surfelement
26 
27 contains
28 
29  subroutine initialize_contact_output_vectors(fstrSOLID,hecMAT)
30  type(fstr_solid) :: fstrsolid
31  type(hecmwst_matrix) :: hecmat
32 
33  if( .not. associated(fstrsolid%CONT_NFORCE) ) then
34  allocate( fstrsolid%CONT_NFORCE(hecmat%NP*3) )
35  fstrsolid%CONT_NFORCE(:) = 0.d0
36  end if
37 
38  if( .not. associated(fstrsolid%CONT_FRIC) ) then
39  allocate( fstrsolid%CONT_FRIC(hecmat%NP*3) )
40  fstrsolid%CONT_FRIC(:) = 0.d0
41  end if
42 
43  if( .not. associated(fstrsolid%CONT_RELVEL) ) then
44  allocate( fstrsolid%CONT_RELVEL(hecmat%NP*3) )
45  fstrsolid%CONT_RELVEL(:) = 0.d0
46  end if
47 
48  if( .not. associated(fstrsolid%CONT_STATE) ) then
49  allocate( fstrsolid%CONT_STATE(hecmat%NP*1) )
50  fstrsolid%CONT_STATE(:) = 0.d0
51  end if
52 
53  if( .not. associated(fstrsolid%CONT_AREA) ) then
54  allocate( fstrsolid%CONT_AREA(hecmat%NP) )
55  fstrsolid%CONT_AREA(:) = 0.d0
56  end if
57 
58  if( .not. associated(fstrsolid%CONT_NTRAC) ) then
59  allocate( fstrsolid%CONT_NTRAC(hecmat%NP*3) )
60  fstrsolid%CONT_NTRAC(:) = 0.d0
61  end if
62 
63  if( .not. associated(fstrsolid%CONT_FTRAC) ) then
64  allocate( fstrsolid%CONT_FTRAC(hecmat%NP*3) )
65  fstrsolid%CONT_FTRAC(:) = 0.d0
66  end if
67 
68  end subroutine
69 
70  subroutine initialize_embed_vectors(fstrSOLID,hecMAT)
71  type(fstr_solid) :: fstrsolid
72  type(hecmwst_matrix) :: hecmat
73 
74  if( .not. associated(fstrsolid%EMBED_NFORCE) ) then
75  allocate( fstrsolid%EMBED_NFORCE(hecmat%NP*3) )
76  fstrsolid%EMBED_NFORCE(:) = 0.d0
77  end if
78  end subroutine
79 
80  subroutine setup_contact_elesurf_for_area( hecMESH, fstrSOLID )
81  type( hecmwst_local_mesh ), intent(in) :: hecmesh
82  type(fstr_solid), intent(inout) :: fstrsolid
83 
84  integer(kind=kint) :: i, j, k, sgrp_id, is, ie, eid, sid, n_cdsurfs
85  logical, pointer :: cdef_surf(:,:)
86 
87  if( associated(fstrsolid%CONT_SGRP_ID) ) deallocate(fstrsolid%CONT_SGRP_ID)
88 
89  allocate(cdef_surf(l_max_elem_surf,hecmesh%n_elem))
90  cdef_surf(:,:) = .false.
91 
92  ! label contact defined surfaces
93  n_cdsurfs = 0
94  do i=1, fstrsolid%n_contacts
95  !grpid = fstrSOLID%contacts(i)%group
96  !if( .not. fstr_isContactActive( fstrSOLID, grpid, cstep ) ) then
97  ! call clear_contact_state(fstrSOLID%contacts(i)); cycle
98  !endif
99 
100  do k=1,2 !slave,master
101  if( k==1 ) then !slave
102  sgrp_id = fstrsolid%contacts(i)%surf_id1_sgrp
103  else if( k==2 ) then !master
104  sgrp_id = fstrsolid%contacts(i)%surf_id2
105  end if
106 
107  if( sgrp_id <= 0 ) cycle
108 
109  is = hecmesh%surf_group%grp_index(sgrp_id-1) + 1
110  ie = hecmesh%surf_group%grp_index(sgrp_id )
111  do j=is,ie
112  eid = hecmesh%surf_group%grp_item(2*j-1)
113  sid = hecmesh%surf_group%grp_item(2*j)
114  ! only internal and boundary element should be added
115  if( .not. cdef_surf(sid,eid) ) n_cdsurfs = n_cdsurfs + 1
116  cdef_surf(sid,eid) = .true.
117  enddo
118  end do
119  enddo
120 
121  !gather info of contact defined surfaces
122  allocate(fstrsolid%CONT_SGRP_ID(2*n_cdsurfs))
123  n_cdsurfs = 0
124  do i=1,hecmesh%n_elem
125  do j=1,l_max_elem_surf
126  if( cdef_surf(j,i) ) then
127  n_cdsurfs = n_cdsurfs + 1
128  fstrsolid%CONT_SGRP_ID(2*n_cdsurfs-1) = i
129  fstrsolid%CONT_SGRP_ID(2*n_cdsurfs ) = j
130  endif
131  end do
132  end do
133  deallocate(cdef_surf)
134 
135  end subroutine
136 
137  subroutine calc_contact_area( hecMESH, fstrSOLID, flag )
138  type( hecmwst_local_mesh ), intent(in) :: hecmesh
139  type(fstr_solid), intent(inout) :: fstrsolid
140  integer(kind=kint), intent(in) :: flag
141 
142  integer(kind=kint), parameter :: ndof=3
143  integer(kind=kint) :: i, isuf, icel, sid, etype, nn, is, idx
144  integer(kind=kint) :: ndlocal(l_max_elem_node)
145  real(kind=kreal), allocatable :: coord(:)
146  real(kind=kreal) :: ecoord(ndof,l_max_elem_node), vect(l_max_elem_node)
147 
148  fstrsolid%CONT_AREA(:) = 0.d0
149 
150  if( .not. associated(fstrsolid%CONT_SGRP_ID) ) return
151 
152  allocate(coord(ndof*hecmesh%n_node))
153  do i=1,ndof*hecmesh%n_node
154  coord(i) = hecmesh%node(i)+fstrsolid%unode(i)
155  end do
156  if( flag == 1 ) then
157  do i=1,ndof*hecmesh%n_node
158  coord(i) = coord(i)+fstrsolid%dunode(i)
159  end do
160  end if
161 
162  do isuf=1,size(fstrsolid%CONT_SGRP_ID)/2
163  icel = fstrsolid%CONT_SGRP_ID(2*isuf-1)
164  sid = fstrsolid%CONT_SGRP_ID(2*isuf )
165 
166  etype = hecmesh%elem_type(icel)
167  nn = hecmw_get_max_node(etype)
168  is = hecmesh%elem_node_index(icel-1)
169  ndlocal(1:nn) = hecmesh%elem_node_item (is+1:is+nn)
170 
171  do i=1,nn
172  idx = ndof*(ndlocal(i)-1)
173  ecoord(1:ndof,i) = coord(idx+1:idx+ndof)
174  end do
175 
176  call calc_nodalarea_surfelement( etype, ecoord, sid, vect )
177 
178  do i=1,nn
179  idx = ndlocal(i)
180  fstrsolid%CONT_AREA(idx) = fstrsolid%CONT_AREA(idx) + vect(i)
181  end do
182 
183  end do
184 
185  deallocate(coord)
186  end subroutine
187 
188  subroutine calc_nodalarea_surfelement( etype, ecoord, sid, vect )
189  integer(kind=kint), intent(in) :: etype
190  real(kind=kreal), intent(in) :: ecoord(:,:)
191  integer(kind=kint), intent(in) :: sid
192  real(kind=kreal), intent(out) :: vect(:)
193 
194  integer(kind=kint), parameter :: ndof=3
195  integer(kind=kint) :: nod(l_max_surface_node)
196  integer(kind=kint) :: nsur, stype, ig0, i
197  real(kind=kreal) :: localcoord(2), normal(3), area, wg
198  real(kind=kreal) :: scoord(ndof,l_max_surface_node), h(l_max_surface_node)
199 
200  vect(:) = 0.d0
201 
202  call getsubface( etype, sid, stype, nod )
203  nsur = getnumberofnodes( stype )
204  do i=1,nsur
205  scoord(1:ndof,i) = ecoord(1:ndof,nod(i))
206  end do
207 
208  area = 0.d0
209  do ig0=1,numofquadpoints( stype )
210  call getquadpoint( stype, ig0, localcoord(1:2) )
211  call getshapefunc( stype, localcoord(1:2), h(1:nsur) )
212 
213  wg=getweight( stype, ig0 )
214  ! normal = dx/dr_1 \times dx/dr_2
215  normal(1:3) = surfacenormal( stype, nsur, localcoord(1:2), scoord(1:ndof,1:nsur) )
216  area = area + dsqrt(dot_product(normal,normal))*wg
217  enddo
218  area = area/dble(nsur)
219  do i=1,nsur
220  vect(nod(i)) = area
221  end do
222 
223  end subroutine
224 
225  subroutine fstr_setup_parancon_contactvalue(hecMESH,ndof,vec,vtype)
226  use m_fstr
227  implicit none
228  type(hecmwst_local_mesh), intent(in) :: hecmesh
229  integer(kind=kint), intent(in) :: ndof
230  real(kind=kreal), pointer, intent(inout) :: vec(:)
231  integer(kind=kint), intent(in) :: vtype !1:value, 2:state
232  !
233  integer(kind=kint) :: i,n,i0,n_loc
234  integer(kind=kint) :: offset, pid, lid
235  integer(kind=kint), allocatable :: displs(:)
236  real(kind=kreal), allocatable :: vec_all(:)
237 
238  !
239  n_loc = hecmesh%nn_internal
240  allocate(displs(0:nprocs))
241  displs(:) = 0
242  displs(myrank+1) = n_loc
243  call hecmw_allreduce_i(hecmesh, displs, nprocs+1, hecmw_sum)
244  do i=1,nprocs
245  displs(i) = displs(i-1) + displs(i)
246  end do
247  offset = displs(myrank)
248  n = displs(nprocs)
249 
250  allocate(vec_all(ndof*n))
251 
252  if( vtype == 1 ) then
253  vec_all(:) = 0.d0
254  do i= 1, hecmesh%n_node
255  pid = hecmesh%node_ID(i*2)
256  lid = hecmesh%node_ID(i*2-1)
257  i0 = (displs(pid) + (lid-1))*ndof
258  vec_all(i0+1:i0+ndof) = vec((i-1)*ndof+1:i*ndof)
259  vec((i-1)*ndof+1:i*ndof) = 0.d0
260  enddo
261 
262  call hecmw_allreduce_r(hecmesh, vec_all, n*ndof, hecmw_sum)
263  do i= 1, hecmesh%n_node
264  pid = hecmesh%node_ID(i*2)
265  lid = hecmesh%node_ID(i*2-1)
266  i0 = (displs(pid) + (lid-1))*ndof
267  if (dot_product(vec_all(i0+1:i0+ndof),vec_all(i0+1:i0+ndof)) == 0.d0) cycle
268  vec((i-1)*ndof+1:i*ndof) = vec_all(i0+1:i0+ndof)
269  enddo
270  do i=1,ndof*n_loc
271  vec(i) = vec_all(offset*ndof+i)
272  end do
273  else if( vtype == 2 ) then
274  vec_all(:) = -1000.d0
275  do i= 1, hecmesh%n_node
276  if( vec(i) == 0.d0 ) cycle
277  pid = hecmesh%node_ID(i*2)
278  lid = hecmesh%node_ID(i*2-1)
279  i0 = displs(pid) + lid
280  vec_all(i0) = vec(i)
281  enddo
282 
283  call hecmw_allreduce_r(hecmesh, vec_all, n, hecmw_max)
284  do i= 1, hecmesh%n_node
285  pid = hecmesh%node_ID(i*2)
286  lid = hecmesh%node_ID(i*2-1)
287  i0 = displs(pid) + lid
288  if(vec_all(i0) == -1000.d0) cycle
289  vec(i) = vec_all(i0)
290  enddo
291  end if
292 
293  deallocate(displs,vec_all)
294  end subroutine
295 
297  subroutine update_contact_state_vectors( contact, dt, relvel_vec, state_vec )
298  type( tcontact ), intent(in) :: contact
299  real(kind=kreal), intent(in) :: dt
300  real(kind=kreal), intent(inout) :: relvel_vec(:)
301  real(kind=kreal), intent(inout) :: state_vec(:)
302 
303  integer(kind=kint) :: i, j, slave
304 
305  if( contact%method == contacts2s ) then
306  ! MORTAR=YES: the contact state lives per integration point in slave_surf
307  ! (contact%slave is unused). Aggregate each segment's state onto its slave nodes
308  ! for nodal output, using the same convention as the NODE-SURF path (free nodes
309  ! show CONTACTFREE, active nodes show CONTACTSTICK/SLIP; max over segments
310  ! sharing a node).
311  do i = 1, size(contact%slave_surf)
312  do j = 1, size(contact%slave_surf(i)%nodes)
313  slave = contact%slave_surf(i)%nodes(j)
314  if( state_vec(slave) < 0.1d0 .or. contact%slave_surf(i)%state > 0 ) &
315  & state_vec(slave) = dble(contact%slave_surf(i)%state)
316  enddo
317  enddo
318  return
319  endif
320 
321  do i= 1, size(contact%slave)
322  slave = contact%slave(i)
323  if( state_vec(slave) < 0.1d0 .or. contact%states(i)%state > 0 ) &
324  & state_vec(slave) = dble(contact%states(i)%state)
325 
326  if( is_contact_free(contact%states(i)%state) ) cycle ! not in contact or near
327  if( dt < 1.d-16 ) cycle ! too small delta t
328  relvel_vec(3*slave-2:3*slave) = contact%states(i)%reldisp(1:3)/dt
329  enddo
330 
331  end subroutine update_contact_state_vectors
332 
333 end module m_fstr_contact_output
Definition: hecmw.f90:6
This module provides geometric calculations for contact.
Contact output vector processing (initialization, area calculation, parallel)
subroutine, public fstr_setup_parancon_contactvalue(hecMESH, ndof, vec, vtype)
subroutine, public setup_contact_elesurf_for_area(hecMESH, fstrSOLID)
subroutine, public calc_contact_area(hecMESH, fstrSOLID, flag)
subroutine, public initialize_contact_output_vectors(fstrSOLID, hecMAT)
subroutine, public initialize_embed_vectors(fstrSOLID, hecMAT)
subroutine, public update_contact_state_vectors(contact, dt, relvel_vec, state_vec)
Update contact state output vectors (CONT_RELVEL, CONT_STATE)
This module defines common data and basic structures for analysis.
Definition: m_fstr.F90:15
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.F90:107
integer(kind=kint) nprocs
Definition: m_fstr.F90:108
This module manages the data structure for contact calculation.
integer, parameter contacts2s
pure logical function is_contact_free(state)
Whether the contact state is completely free (no projection info)
Structure to includes all info needed by contact calculation.