FrontISTR  6.0.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 #ifdef HECMW_ARCH_FX64
30 
31  integer(kind=kint), save :: N, NP, NZIN
32  integer(kind=kint), allocatable, save :: index_i(:), item_i(:)
33  real(kind=kreal), allocatable, save :: a_i(:)
34 #endif
35 
36  ! added for tuning >>>
37  integer, parameter :: numOfBlockPerThread = 100
38  logical, save :: isFirst = .true.
39  integer, save :: numOfThread = 1
40  integer, save, allocatable :: startPos(:), endPos(:)
41  integer(kind=kint), save :: sectorCacheSize0, sectorCacheSize1
42  ! <<< added for tuning
43 
44 contains
45 
46  !C
47  !C***
48  !C*** hecmw_matvec_33_setup
49  !C***
50  !C
51  subroutine hecmw_matvec_33_setup (hecMESH, hecMAT)
52  use hecmw_util
53  use hecmw_jad_type
54  implicit none
55  type (hecmwst_local_mesh), intent(in) :: hecmesh
56  type (hecmwst_matrix), intent(in), target :: hecmat
57 
58  ! JAD takes over the whole matvec, so the tuned implementations must stay out of it
59  if (hecmw_jad_is_initialized().ne.0) return
60 
61  matvec_impl = hecmw_mat_get_matvec_impl(hecmat)
62  if (matvec_impl == hecmw_matvec_impl_csr) call hecmw_matvec_setup_33(hecmesh, hecmat)
63  end subroutine hecmw_matvec_33_setup
64 
65  subroutine hecmw_matvec_setup_33 (hecMESH, hecMAT)
66  use hecmw_jad_type
68  implicit none
69  type (hecmwST_local_mesh), intent(in) :: hecMESH
70  type (hecmwST_matrix), intent(in), target :: hecMAT
71 #ifdef HECMW_ARCH_FX64
72 
73  integer(kind=kint) :: i, j, k
74 
75  if (hecmw_jad_is_initialized().ne.0) return
76 
77  n = hecmat%N
78  np = hecmat%NP
79  if( allocated(index_i) ) deallocate(index_i)
80  if( allocated(item_i) ) deallocate(item_i)
81  if( allocated(a_i) ) deallocate(a_i)
82  !if( allocated(index_o) ) deallocate(index_o)
83  !if( allocated(item_o) ) deallocate(item_o)
84  !if( allocated(A_o) ) deallocate(A_o)
85 
86  !count nonzero elements
87  nzin = hecmat%indexL(n) + n + hecmat%indexU(n)
88  !NZOUT = 0
89  !! upper
90  !do i=1,N
91  ! do k=hecMAT%indexU(i-1)+1,hecMAT%indexU(i)
92  ! j = hecMAT%itemU(k)
93  ! if( j > N ) NZOUT = NZOUT + 1
94  ! end do
95  !end do
96  !NZIN = NZIN - NZOUT
97 
98  allocate(index_i(0:n),item_i(3*nzin),a_i(9*nzin))
99  !allocate(index_o(0:N),item_o(3*NZOUT),A_o(9*NZOUT))
100 
101  ! set value
102  nzin = 0
103  !NZOUT = 0
104  index_i(0) = 0
105  !index_o(0) = 0
106  do i=1,n
107  ! lower
108  do k=hecmat%indexL(i-1)+1,hecmat%indexL(i)
109  j = hecmat%itemL(k)
110  item_i(nzin+1) = 3*j-2
111  item_i(nzin+2) = 3*j-1
112  item_i(nzin+3) = 3*j
113  nzin = nzin + 3
114  a_i(3*nzin-8:3*nzin) = hecmat%AL(9*k-8:9*k)
115  call hecmw_mat_block_transpose_33(a_i(3*nzin-8:3*nzin))
116  end do
117  ! diag
118  item_i(nzin+1) = 3*i-2
119  item_i(nzin+2) = 3*i-1
120  item_i(nzin+3) = 3*i
121  nzin = nzin + 3
122  a_i(3*nzin-8:3*nzin) = hecmat%D(9*i-8:9*i)
123  call hecmw_mat_block_transpose_33(a_i(3*nzin-8:3*nzin))
124  ! upper
125  do k=hecmat%indexU(i-1)+1,hecmat%indexU(i)
126  j = hecmat%itemU(k)
127  !if( j > N ) then
128  ! item_o(NZOUT+1) = 3*j-2
129  ! item_o(NZOUT+2) = 3*j-1
130  ! item_o(NZOUT+3) = 3*j
131  ! NZOUT = NZOUT + 3
132  ! A_o(3*NZOUT-8:3*NZOUT) = hecMAT%AU(9*k-8:9*k)
133  ! call hecmw_mat_block_transpose_33(A_o(3*NZOUT-8:3*NZOUT))
134  !else
135  item_i(nzin+1) = 3*j-2
136  item_i(nzin+2) = 3*j-1
137  item_i(nzin+3) = 3*j
138  nzin = nzin + 3
139  a_i(3*nzin-8:3*nzin) = hecmat%AU(9*k-8:9*k)
140  call hecmw_mat_block_transpose_33(a_i(3*nzin-8:3*nzin))
141  !end if
142  end do
143 
144  index_i(i) = nzin
145  !index_o(i) = NZOUT
146  end do
147 
148 #endif
149  end subroutine hecmw_matvec_setup_33
150 
151  !C
152  !C***
153  !C*** hecmw_matvec_33_teardown
154  !C***
155  !C
157  implicit none
158 
159 #ifdef HECMW_ARCH_FX64
160  if( allocated(index_i) ) deallocate(index_i)
161  if( allocated(item_i) ) deallocate(item_i)
162  if( allocated(a_i) ) deallocate(a_i)
163 #endif
164  matvec_impl = hecmw_matvec_impl_bsr
165  end subroutine hecmw_matvec_33_teardown
166 
167  !C
168  !C***
169  !C*** hecmw_matvec_33
170  !C***
171  !C
172  subroutine hecmw_matvec_33 (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
173  use hecmw_util
174  use hecmw_jad_type
175  use m_hecmw_comm_f
176 
177  implicit none
178  type (hecmwst_local_mesh), intent(in) :: hecmesh
179  type (hecmwst_matrix), intent(in), target :: hecmat
180  real(kind=kreal), intent(inout) :: x(:)
181  real(kind=kreal), intent(out) :: y(:)
182  real(kind=kreal), intent(inout) :: time_ax
183  real(kind=kreal), intent(inout), optional :: commtime
184 
185  real(kind=kreal) :: start_time, end_time, tcomm
186 
187  if (hecmw_jad_is_initialized().ne.0) then
188  tcomm = 0.d0
189  start_time = hecmw_wtime()
190  call hecmw_jad_matvec(hecmesh, hecmat, x, y, tcomm)
191  end_time = hecmw_wtime()
192  time_ax = time_ax + end_time - start_time - tcomm
193  if (present(commtime)) commtime = commtime + tcomm
194  else
195  select case (matvec_impl)
196  case (hecmw_matvec_impl_bsr)
197  call hecmw_matvec_33_generic(hecmesh, hecmat, x, y, time_ax, commtime)
198 #ifdef HECMW_ARCH_FX64
199  case (hecmw_matvec_impl_csr)
200  call hecmw_matvec_33_csr(hecmesh, hecmat, x, y, time_ax, commtime)
201 #endif
202  case default
203  if (.not. matvec_impl_missing_reported) then
204  matvec_impl_missing_reported = .true.
205  if (hecmw_comm_get_rank() == 0) write(*,'(a)') &
206  '#### MATRIXFORMAT: this build has no matvec for the selected format '// &
207  '-- running the BSR implementation'
208  endif
209  call hecmw_matvec_33_generic(hecmesh, hecmat, x, y, time_ax, commtime)
210  end select
211  endif
212  end subroutine hecmw_matvec_33
213 
214  !C
215  !C***
216  !C*** hecmw_matvec_33_generic ( private subroutine )
217  !C***
218  !C
219  subroutine hecmw_matvec_33_generic (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
220  use hecmw_util
221  use m_hecmw_comm_f
222  !$ use omp_lib
223 
224  implicit none
225  type (hecmwST_local_mesh), intent(in) :: hecMESH
226  type (hecmwST_matrix), intent(in), target :: hecMAT
227  real(kind=kreal), intent(inout) :: x(:)
228  real(kind=kreal), intent(out) :: y(:)
229  real(kind=kreal), intent(inout) :: time_ax
230  real(kind=kreal), intent(inout), optional :: commtime
231 
232  real(kind=kreal) :: start_time, end_time
233  integer(kind=kint) :: i, j, jS, jE, in
234  real(kind=kreal) :: yv1, yv2, yv3, x1, x2, x3
235 
236  integer(kind=kint) :: N, NP
237  integer(kind=kint), pointer :: indexL(:), itemL(:), indexU(:), itemU(:), indexA(:), itemA(:)
238  real(kind=kreal), pointer :: al(:), au(:), d(:), a(:)
239 
240  ! added for tuning >>>
241  integer(kind=kint) :: threadNum, blockNum, numOfBlock
242  integer(kind=kint) :: blockIndex
243  ! <<< added for tuning
244 
245  n = hecmat%N
246  np = hecmat%NP
247  indexl => hecmat%indexL
248  indexu => hecmat%indexU
249  indexa => hecmat%indexA
250  iteml => hecmat%itemL
251  itemu => hecmat%itemU
252  itema => hecmat%itemA
253  al => hecmat%AL
254  au => hecmat%AU
255  d => hecmat%D
256  a => hecmat%A
257 
258  ! added for tuning >>>
259 #ifndef _OPENACC
260  if (.not. isfirst) then
261  numofblock = numofthread * numofblockperthread
262  if (endpos(numofblock-1) .ne. n-1) then
263  deallocate(startpos, endpos)
264  isfirst = .true.
265  endif
266  endif
267  if (isfirst) then
268  call setup_tuning_parameters(n, np, indexl, indexu)
269  isfirst = .false.
270  endif
271 #endif
272  ! <<< added for tuning
273 
274  start_time= hecmw_wtime()
275  call hecmw_update_r (hecmesh, x, np, 3)
276  end_time= hecmw_wtime()
277  if (present(commtime)) commtime = commtime + end_time - start_time
278 
279  start_time = hecmw_wtime()
280 
281 #ifdef _OPENACC
282  !$acc kernels
283  !$acc loop independent
284  do i = 1, n
285  x1= x(3*i-2)
286  x2= x(3*i-1)
287  x3= x(3*i )
288  yv1= 0
289  yv2= 0
290  yv3= 0
291  js= indexa(i-1) + 1
292  je= indexa(i)
293  do j = js, je
294  in = itema(j)
295  x1= x(3*in-2)
296  x2= x(3*in-1)
297  x3= x(3*in )
298  yv1= yv1 + a(9*j-8)*x1 + a(9*j-7)*x2 + a(9*j-6)*x3
299  yv2= yv2 + a(9*j-5)*x1 + a(9*j-4)*x2 + a(9*j-3)*x3
300  yv3= yv3 + a(9*j-2)*x1 + a(9*j-1)*x2 + a(9*j )*x3
301  enddo
302  y(3*i-2)= yv1
303  y(3*i-1)= yv2
304  y(3*i )= yv3
305  enddo
306  !$acc end kernels
307 #else
308  !call fapp_start("loopInMatvec33", 1, 0)
309  !call start_collection("loopInMatvec33")
310 
311  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
312  !OCL CACHE_SUBSECTOR_ASSIGN(X)
313 
314  !$OMP PARALLEL DEFAULT(NONE) &
315  !$OMP&PRIVATE(i,X1,X2,X3,YV1,YV2,YV3,jS,jE,j,in,threadNum,blockNum,blockIndex) &
316  !$OMP&SHARED(D,AL,AU,indexL,itemL,indexU,itemU,X,Y,startPos,endPos,numOfThread,N)
317  threadnum = 0
318  !$ threadNum = omp_get_thread_num()
319  do blocknum = 0 , numofblockperthread - 1
320  blockindex = blocknum * numofthread + threadnum
321  do i = startpos(blockindex), endpos(blockindex)
322  x1= x(3*i-2)
323  x2= x(3*i-1)
324  x3= x(3*i )
325  yv1= d(9*i-8)*x1 + d(9*i-7)*x2 + d(9*i-6)*x3
326  yv2= d(9*i-5)*x1 + d(9*i-4)*x2 + d(9*i-3)*x3
327  yv3= d(9*i-2)*x1 + d(9*i-1)*x2 + d(9*i )*x3
328 
329  js= indexl(i-1) + 1
330  je= indexl(i )
331  do j= js, je
332  in = iteml(j)
333  x1= x(3*in-2)
334  x2= x(3*in-1)
335  x3= x(3*in )
336  yv1= yv1 + al(9*j-8)*x1 + al(9*j-7)*x2 + al(9*j-6)*x3
337  yv2= yv2 + al(9*j-5)*x1 + al(9*j-4)*x2 + al(9*j-3)*x3
338  yv3= yv3 + al(9*j-2)*x1 + al(9*j-1)*x2 + al(9*j )*x3
339  enddo
340  js= indexu(i-1) + 1
341  je= indexu(i )
342  do j= js, je
343  in = itemu(j)
344  x1= x(3*in-2)
345  x2= x(3*in-1)
346  x3= x(3*in )
347  yv1= yv1 + au(9*j-8)*x1 + au(9*j-7)*x2 + au(9*j-6)*x3
348  yv2= yv2 + au(9*j-5)*x1 + au(9*j-4)*x2 + au(9*j-3)*x3
349  yv3= yv3 + au(9*j-2)*x1 + au(9*j-1)*x2 + au(9*j )*x3
350  enddo
351  y(3*i-2)= yv1
352  y(3*i-1)= yv2
353  y(3*i )= yv3
354  enddo
355  enddo
356  !$OMP END PARALLEL
357 
358  !OCL END_CACHE_SUBSECTOR
359  !OCL END_CACHE_SECTOR_SIZE
360 
361  !call stop_collection("loopInMatvec33")
362  !call fapp_stop("loopInMatvec33", 1, 0)
363 #endif
364 
365  end_time = hecmw_wtime()
366  time_ax = time_ax + end_time - start_time
367 
368  end subroutine hecmw_matvec_33_generic
369 
370  !C
371  !C***
372  !C*** hecmw_matvec_33_csr ( private subroutine )
373  !C***
374  !C
375  subroutine hecmw_matvec_33_csr (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
376  use hecmw_util
377  use m_hecmw_comm_f
378 
379  implicit none
380  type (hecmwST_local_mesh), intent(in) :: hecMESH
381  type (hecmwST_matrix), intent(in), target :: hecMAT
382  real(kind=kreal), intent(inout) :: x(:)
383  real(kind=kreal), intent(out) :: y(:)
384  real(kind=kreal), intent(inout) :: time_ax
385  real(kind=kreal), intent(inout), optional :: commtime
386 #ifdef HECMW_ARCH_FX64
387 
388  real(kind=kreal) :: start_time, end_time
389  integer(kind=kint) :: N, NP
390  integer(kind=kint) :: numOfBlock
391 
392  n = hecmat%N
393  np = hecmat%NP
394 
395  ! added for tuning >>>
396  if (.not. isfirst) then
397  numofblock = numofthread * numofblockperthread
398  if (endpos(numofblock-1) .ne. n-1) then
399  deallocate(startpos, endpos)
400  isfirst = .true.
401  endif
402  endif
403  if (isfirst) then
404  call setup_tuning_parameters(n, np, hecmat%indexL, hecmat%indexU)
405  isfirst = .false.
406  endif
407  numofblock = numofthread * numofblockperthread
408  ! <<< added for tuning
409 
410  start_time= hecmw_wtime()
411  call hecmw_update_r (hecmesh, x, np, 3)
412  end_time= hecmw_wtime()
413  if (present(commtime)) commtime = commtime + end_time - start_time
414 
415  start_time = hecmw_wtime()
416 
417  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
418  call hecmw_matvec_33_core(n,np,nzin,x,y,a_i,item_i,index_i, &
419  numofblock,numofthread,startpos,endpos)
420 
421  !OCL END_CACHE_SECTOR_SIZE
422 
423  end_time = hecmw_wtime()
424  time_ax = time_ax + end_time - start_time
425 
426 #endif
427  end subroutine hecmw_matvec_33_csr
428 
429  subroutine hecmw_matvec_33_core(N,NP,NNZ,X,Y,aval,item,idx,numOfBlock,numOfThread,startPos,endPos)
430  !$ use omp_lib
431  integer(kind=kint), intent(in) :: N
432  integer(kind=kint), intent(in) :: NP
433  integer(kind=kint), intent(in) :: NNZ
434  real(kind=kreal), intent(in) :: x(3*np)
435  real(kind=kreal), intent(inout) :: y(3*n)
436  real(kind=kreal), intent(in) :: aval(3*nnz)
437  integer(kind=kint), intent(in) :: item(NNZ)
438  integer(kind=kint), intent(in) :: idx(0:N)
439  integer(kind=kint), intent(in) :: numOfBlock
440  integer(kind=kint), intent(in) :: numOfThread
441  integer(kind=kint), intent(in) :: startPos(0:numOfBlock)
442  integer(kind=kint), intent(in) :: endPos(0:numOfBlock)
443 #ifdef HECMW_ARCH_FX64
444 
445  integer(kind=kint) :: i, j, jS, jE, in
446  real(kind=kreal) :: yv1, yv2, yv3, x1
447  integer(kind=kint) :: threadNum, blockNum, blockIndex
448 
449  !call fapp_start("loopInMatvec33", 1, 0)
450  !call start_collection("loopInMatvec33")
451 
452  !OCL CACHE_SUBSECTOR_ASSIGN(X)
453 
454  if( numofthread > 1 ) then
455 
456  !$OMP PARALLEL DEFAULT(NONE) &
457  !$OMP&PRIVATE(i,X1,YV1,YV2,YV3,j,threadNum,blockNum,blockIndex) &
458  !$OMP&SHARED(aval,item,idx,X,Y,startPos,endPos,numOfThread)
459  threadnum = 0
460  !$ threadNum = omp_get_thread_num()
461  do blocknum = 0 , numofblockperthread - 1
462  blockindex = blocknum * numofthread + threadnum
463  do i = startpos(blockindex), endpos(blockindex)
464  yv1= 0.d0
465  yv2= 0.d0
466  yv3= 0.d0
467 
468  do j= idx(i-1)+1, idx(i)
469  x1= x(item(j))
470  yv1= yv1 + aval(3*j-2)*x1
471  yv2= yv2 + aval(3*j-1)*x1
472  yv3= yv3 + aval(3*j )*x1
473  enddo
474 
475  y(3*i-2) = yv1
476  y(3*i-1) = yv2
477  y(3*i ) = yv3
478  enddo
479  enddo
480  !$OMP END PARALLEL
481 
482  else
483 
484  do i = 1, n
485  yv1= 0.d0
486  yv2= 0.d0
487  yv3= 0.d0
488 
489  do j= idx(i-1)+1, idx(i)
490  x1= x(item(j))
491  yv1= yv1 + aval(3*j-2)*x1
492  yv2= yv2 + aval(3*j-1)*x1
493  yv3= yv3 + aval(3*j )*x1
494  enddo
495 
496  y(3*i-2)= yv1
497  y(3*i-1)= yv2
498  y(3*i )= yv3
499  enddo
500 
501  end if
502 
503 
504  !OCL END_CACHE_SUBSECTOR
505 
506  !call stop_collection("loopInMatvec33")
507  !call fapp_stop("loopInMatvec33", 1, 0)
508 
509 #endif
510  end subroutine
511 
512  subroutine setup_tuning_parameters(N, NP, indexL, indexU)
513  use hecmw_tuning_fx
514  !$ use omp_lib
515  implicit none
516  integer(kind=kint), intent(in) :: N, NP
517  integer(kind=kint), pointer, intent(in) :: indexL(:), indexU(:)
518  integer(kind=kint) :: i, blockNum, numOfBlock
519  integer(kind=kint) :: numOfElement, elementCount
520  real(kind=kreal) :: numofelementperblock
521 
522  !$ numOfThread = omp_get_max_threads()
523  numofblock = numofthread * numofblockperthread
524  allocate (startpos(0 : numofblock - 1), endpos(0 : numofblock - 1))
525  numofelement = n + indexl(n) + indexu(n)
526  numofelementperblock = dble(numofelement) / numofblock
527  blocknum = 0
528  elementcount = 0
529  startpos(blocknum) = 1
530  do i= 1, n
531  elementcount = elementcount + 1
532  elementcount = elementcount + (indexl(i) - indexl(i-1))
533  elementcount = elementcount + (indexu(i) - indexu(i-1))
534  if (elementcount > (blocknum + 1) * numofelementperblock) then
535  endpos(blocknum) = i
536  ! write(9000+hecmw_comm_get_rank(),*) mod(blockNum, numOfThread), &
537  ! startPos(blockNum), endPos(blockNum)
538  blocknum = blocknum + 1
539  startpos(blocknum) = i + 1
540  if (blocknum == (numofblock - 1)) exit
541  endif
542  enddo
543  endpos(blocknum) = n
544  ! write(9000+hecmw_comm_get_rank(),*) mod(blockNum, numOfThread), &
545  ! startPos(blockNum), endPos(blockNum)
546  ! for irregular data
547  do i= blocknum+1, numofblock-1
548  startpos(i) = n
549  endpos(i) = n-1
550  ! write(9000+hecmw_comm_get_rank(),*) mod(i, numOfThread), &
551  ! startPos(i), endPos(i)
552  end do
553 
555  sectorcachesize0, sectorcachesize1)
556  end subroutine setup_tuning_parameters
557 
558  !C
559  !C***
560  !C*** hecmw_matresid_33
561  !C***
562  !C
563  subroutine hecmw_matresid_33 (hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
564  use hecmw_util
565  implicit none
566  type (hecmwst_local_mesh), intent(in) :: hecmesh
567  type (hecmwst_matrix), intent(in) :: hecmat
568  real(kind=kreal), intent(in) :: b(:)
569  real(kind=kreal), intent(inout) :: x(:)
570  real(kind=kreal), intent(out) :: r(:)
571  real(kind=kreal), intent(inout) :: time_ax
572  real(kind=kreal), intent(inout), optional :: commtime
573 
574  integer(kind=kint) :: i
575  real(kind=kreal) :: tcomm
576 
577  tcomm = 0.d0
578  call hecmw_matvec_33 (hecmesh, hecmat, x, r, time_ax, tcomm)
579  if (present(commtime)) commtime = commtime + tcomm
580 #ifdef _OPENACC
581  !$acc kernels
582  !$acc loop independent
583 #else
584  !$omp parallel default(none),private(i),shared(hecMAT,R,B)
585  !$omp do
586 #endif
587  do i = 1, hecmat%N * 3
588  r(i) = b(i) - r(i)
589  enddo
590 #ifdef _OPENACC
591  !$acc end kernels
592 #else
593  !$omp end do
594  !$omp end parallel
595 #endif
596  end subroutine hecmw_matresid_33
597 
598  !C
599  !C***
600  !C*** hecmw_rel_resid_L2_33
601  !C***
602  !C
603  function hecmw_rel_resid_l2_33 (hecMESH, hecMAT, time_Ax, COMMtime)
604  use hecmw_util
606  implicit none
607  real(kind=kreal) :: hecmw_rel_resid_l2_33
608  type ( hecmwst_local_mesh ), intent(in) :: hecmesh
609  type ( hecmwst_matrix ), intent(in) :: hecmat
610  real(kind=kreal), intent(inout) :: time_ax
611  real(kind=kreal), intent(inout), optional :: commtime
612 
613  real(kind=kreal), allocatable :: r(:)
614  real(kind=kreal) :: bnorm2, rnorm2
615  real(kind=kreal) :: tcomm
616 
617  allocate(r(hecmat%NDOF*hecmat%NP))
618 
619  tcomm = 0.d0
620  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, &
621  hecmat%B, hecmat%B, bnorm2, tcomm)
622  if (bnorm2 == 0.d0) then
623  bnorm2 = 1.d0
624  endif
625  call hecmw_matresid_33(hecmesh, hecmat, hecmat%X, hecmat%B, r, time_ax, tcomm)
626  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, r, r, rnorm2, tcomm)
627  hecmw_rel_resid_l2_33 = sqrt(rnorm2 / bnorm2)
628 
629  if (present(commtime)) commtime = commtime + tcomm
630 
631  deallocate(r)
632  end function hecmw_rel_resid_l2_33
633 
634  !C
635  !C***
636  !C*** hecmw_Tvec_33
637  !C***
638  !C
639  subroutine hecmw_tvec_33 (hecMESH, X, Y, COMMtime)
640  use hecmw_util
641  use m_hecmw_comm_f
642  implicit none
643  type (hecmwst_local_mesh), intent(in) :: hecmesh
644  real(kind=kreal), intent(inout) :: x(:)
645  real(kind=kreal), intent(out) :: y(:)
646  real(kind=kreal), intent(inout) :: commtime
647 
648  real(kind=kreal) :: start_time, end_time
649  integer(kind=kint) :: i, j, jj, k, kk
650 
651  start_time= hecmw_wtime()
652  call hecmw_update_r (hecmesh, x, hecmesh%n_node, 3)
653  end_time= hecmw_wtime()
654  commtime = commtime + end_time - start_time
655 
656 #ifdef _OPENACC
657  !$acc kernels
658  !$acc loop independent private(i)
659 #else
660  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y)
661  !$omp do
662 #endif
663  do i= 1, hecmesh%nn_internal * hecmesh%n_dof
664  y(i)= x(i)
665  enddo
666 #ifndef _OPENACC
667  !$omp end do
668 #endif
669 
670 #ifdef _OPENACC
671  !$acc loop independent private(i,k,kk,j,jj)
672 #else
673  !$omp do
674 #endif
675  outer: do i= 1, hecmesh%mpc%n_mpc
676  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
677  if (hecmesh%mpc%mpc_dof(j) > 3) cycle outer
678  enddo
679  k = hecmesh%mpc%mpc_index(i-1) + 1
680  kk = 3 * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
681  y(kk) = 0.d0
682  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
683  jj = 3 * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
684  y(kk) = y(kk) - hecmesh%mpc%mpc_val(j) * x(jj)
685  enddo
686  enddo outer
687 #ifdef _OPENACC
688  !$acc end kernels
689 #else
690  !$omp end do
691  !$omp end parallel
692 #endif
693 
694  end subroutine hecmw_tvec_33
695 
696  !C
697  !C***
698  !C*** hecmw_Ttvec_33
699  !C***
700  !C
701  subroutine hecmw_ttvec_33 (hecMESH, X, Y, COMMtime)
702  use hecmw_util
703  use m_hecmw_comm_f
704  implicit none
705  type (hecmwst_local_mesh), intent(in) :: hecmesh
706  real(kind=kreal), intent(inout) :: x(:)
707  real(kind=kreal), intent(inout) :: y(:)
708  real(kind=kreal), intent(inout) :: commtime
709 
710  real(kind=kreal) :: start_time, end_time
711  integer(kind=kint) :: i, j, jj, k, kk
712 
713  start_time= hecmw_wtime()
714  call hecmw_update_r (hecmesh, x, hecmesh%n_node, 3)
715  end_time= hecmw_wtime()
716  commtime = commtime + end_time - start_time
717 
718 #ifdef _OPENACC
719  !$acc kernels
720  !$acc loop independent private(i)
721 #else
722  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y)
723  !$omp do
724 #endif
725  do i= 1, hecmesh%nn_internal * hecmesh%n_dof
726  y(i)= x(i)
727  enddo
728 #ifndef _OPENACC
729  !$omp end do
730 #endif
731 
732 #ifdef _OPENACC
733  !$acc loop independent private(i,k,kk,j,jj)
734 #else
735  !$omp do
736 #endif
737  outer: do i= 1, hecmesh%mpc%n_mpc
738  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
739  if (hecmesh%mpc%mpc_dof(j) > 3) cycle outer
740  enddo
741  k = hecmesh%mpc%mpc_index(i-1) + 1
742  kk = 3 * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
743  y(kk) = 0.d0
744  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
745  jj = 3 * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
746 #ifdef _OPENACC
747  !$acc atomic update
748 #else
749  !$omp atomic
750 #endif
751  y(jj) = y(jj) - hecmesh%mpc%mpc_val(j) * x(kk)
752  !$acc end atomic
753  enddo
754  enddo outer
755 #ifdef _OPENACC
756  !$acc end kernels
757 #else
758  !$omp end do
759  !$omp end parallel
760 #endif
761 
762  end subroutine hecmw_ttvec_33
763 
764 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
subroutine, public hecmw_mat_block_transpose_33(mat)
integer(kind=kint) function, public hecmw_mat_get_matvec_impl(hecMAT)
integer(kind=kint), parameter, public hecmw_matvec_impl_bsr
integer(kind=kint), parameter, public hecmw_matvec_impl_csr
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 hecmw_matvec_setup_33(hecMESH, hecMAT)
subroutine, public hecmw_matvec_33_teardown
subroutine hecmw_matvec_33_csr(hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
subroutine, public hecmw_ttvec_33(hecMESH, X, Y, COMMtime)
subroutine hecmw_matvec_33_core(N, NP, NNZ, X, Y, aval, item, idx, numOfBlock, numOfThread, startPos, endPos)
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)