FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_solver_las_66.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_66
13  public :: hecmw_matresid_66
14  public :: hecmw_rel_resid_l2_66
15 
16 contains
17 
18  !C
19  !C***
20  !C*** hecmw_matvec_66
21  !C***
22  !C
23  subroutine hecmw_matvec_66 (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
24  use hecmw_util
25  use m_hecmw_comm_f
26  use hecmw_jad_type
27  use hecmw_tuning_fx
28  !$ use omp_lib
29 
30  implicit none
31  type (hecmwst_local_mesh), intent(in) :: hecmesh
32  type (hecmwst_matrix), intent(in), target :: hecmat
33  real(kind=kreal), intent(inout) :: x(:)
34  real(kind=kreal), intent(out) :: y(:)
35  real(kind=kreal), intent(inout) :: time_ax
36  real(kind=kreal), intent(inout), optional :: commtime
37 
38  real(kind=kreal) :: start_time, end_time, tcomm
39  integer(kind=kint) :: i, j, js, je, in
40  real(kind=kreal) :: yv1, yv2, yv3, x1, x2, x3
41  real(kind=kreal) :: yv4, yv5, yv6, x4, x5, x6
42 
43  integer(kind=kint) :: n, np
44  integer(kind=kint), pointer :: indexl(:), iteml(:), indexu(:), itemu(:), indexa(:), itema(:)
45  real(kind=kreal), pointer :: al(:), au(:), d(:), a(:)
46 
47  ! added for tuning >>>
48  integer, parameter :: numofblockperthread = 100
49  logical, save :: isfirst = .true.
50  integer, save :: numofthread = 1
51  integer, save, allocatable :: startpos(:), endpos(:)
52  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
53  integer(kind=kint) :: threadnum, blocknum, numofblock
54  integer(kind=kint) :: numofelement, elementcount, blockindex
55  real(kind=kreal) :: numofelementperblock
56  ! <<< added for tuning
57 
58  if (hecmw_jad_is_initialized().ne.0) then
59  tcomm = 0.d0
60  start_time = hecmw_wtime()
61  call hecmw_jad_matvec(hecmesh, hecmat, x, y, tcomm)
62  end_time = hecmw_wtime()
63  time_ax = time_ax + end_time - start_time - tcomm
64  if (present(commtime)) commtime = commtime + tcomm
65  else
66 
67  n = hecmat%N
68  np = hecmat%NP
69  indexl => hecmat%indexL
70  indexu => hecmat%indexU
71  indexa => hecmat%indexA
72  iteml => hecmat%itemL
73  itemu => hecmat%itemU
74  itema => hecmat%itemA
75  al => hecmat%AL
76  au => hecmat%AU
77  d => hecmat%D
78  a => hecmat%A
79 
80  ! added for tuning >>>
81 #ifndef _OPENACC
82  if (.not. isfirst) then
83  numofblock = numofthread * numofblockperthread
84  if (endpos(numofblock-1) .ne. n-1) then
85  deallocate(startpos, endpos)
86  isfirst = .true.
87  endif
88  endif
89  if (isfirst) then
90  !$ numOfThread = omp_get_max_threads()
91  numofblock = numofthread * numofblockperthread
92  allocate (startpos(0 : numofblock - 1), endpos(0 : numofblock - 1))
93  numofelement = n + indexl(n) + indexu(n)
94  numofelementperblock = dble(numofelement) / numofblock
95  blocknum = 0
96  elementcount = 0
97  startpos(blocknum) = 1
98  do i= 1, n
99  elementcount = elementcount + 1
100  elementcount = elementcount + (indexl(i) - indexl(i-1))
101  elementcount = elementcount + (indexu(i) - indexu(i-1))
102  if (elementcount > (blocknum + 1) * numofelementperblock) then
103  endpos(blocknum) = i
104  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
105  ! startPos(blockNum), endPos(blockNum)
106  blocknum = blocknum + 1
107  startpos(blocknum) = i + 1
108  if (blocknum == (numofblock - 1)) exit
109  endif
110  enddo
111  endpos(blocknum) = n
112  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
113  ! startPos(blockNum), endPos(blockNum)
114  ! for irregular data
115  do i= blocknum+1, numofblock-1
116  startpos(i) = n
117  endpos(i) = n-1
118  ! write(9000+hecMESH%my_rank,*) mod(i, numOfThread), &
119  ! startPos(i), endPos(i)
120  end do
121 
123  sectorcachesize0, sectorcachesize1)
124 
125  isfirst = .false.
126  endif
127 #endif
128  ! <<< added for tuning
129 
130  start_time= hecmw_wtime()
131  call hecmw_update_r (hecmesh, x, np, 6)
132  end_time= hecmw_wtime()
133  if (present(commtime)) commtime = commtime + end_time - start_time
134 
135  start_time = hecmw_wtime()
136 
137 #ifdef _OPENACC
138  !$acc kernels
139  !$acc loop independent
140  do i = 1, n
141  x1= x(6*i-5)
142  x2= x(6*i-4)
143  x3= x(6*i-3)
144  x4= x(6*i-2)
145  x5= x(6*i-1)
146  x6= x(6*i )
147  yv1= 0
148  yv2= 0
149  yv3= 0
150  yv4= 0
151  yv5= 0
152  yv6= 0
153  js= indexa(i-1) + 1
154  je= indexa(i)
155  do j= js, je
156  in = itema(j)
157  x1= x(6*in-5)
158  x2= x(6*in-4)
159  x3= x(6*in-3)
160  x4= x(6*in-2)
161  x5= x(6*in-1)
162  x6= x(6*in )
163  yv1= yv1 + a(36*j-35)*x1 + a(36*j-34)*x2 + a(36*j-33)*x3 + a(36*j-32)*x4 + a(36*j-31)*x5 + a(36*j-30)*x6
164  yv2= yv2 + a(36*j-29)*x1 + a(36*j-28)*x2 + a(36*j-27)*x3 + a(36*j-26)*x4 + a(36*j-25)*x5 + a(36*j-24)*x6
165  yv3= yv3 + a(36*j-23)*x1 + a(36*j-22)*x2 + a(36*j-21)*x3 + a(36*j-20)*x4 + a(36*j-19)*x5 + a(36*j-18)*x6
166  yv4= yv4 + a(36*j-17)*x1 + a(36*j-16)*x2 + a(36*j-15)*x3 + a(36*j-14)*x4 + a(36*j-13)*x5 + a(36*j-12)*x6
167  yv5= yv5 + a(36*j-11)*x1 + a(36*j-10)*x2 + a(36*j-9 )*x3 + a(36*j-8 )*x4 + a(36*j-7 )*x5 + a(36*j-6 )*x6
168  yv6= yv6 + a(36*j-5 )*x1 + a(36*j-4 )*x2 + a(36*j-3 )*x3 + a(36*j-2 )*x4 + a(36*j-1 )*x5 + a(36*j )*x6
169  enddo
170  y(6*i-5)= yv1
171  y(6*i-4)= yv2
172  y(6*i-3)= yv3
173  y(6*i-2)= yv4
174  y(6*i-1)= yv5
175  y(6*i )= yv6
176  enddo
177  !$acc end kernels
178 #else
179  !call fapp_start("loopInMatvec66", 1, 0)
180  !call start_collection("loopInMatvec66")
181 
182  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
183  !OCL CACHE_SUBSECTOR_ASSIGN(X)
184 
185  !$OMP PARALLEL DEFAULT(NONE) &
186  !$OMP&PRIVATE(i,X1,X2,X3,X4,X5,X6,YV1,YV2,YV3,YV4,YV5,YV6,jS,jE,j,in,threadNum,blockNum,blockIndex) &
187  !$OMP&SHARED(D,AL,AU,indexL,itemL,indexU,itemU,X,Y,startPos,endPos,numOfThread,N)
188  threadnum = 0
189  !$ threadNum = omp_get_thread_num()
190  do blocknum = 0 , numofblockperthread - 1
191  blockindex = blocknum * numofthread + threadnum
192  do i = startpos(blockindex), endpos(blockindex)
193  x1= x(6*i-5)
194  x2= x(6*i-4)
195  x3= x(6*i-3)
196  x4= x(6*i-2)
197  x5= x(6*i-1)
198  x6= x(6*i )
199  yv1= d(36*i-35)*x1 + d(36*i-34)*x2 + d(36*i-33)*x3 + d(36*i-32)*x4 + d(36*i-31)*x5 + d(36*i-30)*x6
200  yv2= d(36*i-29)*x1 + d(36*i-28)*x2 + d(36*i-27)*x3 + d(36*i-26)*x4 + d(36*i-25)*x5 + d(36*i-24)*x6
201  yv3= d(36*i-23)*x1 + d(36*i-22)*x2 + d(36*i-21)*x3 + d(36*i-20)*x4 + d(36*i-19)*x5 + d(36*i-18)*x6
202  yv4= d(36*i-17)*x1 + d(36*i-16)*x2 + d(36*i-15)*x3 + d(36*i-14)*x4 + d(36*i-13)*x5 + d(36*i-12)*x6
203  yv5= d(36*i-11)*x1 + d(36*i-10)*x2 + d(36*i-9 )*x3 + d(36*i-8 )*x4 + d(36*i-7 )*x5 + d(36*i-6 )*x6
204  yv6= d(36*i-5 )*x1 + d(36*i-4 )*x2 + d(36*i-3 )*x3 + d(36*i-2 )*x4 + d(36*i-1 )*x5 + d(36*i )*x6
205 
206  js= indexl(i-1) + 1
207  je= indexl(i )
208  do j= js, je
209  in = iteml(j)
210  x1= x(6*in-5)
211  x2= x(6*in-4)
212  x3= x(6*in-3)
213  x4= x(6*in-2)
214  x5= x(6*in-1)
215  x6= x(6*in )
216  yv1= yv1 + al(36*j-35)*x1 + al(36*j-34)*x2 + al(36*j-33)*x3 + al(36*j-32)*x4 + al(36*j-31)*x5 + al(36*j-30)*x6
217  yv2= yv2 + al(36*j-29)*x1 + al(36*j-28)*x2 + al(36*j-27)*x3 + al(36*j-26)*x4 + al(36*j-25)*x5 + al(36*j-24)*x6
218  yv3= yv3 + al(36*j-23)*x1 + al(36*j-22)*x2 + al(36*j-21)*x3 + al(36*j-20)*x4 + al(36*j-19)*x5 + al(36*j-18)*x6
219  yv4= yv4 + al(36*j-17)*x1 + al(36*j-16)*x2 + al(36*j-15)*x3 + al(36*j-14)*x4 + al(36*j-13)*x5 + al(36*j-12)*x6
220  yv5= yv5 + al(36*j-11)*x1 + al(36*j-10)*x2 + al(36*j-9 )*x3 + al(36*j-8 )*x4 + al(36*j-7 )*x5 + al(36*j-6 )*x6
221  yv6= yv6 + al(36*j-5 )*x1 + al(36*j-4 )*x2 + al(36*j-3 )*x3 + al(36*j-2 )*x4 + al(36*j-1 )*x5 + al(36*j )*x6
222  enddo
223  js= indexu(i-1) + 1
224  je= indexu(i )
225  do j= js, je
226  in = itemu(j)
227  x1= x(6*in-5)
228  x2= x(6*in-4)
229  x3= x(6*in-3)
230  x4= x(6*in-2)
231  x5= x(6*in-1)
232  x6= x(6*in )
233  yv1= yv1 + au(36*j-35)*x1 + au(36*j-34)*x2 + au(36*j-33)*x3 + au(36*j-32)*x4 + au(36*j-31)*x5 + au(36*j-30)*x6
234  yv2= yv2 + au(36*j-29)*x1 + au(36*j-28)*x2 + au(36*j-27)*x3 + au(36*j-26)*x4 + au(36*j-25)*x5 + au(36*j-24)*x6
235  yv3= yv3 + au(36*j-23)*x1 + au(36*j-22)*x2 + au(36*j-21)*x3 + au(36*j-20)*x4 + au(36*j-19)*x5 + au(36*j-18)*x6
236  yv4= yv4 + au(36*j-17)*x1 + au(36*j-16)*x2 + au(36*j-15)*x3 + au(36*j-14)*x4 + au(36*j-13)*x5 + au(36*j-12)*x6
237  yv5= yv5 + au(36*j-11)*x1 + au(36*j-10)*x2 + au(36*j-9 )*x3 + au(36*j-8 )*x4 + au(36*j-7 )*x5 + au(36*j-6 )*x6
238  yv6= yv6 + au(36*j-5 )*x1 + au(36*j-4 )*x2 + au(36*j-3 )*x3 + au(36*j-2 )*x4 + au(36*j-1 )*x5 + au(36*j )*x6
239  enddo
240  y(6*i-5)= yv1
241  y(6*i-4)= yv2
242  y(6*i-3)= yv3
243  y(6*i-2)= yv4
244  y(6*i-1)= yv5
245  y(6*i )= yv6
246  enddo
247  enddo
248  !$OMP END PARALLEL
249 
250  !OCL END_CACHE_SUBSECTOR
251  !OCL END_CACHE_SECTOR_SIZE
252 
253  !call stop_collection("loopInMatvec66")
254  !call fapp_stop("loopInMatvec66", 1, 0)
255 #endif
256 
257  end_time = hecmw_wtime()
258  time_ax = time_ax + end_time - start_time
259 
260  endif
261  end subroutine hecmw_matvec_66
262 
263  !C
264  !C***
265  !C*** hecmw_matresid_66
266  !C***
267  !C
268  subroutine hecmw_matresid_66 (hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
269  use hecmw_util
270  implicit none
271  type (hecmwst_local_mesh), intent(in) :: hecmesh
272  type (hecmwst_matrix), intent(in) :: hecmat
273  real(kind=kreal), intent(in) :: b(:)
274  real(kind=kreal), intent(inout) :: x(:)
275  real(kind=kreal), intent(out) :: r(:)
276  real(kind=kreal), intent(inout) :: time_ax
277  real(kind=kreal), intent(inout), optional :: commtime
278 
279  integer(kind=kint) :: i
280  real(kind=kreal) :: tcomm
281 
282  tcomm = 0.d0
283  call hecmw_matvec_66 (hecmesh, hecmat, x, r, time_ax, tcomm)
284  if (present(commtime)) commtime = commtime + tcomm
285 #ifdef _OPENACC
286  !$acc kernels
287  !$acc loop independent
288 #else
289  !$omp parallel default(none),private(i),shared(hecMAT,R,B)
290  !$omp do
291 #endif
292  do i = 1, hecmat%N * 6
293  r(i) = b(i) - r(i)
294  enddo
295 #ifdef _OPENACC
296  !$acc end kernels
297 #else
298  !$omp end do
299  !$omp end parallel
300 #endif
301  end subroutine hecmw_matresid_66
302 
303  !C
304  !C***
305  !C*** hecmw_rel_resid_L2_66
306  !C***
307  !C
308  function hecmw_rel_resid_l2_66 (hecMESH, hecMAT, time_Ax, COMMtime)
309  use hecmw_util
311  implicit none
312  real(kind=kreal) :: hecmw_rel_resid_l2_66
313  type ( hecmwst_local_mesh ), intent(in) :: hecmesh
314  type ( hecmwst_matrix ), intent(in) :: hecmat
315  real(kind=kreal), intent(inout) :: time_ax
316  real(kind=kreal), intent(inout), optional :: commtime
317 
318  real(kind=kreal), allocatable :: r(:)
319  real(kind=kreal) :: bnorm2, rnorm2
320  real(kind=kreal) :: tcomm
321 
322  allocate(r(hecmat%NDOF*hecmat%NP))
323 
324  tcomm = 0.d0
325  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, &
326  hecmat%B, hecmat%B, bnorm2, tcomm)
327  if (bnorm2 == 0.d0) then
328  bnorm2 = 1.d0
329  endif
330  call hecmw_matresid_66(hecmesh, hecmat, hecmat%X, hecmat%B, r, time_ax, tcomm)
331  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, r, r, rnorm2, tcomm)
332  hecmw_rel_resid_l2_66 = sqrt(rnorm2 / bnorm2)
333 
334  if (present(commtime)) commtime = commtime + tcomm
335 
336  deallocate(r)
337  end function hecmw_rel_resid_l2_66
338 
339 end module hecmw_solver_las_66
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, public hecmw_matresid_66(hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
real(kind=kreal) function, public hecmw_rel_resid_l2_66(hecMESH, hecMAT, time_Ax, COMMtime)
subroutine, public hecmw_matvec_66(hecMESH, hecMAT, X, Y, time_Ax, 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)