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