FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_solver_las_nn.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  use hecmw_util
8  implicit none
9 
10  private
11 
12  public :: hecmw_matvec_nn
13  public :: hecmw_matresid_nn
14  public :: hecmw_rel_resid_l2_nn
15  public :: hecmw_tvec_nn
16  public :: hecmw_ttvec_nn
17 
18 contains
19 
20  !C
21  !C***
22  !C*** hecmw_matvec_nn
23  !C***
24  !C
25  subroutine hecmw_matvec_nn (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
26  use hecmw_util
27  use m_hecmw_comm_f
28  use hecmw_jad_type
29  use hecmw_tuning_fx
30  !$ use omp_lib
31 
32  implicit none
33  type (hecmwst_local_mesh), intent(in) :: hecmesh
34  type (hecmwst_matrix), intent(in), target :: hecmat
35  real(kind=kreal), intent(in) :: x(:)
36  real(kind=kreal), intent(out) :: y(:)
37  real(kind=kreal), intent(inout) :: time_ax
38  real(kind=kreal), intent(inout), optional :: commtime
39 
40  real(kind=kreal) :: start_time, end_time, tcomm
41  integer(kind=kint) :: i, j, k, l, js, je, in
42  real(kind=kreal) :: yv(hecmat%NDOF), xv(hecmat%NDOF)
43 
44  integer(kind=kint) :: n, np, ndof, ndof2
45  integer(kind=kint), pointer :: indexl(:), iteml(:), indexu(:), itemu(:), indexa(:), itema(:)
46  real(kind=kreal), pointer :: al(:), au(:), d(:), a(:)
47 
48  ! added for tuning >>>
49  integer, parameter :: numofblockperthread = 100
50  logical, save :: isfirst = .true.
51  integer, save :: numofthread = 1
52  integer, save, allocatable :: startpos(:), endpos(:)
53  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
54  integer(kind=kint) :: threadnum, blocknum, numofblock
55  integer(kind=kint) :: numofelement, elementcount, blockindex
56  real(kind=kreal) :: numofelementperblock
57  ! <<< added for tuning
58 
59  if (hecmw_jad_is_initialized().ne.0) then
60  tcomm = 0.d0
61  start_time = hecmw_wtime()
62  call hecmw_jad_matvec(hecmesh, hecmat, x, y, tcomm)
63  end_time = hecmw_wtime()
64  time_ax = time_ax + end_time - start_time - tcomm
65  if (present(commtime)) commtime = commtime + tcomm
66  else
67 
68  n = hecmat%N
69  np = hecmat%NP
70  indexl => hecmat%indexL
71  indexu => hecmat%indexU
72  indexa => hecmat%indexA
73  iteml => hecmat%itemL
74  itemu => hecmat%itemU
75  itema => hecmat%itemA
76  al => hecmat%AL
77  au => hecmat%AU
78  d => hecmat%D
79  a => hecmat%A
80  ndof = hecmat%NDOF
81  ndof2 = ndof*ndof
82 
83  ! added for tuning >>>
84 #ifndef _OPENACC
85  if (.not. isfirst) then
86  numofblock = numofthread * numofblockperthread
87  if (endpos(numofblock-1) .ne. n-1) then
88  deallocate(startpos, endpos)
89  isfirst = .true.
90  endif
91  endif
92  if (isfirst) then
93  !$ numOfThread = omp_get_max_threads()
94  numofblock = numofthread * numofblockperthread
95  allocate (startpos(0 : numofblock - 1), endpos(0 : numofblock - 1))
96  numofelement = n + indexl(n) + indexu(n)
97  numofelementperblock = dble(numofelement) / numofblock
98  blocknum = 0
99  elementcount = 0
100  startpos(blocknum) = 1
101  do i= 1, n
102  elementcount = elementcount + 1
103  elementcount = elementcount + (indexl(i) - indexl(i-1))
104  elementcount = elementcount + (indexu(i) - indexu(i-1))
105  if (elementcount > (blocknum + 1) * numofelementperblock) then
106  endpos(blocknum) = i
107  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
108  ! startPos(blockNum), endPos(blockNum)
109  blocknum = blocknum + 1
110  startpos(blocknum) = i + 1
111  if (blocknum == (numofblock - 1)) exit
112  endif
113  enddo
114  endpos(blocknum) = n
115  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
116  ! startPos(blockNum), endPos(blockNum)
117  ! for irregular data
118  do i= blocknum+1, numofblock-1
119  startpos(i) = n
120  endpos(i) = n-1
121  ! write(9000+hecMESH%my_rank,*) mod(i, numOfThread), &
122  ! startPos(i), endPos(i)
123  end do
124 
125  call hecmw_tuning_fx_calc_sector_cache(np, ndof, &
126  sectorcachesize0, sectorcachesize1)
127 
128  isfirst = .false.
129  endif
130 #endif
131  ! <<< added for tuning
132 
133  start_time= hecmw_wtime()
134  call hecmw_update_r (hecmesh, x, np, ndof)
135  end_time= hecmw_wtime()
136  if (present(commtime)) commtime = commtime + end_time - start_time
137 
138  start_time = hecmw_wtime()
139 
140 #ifdef _OPENACC
141  !$acc kernels
142  !$acc loop independent
143  do i = 1, n
144  do k=1,ndof
145  xv(k) = x(ndof*(i-1)+k)
146  end do
147  yv(:)=0.0d0
148  js= indexa(i-1) + 1
149  je= indexa(i)
150  do j= js, je
151  in = itema(j)
152  do k=1,ndof
153  xv(k) = x(ndof*(in-1)+k)
154  end do
155  do k=1,ndof
156  do l=1,ndof
157  yv(k)=yv(k)+a(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
158  end do
159  end do
160  enddo
161  do k=1,ndof
162  y(ndof*(i-1)+k) = yv(k)
163  end do
164  enddo
165  !$acc end kernels
166 #else
167  !call fapp_start("loopInMatvec33", 1, 0)
168  !call start_collection("loopInMatvec33")
169 
170  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
171  !OCL CACHE_SUBSECTOR_ASSIGN(X)
172 
173  !$OMP PARALLEL DEFAULT(NONE) &
174  !$OMP&PRIVATE(i,XV,YV,jS,jE,j,k,l,in,threadNum,blockNum,blockIndex) &
175  !$OMP&SHARED(D,AL,AU,indexL,itemL,indexU,itemU,X,Y,startPos,endPos,numOfThread,N,NDOF,NDOF2)
176  threadnum = 0
177  !$ threadNum = omp_get_thread_num()
178  do blocknum = 0 , numofblockperthread - 1
179  blockindex = blocknum * numofthread + threadnum
180  do i = startpos(blockindex), endpos(blockindex)
181  do k=1,ndof
182  xv(k) = x(ndof*(i-1)+k)
183  end do
184  yv(:)=0.0d0
185  do k=1,ndof
186  do l=1,ndof
187  yv(k)=yv(k)+d(ndof2*(i-1)+(k-1)*ndof+l)*xv(l)
188  end do
189  end do
190  js= indexl(i-1) + 1
191  je= indexl(i )
192  do j= js, je
193  in = iteml(j)
194  do k=1,ndof
195  xv(k) = x(ndof*(in-1)+k)
196  end do
197  do k=1,ndof
198  do l=1,ndof
199  yv(k)=yv(k)+al(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
200  end do
201  end do
202  enddo
203  js= indexu(i-1) + 1
204  je= indexu(i )
205  do j= js, je
206  in = itemu(j)
207  do k=1,ndof
208  xv(k) = x(ndof*(in-1)+k)
209  end do
210  do k=1,ndof
211  do l=1,ndof
212  yv(k)=yv(k)+au(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
213  end do
214  end do
215  enddo
216  do k=1,ndof
217  y(ndof*(i-1)+k) = yv(k)
218  end do
219  enddo
220  enddo
221  !$OMP END PARALLEL
222 
223  !OCL END_CACHE_SUBSECTOR
224  !OCL END_CACHE_SECTOR_SIZE
225 
226  !call stop_collection("loopInMatvec33")
227  !call fapp_stop("loopInMatvec33", 1, 0)
228 #endif
229 
230  end_time = hecmw_wtime()
231  time_ax = time_ax + end_time - start_time
232  endif
233 
234  end subroutine hecmw_matvec_nn
235 
236 
237 
238  !C
239  !C***
240  !C*** hecmw_matresid_nn
241  !C***
242  !C
243  subroutine hecmw_matresid_nn (hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
244  use hecmw_util
245  implicit none
246  type (hecmwst_local_mesh), intent(in) :: hecmesh
247  type (hecmwst_matrix), intent(in) :: hecmat
248  real(kind=kreal), intent(in) :: x(:), b(:)
249  real(kind=kreal), intent(out) :: r(:)
250  real(kind=kreal), intent(inout) :: time_ax
251  real(kind=kreal), intent(inout), optional :: commtime
252 
253  integer(kind=kint) :: i
254  real(kind=kreal) :: tcomm
255 
256  tcomm = 0.d0
257  call hecmw_matvec_nn (hecmesh, hecmat, x, r, time_ax, tcomm)
258  if (present(commtime)) commtime = commtime + tcomm
259 #ifdef _OPENACC
260  !$acc kernels
261  !$acc loop independent
262 #else
263  !$omp parallel default(none),private(i),shared(hecMAT,R,B)
264  !$omp do
265 #endif
266  do i = 1, hecmat%N * hecmat%NDOF
267  r(i) = b(i) - r(i)
268  enddo
269 #ifdef _OPENACC
270  !$acc end kernels
271 #else
272  !$omp end do
273  !$omp end parallel
274 #endif
275  end subroutine hecmw_matresid_nn
276 
277  !C
278  !C***
279  !C*** hecmw_rel_resid_L2_nn
280  !C***
281  !C
282  function hecmw_rel_resid_l2_nn (hecMESH, hecMAT, time_Ax, COMMtime)
283  use hecmw_util
285  implicit none
286  real(kind=kreal) :: hecmw_rel_resid_l2_nn
287  type ( hecmwst_local_mesh ), intent(in) :: hecmesh
288  type ( hecmwst_matrix ), intent(in) :: hecmat
289  real(kind=kreal), intent(inout) :: time_ax
290  real(kind=kreal), intent(inout), optional :: commtime
291 
292  real(kind=kreal), allocatable :: r(:)
293  real(kind=kreal) :: bnorm2, rnorm2
294  real(kind=kreal) :: tcomm
295 
296  allocate(r(hecmat%NDOF*hecmat%NP))
297 
298  tcomm = 0.d0
299  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, &
300  hecmat%B, hecmat%B, bnorm2, tcomm)
301  if (bnorm2 == 0.d0) then
302  bnorm2 = 1.d0
303  endif
304  call hecmw_matresid_nn(hecmesh, hecmat, hecmat%X, hecmat%B, r, time_ax, tcomm)
305  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, r, r, rnorm2, tcomm)
306  hecmw_rel_resid_l2_nn = sqrt(rnorm2 / bnorm2)
307 
308  if (present(commtime)) commtime = commtime + tcomm
309 
310  deallocate(r)
311  end function hecmw_rel_resid_l2_nn
312 
313  !C
314  !C***
315  !C*** hecmw_Tvec_nn
316  !C***
317  !C
318  subroutine hecmw_tvec_nn (hecMESH, ndof, X, Y, COMMtime)
319  use hecmw_util
320  use m_hecmw_comm_f
321  implicit none
322  type (hecmwst_local_mesh), intent(in) :: hecmesh
323  integer(kind=kint), intent(in) :: ndof
324  real(kind=kreal), intent(in) :: x(:)
325  real(kind=kreal), intent(out) :: y(:)
326  real(kind=kreal), intent(inout) :: commtime
327 
328  real(kind=kreal) :: start_time, end_time
329  integer(kind=kint) :: i, j, jj, k, kk
330 
331  start_time= hecmw_wtime()
332  call hecmw_update_r (hecmesh, x, hecmesh%n_node, ndof)
333  end_time= hecmw_wtime()
334  commtime = commtime + end_time - start_time
335 
336 #ifdef _OPENACC
337  !$acc kernels
338  !$acc loop independent
339 #else
340  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y),firstprivate(ndof)
341  !$omp do
342 #endif
343  do i= 1, hecmesh%nn_internal * ndof
344  y(i)= x(i)
345  enddo
346 #ifndef _OPENACC
347  !$omp end do
348 #endif
349 
350 #ifdef _OPENACC
351  !$acc loop independent
352 #else
353  !$omp do
354 #endif
355  outer: do i= 1, hecmesh%mpc%n_mpc
356  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
357  if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
358  enddo
359  k = hecmesh%mpc%mpc_index(i-1) + 1
360  kk = ndof * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
361  y(kk) = 0.d0
362  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
363  jj = ndof * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
364  y(kk) = y(kk) - hecmesh%mpc%mpc_val(j) * x(jj)
365  enddo
366  enddo outer
367 #ifdef _OPENACC
368  !$acc end kernels
369 #else
370  !$omp end do
371  !$omp end parallel
372 #endif
373 
374  end subroutine hecmw_tvec_nn
375 
376  !C
377  !C***
378  !C*** hecmw_Ttvec_nn
379  !C***
380  !C
381  subroutine hecmw_ttvec_nn (hecMESH, ndof, X, Y, COMMtime)
382  use hecmw_util
383  use m_hecmw_comm_f
384  implicit none
385  type (hecmwst_local_mesh), intent(in) :: hecmesh
386  integer(kind=kint), intent(in) :: ndof
387  real(kind=kreal), intent(in) :: x(:)
388  real(kind=kreal), intent(out) :: y(:)
389  real(kind=kreal), intent(inout) :: commtime
390 
391  real(kind=kreal) :: start_time, end_time
392  integer(kind=kint) :: i, j, jj, k, kk
393 
394  start_time= hecmw_wtime()
395  call hecmw_update_r (hecmesh, x, hecmesh%n_node,ndof)
396  end_time= hecmw_wtime()
397  commtime = commtime + end_time - start_time
398 
399 #ifdef _OPENACC
400  !$acc kernels
401  !$acc loop independent
402 #else
403  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y),firstprivate(ndof)
404  !$omp do
405 #endif
406  do i= 1, hecmesh%nn_internal * ndof
407  y(i)= x(i)
408  enddo
409 #ifndef _OPENACC
410  !$omp end do
411 #endif
412 
413 #ifdef _OPENACC
414  !$acc loop independent
415 #else
416  !$omp do
417 #endif
418  outer: do i= 1, hecmesh%mpc%n_mpc
419  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
420  if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
421  enddo
422  k = hecmesh%mpc%mpc_index(i-1) + 1
423  kk = ndof * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
424  y(kk) = 0.d0
425  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
426  jj = ndof * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
427 #ifdef _OPENACC
428  !$acc atomic update
429 #else
430  !$omp atomic
431 #endif
432  y(jj) = y(jj) - hecmesh%mpc%mpc_val(j) * x(kk)
433  enddo
434  enddo outer
435 #ifdef _OPENACC
436  !$acc end kernels
437 #else
438  !$omp end do
439  !$omp end parallel
440 #endif
441 
442 
443  end subroutine hecmw_ttvec_nn
444 
445  !C
446  !C***
447  !C*** hecmw_mat_diag_sr_nn
448  !C***
449  !C
450  subroutine hecmw_mat_diag_sr_nn(hecMESH, hecMAT, COMMtime)
451  use hecmw_util
452  use m_hecmw_comm_f
453  implicit none
454  type (hecmwST_local_mesh), intent(in) :: hecMESH
455  type (hecmwST_matrix), intent(inout), target :: hecMAT
456  real(kind=kreal), intent(inout), optional :: commtime
457  real(kind=kreal), allocatable :: w(:,:)
458  real(kind=kreal), pointer :: d(:)
459  integer(kind=kint) :: ip, NDOF, i, j
460  real(kind=kreal) :: start_time, end_time
461  ndof = hecmat%NDOF
462  allocate(w(ndof*hecmat%NP,ndof))
463  d => hecmat%D
464  do ip= 1, hecmat%N
465  do i=1,ndof
466  do j=1,ndof
467  w(ndof*(ip-1)+i,j) = d(ndof*ndof*(ip-1)+(i-1)*ndof+j)
468  end do
469  end do
470  enddo
471  start_time= hecmw_wtime()
472  do i=1,ndof
473  call hecmw_update_r (hecmesh, w(:,i), hecmat%NP, ndof)
474  end do
475  end_time= hecmw_wtime()
476  if (present(commtime)) commtime = commtime + end_time - start_time
477  do ip= hecmat%N+1, hecmat%NP
478  do i=1,ndof
479  do j=1,ndof
480  d(ndof*ndof*(ip-1)+(i-1)*ndof+j) = w(ndof*(ip-1)+i,j)
481  end do
482  end do
483  enddo
484  deallocate(w)
485  end subroutine hecmw_mat_diag_sr_nn
486 
487  subroutine hecmw_mat_add_nn(hecMAT1, hecMAT2, hecMAT3)
488  use hecmw_util
489  implicit none
490  type (hecmwST_matrix) :: hecMAT1, hecMAT2, hecMAT3
491  integer(kind=kint) :: i
492 
493  do i = 1, hecmat1%NP*hecmat1%NDOF*hecmat1%NDOF
494  hecmat3%D(i) = hecmat1%D(i) + hecmat2%D(i)
495  enddo
496 
497  do i = 1, hecmat1%NPU*hecmat1%NDOF*hecmat1%NDOF
498  hecmat3%AU(i) = hecmat1%AU(i) + hecmat2%AU(i)
499  enddo
500 
501  do i = 1, hecmat1%NPL*hecmat1%NDOF*hecmat1%NDOF
502  hecmat3%AL(i) = hecmat1%AL(i) + hecmat2%AL(i)
503  enddo
504  end subroutine hecmw_mat_add_nn
505 
506  subroutine hecmw_mat_multiple_nn(hecMAT, alpha)
507  use hecmw_util
508  implicit none
509  type (hecmwST_matrix) :: hecMAT
510  real(kind=kreal), intent(in) :: alpha
511  integer(kind=kint) :: i
512 
513  do i = 1, hecmat%NP*hecmat%NDOF*hecmat%NDOF
514  hecmat%D(i) = alpha*hecmat%D(i)
515  enddo
516 
517  do i = 1, hecmat%NPU*hecmat%NDOF*hecmat%NDOF
518  hecmat%AU(i) = alpha*hecmat%AU(i)
519  enddo
520 
521  do i = 1, hecmat%NPL*hecmat%NDOF*hecmat%NDOF
522  hecmat%AL(i) = alpha*hecmat%AL(i)
523  enddo
524  end subroutine hecmw_mat_multiple_nn
525 end module hecmw_solver_las_nn
Jagged Diagonal Matrix storage for vector processors. Original code was provided by JAMSTEC.
Definition: hecmw_jadm.f90:8
subroutine, public hecmw_jad_matvec(hecMESH, hecMAT, X, Y, COMMtime)
Definition: hecmw_jadm.f90:61
integer(kind=kint) function, public hecmw_jad_is_initialized()
Definition: hecmw_jadm.f90:56
subroutine hecmw_mat_multiple_nn(hecMAT, alpha)
subroutine hecmw_mat_add_nn(hecMAT1, hecMAT2, hecMAT3)
subroutine, public hecmw_ttvec_nn(hecMESH, ndof, X, Y, COMMtime)
real(kind=kreal) function, public hecmw_rel_resid_l2_nn(hecMESH, hecMAT, time_Ax, COMMtime)
subroutine, public hecmw_tvec_nn(hecMESH, ndof, X, Y, COMMtime)
subroutine, public hecmw_matvec_nn(hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
subroutine, public hecmw_matresid_nn(hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
subroutine hecmw_mat_diag_sr_nn(hecMESH, hecMAT, COMMtime)
subroutine hecmw_innerproduct_r(hecMESH, ndof, X, Y, sum, COMMtime)
subroutine, public hecmw_tuning_fx_calc_sector_cache(N, NDOF, sectorCacheSize0, sectorCacheSize1)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=4), parameter kreal
real(kind=kreal) function hecmw_wtime()
subroutine hecmw_update_r(hecMESH, val, n, m)