FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_comm_contact_f.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 !-------------------------------------------------------------------------------
5 
7 
8  use hecmw_util
10 
11  implicit none
12 
13  private
14  public :: hecmwst_contact_comm
15  public :: hecmw_contact_comm_init
22 
23  type hecmwst_contact_comm
24  private
25  integer(kind=kint) :: n_neighbor_pe
26  integer(kind=kint), pointer :: neighbor_pe(:)
27  integer(kind=kint) :: MPI_COMM
28  integer(kind=kint), pointer :: ext_index(:)
29  integer(kind=kint), pointer :: ext_item(:)
30  integer(kind=kint), pointer :: int_index(:)
31  integer(kind=kint), pointer :: int_item(:)
32  end type hecmwst_contact_comm
33 
34  integer(kind=kint), parameter :: op_overwrite = 46810
35 
36  integer(kind=kint), parameter :: DBG = 0
37 
38 contains
39 
40  subroutine hecmw_contact_comm_init(conComm, hecMESH, ndof, n_contact_dof, contact_dofs)
41  implicit none
42  type (hecmwst_contact_comm), intent(inout) :: concomm
43  type (hecmwst_local_mesh), intent(in) :: hecmesh
44  integer(kind=kint), intent(in) :: ndof, n_contact_dof
45  integer(kind=kint), intent(in) :: contact_dofs(:)
46  integer(kind=kint), pointer :: ext_index(:), ext_item(:), int_index(:), int_item(:)
47  integer(kind=kint), allocatable :: n_ext_per_dom(:), n_int_per_dom(:), ext_item_remote(:)
48  integer(kind=kint), allocatable :: statuses(:,:), requests(:)
49  integer(kind=kint) :: nn_int, np, ilag, icontact, irow, irank, idom, tag, idof, idx, irow_remote
50  integer(kind=kint) :: n_send, is, ie, len
51  if (hecmesh%n_neighbor_pe == 0) then
52  concomm%n_neighbor_pe = 0
53  return
54  endif
55  nn_int = hecmesh%nn_internal
56  np = hecmesh%n_node
57  ! count external contact dofs
58  allocate(n_ext_per_dom(hecmesh%n_neighbor_pe))
59  n_ext_per_dom(:) = 0
60  do ilag = 1, n_contact_dof
61  icontact = contact_dofs(ilag)
62  if (icontact <= nn_int*ndof) cycle ! skip internal contact dof
63  irow = (icontact+ndof-1) / ndof
64  irank = hecmesh%node_ID(2*irow)
65  call rank_to_idom(hecmesh, irank, idom)
66  n_ext_per_dom(idom) = n_ext_per_dom(idom) + 1
67  enddo
68  ! send external / recv internal contact dofs
69  allocate(statuses(hecmw_status_size, hecmesh%n_neighbor_pe))
70  allocate(requests(hecmesh%n_neighbor_pe))
71  do idom = 1, hecmesh%n_neighbor_pe
72  irank = hecmesh%neighbor_pe(idom)
73  tag = 5001
74  call hecmw_isend_int(n_ext_per_dom(idom), 1, irank, tag, &
75  hecmesh%MPI_COMM, requests(idom))
76  enddo
77  allocate(n_int_per_dom(hecmesh%n_neighbor_pe))
78  do idom = 1, hecmesh%n_neighbor_pe
79  irank = hecmesh%neighbor_pe(idom)
80  tag = 5001
81  call hecmw_recv_int(n_int_per_dom(idom), 1, irank, tag, &
82  hecmesh%MPI_COMM, statuses(:,1))
83  enddo
84  call hecmw_waitall(hecmesh%n_neighbor_pe, requests, statuses)
85  ! make index
86  allocate(ext_index(0:hecmesh%n_neighbor_pe))
87  allocate(int_index(0:hecmesh%n_neighbor_pe))
88  ext_index(0) = 0
89  int_index(0) = 0
90  do idom = 1, hecmesh%n_neighbor_pe
91  ext_index(idom) = ext_index(idom-1) + n_ext_per_dom(idom)
92  int_index(idom) = int_index(idom-1) + n_int_per_dom(idom)
93  enddo
94  ! make ext_item
95  allocate(ext_item(ext_index(hecmesh%n_neighbor_pe)))
96  allocate(ext_item_remote(ext_index(hecmesh%n_neighbor_pe)))
97  n_ext_per_dom(:) = 0
98  do ilag = 1, n_contact_dof
99  icontact = contact_dofs(ilag)
100  if (icontact <= nn_int*ndof) cycle ! skip internal contact dof
101  irow = (icontact+ndof-1) / ndof
102  idof = icontact - ndof*(irow-1)
103  irank = hecmesh%node_ID(2*irow)
104  call rank_to_idom(hecmesh, irank, idom)
105  n_ext_per_dom(idom) = n_ext_per_dom(idom) + 1
106  idx = ext_index(idom-1)+n_ext_per_dom(idom)
107  ext_item(idx) = icontact
108  irow_remote = hecmesh%node_ID(2*irow-1)
109  ext_item_remote(idx) = ndof*(irow_remote-1)+idof
110  enddo
111  deallocate(n_ext_per_dom)
112  deallocate(n_int_per_dom)
113  ! send ext_item_remote and recv int_item
114  n_send = 0
115  do idom = 1, hecmesh%n_neighbor_pe
116  irank = hecmesh%neighbor_pe(idom)
117  is = ext_index(idom-1)+1
118  ie = ext_index(idom)
119  len = ie-is+1
120  if (len == 0) cycle
121  n_send = n_send + 1
122  tag = 5002
123  call hecmw_isend_int(ext_item_remote(is:ie), len, irank, tag, &
124  hecmesh%MPI_COMM, requests(n_send))
125  enddo
126  allocate(int_item(int_index(hecmesh%n_neighbor_pe)))
127  do idom = 1, hecmesh%n_neighbor_pe
128  irank = hecmesh%neighbor_pe(idom)
129  is = int_index(idom-1)+1
130  ie = int_index(idom)
131  len = ie-is+1
132  if (len == 0) cycle
133  tag = 5002
134  call hecmw_recv_int(int_item(is:ie), len, irank, tag, &
135  hecmesh%MPI_COMM, statuses(:,1))
136  enddo
137  call hecmw_waitall(n_send, requests, statuses)
138  deallocate(statuses, requests)
139  if (dbg >= 2) then
140  write(0,*) ' DEBUG2: ext_index',ext_index(:)
141  write(0,*) ' DEBUG2: ext_item',ext_item(:)
142  write(0,*) ' DEBUG2: ext_item_remote',ext_item_remote(:)
143  write(0,*) ' DEBUG2: int_index',int_index(:)
144  write(0,*) ' DEBUG2: int_item',int_item(:)
145  endif
146  deallocate(ext_item_remote)
147  !
148  concomm%n_neighbor_pe = hecmesh%n_neighbor_pe
149  allocate(concomm%neighbor_pe(concomm%n_neighbor_pe))
150  concomm%neighbor_pe(:) = hecmesh%neighbor_pe(:)
151  concomm%MPI_COMM = hecmesh%MPI_COMM
152  concomm%ext_index => ext_index
153  concomm%ext_item => ext_item
154  concomm%int_index => int_index
155  concomm%int_item => int_item
156  end subroutine hecmw_contact_comm_init
157 
158  subroutine hecmw_contact_comm_finalize(conComm)
159  implicit none
160  type (hecmwst_contact_comm), intent(inout) :: concomm
161  if (concomm%n_neighbor_pe == 0) return
162  if (associated(concomm%neighbor_pe)) deallocate(concomm%neighbor_pe)
163  if (associated(concomm%ext_index)) deallocate(concomm%ext_index)
164  if (associated(concomm%ext_item)) deallocate(concomm%ext_item)
165  if (associated(concomm%int_index)) deallocate(concomm%int_index)
166  if (associated(concomm%int_item)) deallocate(concomm%int_item)
167  concomm%n_neighbor_pe = 0
168  concomm%MPI_COMM = 0
169  end subroutine hecmw_contact_comm_finalize
170 
171  subroutine hecmw_contact_comm_reduce_r(conComm, vec, op)
172  implicit none
173  type (hecmwst_contact_comm), intent(in) :: concomm
174  real(kind=kreal), intent(inout) :: vec(:)
175  integer(kind=kint), intent(in) :: op
176  if (concomm%n_neighbor_pe == 0) return
177  call send_recv_contact_info_r(concomm%n_neighbor_pe, concomm%neighbor_pe, concomm%MPI_COMM, &
178  concomm%ext_index, concomm%ext_item, concomm%int_index, concomm%int_item, vec, op)
179  end subroutine hecmw_contact_comm_reduce_r
180 
181  subroutine hecmw_contact_comm_bcast_r(conComm, vec)
182  implicit none
183  type (hecmwst_contact_comm), intent(in) :: concomm
184  real(kind=kreal), intent(inout) :: vec(:)
185  integer(kind=kint) :: op
186  if (concomm%n_neighbor_pe == 0) return
187  op = op_overwrite
188  call send_recv_contact_info_r(concomm%n_neighbor_pe, concomm%neighbor_pe, concomm%MPI_COMM, &
189  concomm%int_index, concomm%int_item, concomm%ext_index, concomm%ext_item, vec, op)
190  end subroutine hecmw_contact_comm_bcast_r
191 
192  subroutine hecmw_contact_comm_reduce_i(conComm, vec, op)
193  implicit none
194  type (hecmwst_contact_comm), intent(in) :: concomm
195  integer(kind=kint), intent(inout) :: vec(:)
196  integer(kind=kint), intent(in) :: op
197  if (concomm%n_neighbor_pe == 0) return
198  call send_recv_contact_info_i(concomm%n_neighbor_pe, concomm%neighbor_pe, concomm%MPI_COMM, &
199  concomm%ext_index, concomm%ext_item, concomm%int_index, concomm%int_item, vec, op)
200  end subroutine hecmw_contact_comm_reduce_i
201 
202  subroutine hecmw_contact_comm_bcast_i(conComm, vec)
203  implicit none
204  type (hecmwst_contact_comm), intent(in) :: concomm
205  integer(kind=kint), intent(inout) :: vec(:)
206  integer(kind=kint) :: op
207  if (concomm%n_neighbor_pe == 0) return
208  op = op_overwrite
209  call send_recv_contact_info_i(concomm%n_neighbor_pe, concomm%neighbor_pe, concomm%MPI_COMM, &
210  concomm%int_index, concomm%int_item, concomm%ext_index, concomm%ext_item, vec, op)
211  end subroutine hecmw_contact_comm_bcast_i
212 
213  subroutine hecmw_contact_comm_allreduce_i(conComm, vec, op)
214  implicit none
215  type (hecmwst_contact_comm), intent(in) :: concomm
216  integer(kind=kint), intent(inout) :: vec(:)
217  integer(kind=kint), intent(in) :: op
218  call hecmw_contact_comm_reduce_i(concomm, vec, op)
219  call hecmw_contact_comm_bcast_i(concomm, vec)
220  end subroutine hecmw_contact_comm_allreduce_i
221 
222  !
223  ! private subroutines
224  !
225 
226  subroutine rank_to_idom(hecMESH, rank, idom)
227  implicit none
228  type (hecmwst_local_mesh), intent(in) :: hecmesh
229  integer(kind=kint), intent(in) :: rank
230  integer(kind=kint), intent(out) :: idom
231  integer(kind=kint) :: i
232  do i = 1, hecmesh%n_neighbor_pe
233  if (hecmesh%neighbor_pe(i) == rank) then
234  idom = i
235  return
236  endif
237  enddo
238  stop 'ERROR: exp_rank not found in neighbor_pe'
239  end subroutine rank_to_idom
240 
241  subroutine send_recv_contact_info_r(n_neighbor_pe, neighbor_pe, MPI_COMM, &
242  send_index, send_item, recv_index, recv_item, vec, op)
243  implicit none
244  integer(kind=kint), intent(in) :: n_neighbor_pe
245  integer(kind=kint), intent(in) :: neighbor_pe(:)
246  integer(kind=kint), intent(in) :: mpi_comm
247  integer(kind=kint), pointer, intent(in) :: send_index(:), send_item(:), recv_index(:), recv_item(:)
248  real(kind=kreal), intent(inout) :: vec(:)
249  integer(kind=kint), intent(in) :: op
250  real(kind=kreal), allocatable :: send_buf(:), recv_buf(:)
251  integer(kind=kint) :: i, n_send, idom, irank, is, ie, len, tag
252  integer(kind=kint), allocatable :: requests(:), statuses(:,:)
253  if (n_neighbor_pe == 0) return
254  allocate(requests(n_neighbor_pe))
255  allocate(statuses(hecmw_status_size, n_neighbor_pe))
256  allocate(send_buf(send_index(n_neighbor_pe)))
257  allocate(recv_buf(recv_index(n_neighbor_pe)))
258  do i = 1, send_index(n_neighbor_pe)
259  send_buf(i) = vec(send_item(i))
260  enddo
261  n_send = 0
262  do idom = 1, n_neighbor_pe
263  irank = neighbor_pe(idom)
264  is = send_index(idom-1)+1
265  ie = send_index(idom)
266  len = ie-is+1
267  if (len == 0) cycle
268  n_send = n_send + 1
269  tag = 5011
270  call hecmw_isend_r(send_buf(is:ie), len, irank, tag, &
271  mpi_comm, requests(n_send))
272  enddo
273  do idom = 1, n_neighbor_pe
274  irank = neighbor_pe(idom)
275  is = recv_index(idom-1)+1
276  ie = recv_index(idom)
277  len = ie-is+1
278  if (len == 0) cycle
279  tag = 5011
280  call hecmw_recv_r(recv_buf(is:ie), len, irank, tag, &
281  mpi_comm, statuses(:,1))
282  enddo
283  call hecmw_waitall(n_send, requests, statuses)
284  if (op == hecmw_sum) then
285  do i = 1, recv_index(n_neighbor_pe)
286  vec(recv_item(i)) = vec(recv_item(i)) + recv_buf(i)
287  enddo
288  elseif (op == hecmw_prod) then
289  do i = 1, recv_index(n_neighbor_pe)
290  vec(recv_item(i)) = vec(recv_item(i)) * recv_buf(i)
291  enddo
292  elseif (op == hecmw_max) then
293  do i = 1, recv_index(n_neighbor_pe)
294  vec(recv_item(i)) = max(vec(recv_item(i)), recv_buf(i))
295  enddo
296  elseif (op == hecmw_min) then
297  do i = 1, recv_index(n_neighbor_pe)
298  vec(recv_item(i)) = min(vec(recv_item(i)), recv_buf(i))
299  enddo
300  else ! overwrite
301  do i = 1, recv_index(n_neighbor_pe)
302  vec(recv_item(i)) = recv_buf(i)
303  enddo
304  endif
305  deallocate(requests)
306  deallocate(statuses)
307  if (dbg >= 2) then
308  write(0,*) ' DEBUG2: send_buf',send_buf(:)
309  write(0,*) ' DEBUG2: recv_buf',recv_buf(:)
310  endif
311  deallocate(send_buf)
312  deallocate(recv_buf)
313  end subroutine send_recv_contact_info_r
314 
315  subroutine send_recv_contact_info_i(n_neighbor_pe, neighbor_pe, MPI_COMM, &
316  send_index, send_item, recv_index, recv_item, vec, op)
317  implicit none
318  integer(kind=kint), intent(in) :: n_neighbor_pe
319  integer(kind=kint), intent(in) :: neighbor_pe(:)
320  integer(kind=kint), intent(in) :: mpi_comm
321  integer(kind=kint), pointer, intent(in) :: send_index(:), send_item(:), recv_index(:), recv_item(:)
322  integer(kind=kint), intent(inout) :: vec(:)
323  integer(kind=kint), intent(in) :: op
324  integer(kind=kint), allocatable :: send_buf(:), recv_buf(:)
325  integer(kind=kint) :: i, n_send, idom, irank, is, ie, len, tag
326  integer(kind=kint), allocatable :: requests(:), statuses(:,:)
327  if (n_neighbor_pe == 0) return
328  allocate(requests(n_neighbor_pe))
329  allocate(statuses(hecmw_status_size, n_neighbor_pe))
330  allocate(send_buf(send_index(n_neighbor_pe)))
331  allocate(recv_buf(recv_index(n_neighbor_pe)))
332  do i = 1, send_index(n_neighbor_pe)
333  send_buf(i) = vec(send_item(i))
334  enddo
335  n_send = 0
336  do idom = 1, n_neighbor_pe
337  irank = neighbor_pe(idom)
338  is = send_index(idom-1)+1
339  ie = send_index(idom)
340  len = ie-is+1
341  if (len == 0) cycle
342  n_send = n_send + 1
343  tag = 5011
344  call hecmw_isend_int(send_buf(is:ie), len, irank, tag, &
345  mpi_comm, requests(n_send))
346  enddo
347  do idom = 1, n_neighbor_pe
348  irank = neighbor_pe(idom)
349  is = recv_index(idom-1)+1
350  ie = recv_index(idom)
351  len = ie-is+1
352  if (len == 0) cycle
353  tag = 5011
354  call hecmw_recv_int(recv_buf(is:ie), len, irank, tag, &
355  mpi_comm, statuses(:,1))
356  enddo
357  call hecmw_waitall(n_send, requests, statuses)
358  if (op == hecmw_sum) then
359  do i = 1, recv_index(n_neighbor_pe)
360  vec(recv_item(i)) = vec(recv_item(i)) + recv_buf(i)
361  enddo
362  elseif (op == hecmw_prod) then
363  do i = 1, recv_index(n_neighbor_pe)
364  vec(recv_item(i)) = vec(recv_item(i)) * recv_buf(i)
365  enddo
366  elseif (op == hecmw_max) then
367  do i = 1, recv_index(n_neighbor_pe)
368  vec(recv_item(i)) = max(vec(recv_item(i)), recv_buf(i))
369  enddo
370  elseif (op == hecmw_min) then
371  do i = 1, recv_index(n_neighbor_pe)
372  vec(recv_item(i)) = min(vec(recv_item(i)), recv_buf(i))
373  enddo
374  else ! overwrite
375  do i = 1, recv_index(n_neighbor_pe)
376  vec(recv_item(i)) = recv_buf(i)
377  enddo
378  endif
379  deallocate(requests)
380  deallocate(statuses)
381  if (dbg >= 2) then
382  write(0,*) ' DEBUG2: send_buf',send_buf(:)
383  write(0,*) ' DEBUG2: recv_buf',recv_buf(:)
384  endif
385  deallocate(send_buf)
386  deallocate(recv_buf)
387  end subroutine send_recv_contact_info_i
388 
389 end module m_hecmw_contact_comm
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
integer(kind=kint), parameter hecmw_prod
integer(kind=kint), parameter hecmw_max
integer(kind=4), parameter kreal
integer(kind=kint), parameter hecmw_status_size
integer(kind=kint), parameter hecmw_min
subroutine hecmw_isend_int(sbuf, sc, dest, tag, comm, req)
subroutine hecmw_recv_int(rbuf, rc, source, tag, comm, stat)
subroutine hecmw_isend_r(sbuf, sc, dest, tag, comm, req)
subroutine hecmw_waitall(cnt, reqs, stats)
subroutine hecmw_recv_r(rbuf, rc, source, tag, comm, stat)
subroutine, public hecmw_contact_comm_reduce_r(conComm, vec, op)
subroutine, public hecmw_contact_comm_allreduce_i(conComm, vec, op)
subroutine, public hecmw_contact_comm_bcast_r(conComm, vec)
subroutine, public hecmw_contact_comm_init(conComm, hecMESH, ndof, n_contact_dof, contact_dofs)
subroutine, public hecmw_contact_comm_bcast_i(conComm, vec)
subroutine, public hecmw_contact_comm_reduce_i(conComm, vec, op)
subroutine, public hecmw_contact_comm_finalize(conComm)