FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SSOR_44.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 
6 !C
7 !C***
8 !C*** module hecmw_precond_SSOR_44
9 !C***
10 !C
12  use hecmw_util
17 #ifndef _OPENACC
18  !$ use omp_lib
19 #endif
20 
21  private
22 
26 
27  integer(kind=kint) :: N
28  real(kind=kreal), pointer :: d(:) => null()
29  real(kind=kreal), pointer :: al(:) => null()
30  real(kind=kreal), pointer :: au(:) => null()
31  integer(kind=kint), pointer :: indexL(:) => null()
32  integer(kind=kint), pointer :: indexU(:) => null()
33  integer(kind=kint), pointer :: itemL(:) => null()
34  integer(kind=kint), pointer :: itemU(:) => null()
35  real(kind=kreal), pointer :: alu(:) => null()
36 
37  integer(kind=kint) :: NColor
38  integer(kind=kint), pointer :: COLORindex(:) => null()
39  integer(kind=kint), pointer :: perm(:) => null()
40  integer(kind=kint), pointer :: iperm(:) => null()
41 
42  logical, save :: isFirst = .true.
43 
44  logical, save :: INITIALIZED = .false.
45 
46 contains
47 
48  subroutine hecmw_precond_ssor_44_setup(hecMAT)
49  implicit none
50  type(hecmwst_matrix), intent(inout) :: hecmat
51  integer(kind=kint ) :: npl, npu
52  integer(kind=kint ) :: ncolor_in
53  real (kind=kreal) :: sigma_diag
54  real (kind=kreal) :: alutmp(4,4), pw(4)
55  integer(kind=kint ) :: ii, i, j, k
56  integer(kind=kint ) :: nthreads = 1
57  integer(kind=kint ), allocatable :: perm_tmp(:)
58  !real (kind=kreal) :: t0
59 
60  !t0 = hecmw_Wtime()
61  !write(*,*) 'DEBUG: SSOR setup start', hecmw_Wtime()-t0
62 
63  if (initialized) then
64  if (hecmat%Iarray(98) == 1) then ! need symbolic and numerical setup
65  call hecmw_precond_ssor_44_clear(hecmat)
66  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
67  call hecmw_precond_ssor_44_clear(hecmat) ! TEMPORARY
68  else
69  return
70  endif
71  endif
72 
73 #ifndef _OPENACC
74  !$ nthreads = omp_get_max_threads()
75 #endif
76 
77  n = hecmat%N
78  ! N = hecMAT%NP
79  ncolor_in = hecmw_mat_get_ncolor_in(hecmat)
80  sigma_diag = hecmw_mat_get_sigma_diag(hecmat)
81 
82 #ifdef _OPENACC
83  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
84  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
85  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
86  !write(*,*) 'DEBUG: RCM ordering done', hecmw_Wtime()-t0
87  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
88  hecmat%indexU, hecmat%itemU, perm_tmp, &
89  ncolor_in, ncolor, colorindex, perm, iperm)
90  !write(*,*) 'DEBUG: MC ordering done', hecmw_Wtime()-t0
91  deallocate(perm_tmp)
92 
93  !call write_debug_info
94 #else
95  if (nthreads == 1) then
96  ncolor = 1
97  allocate(colorindex(0:1), perm(n), iperm(n))
98  colorindex(0) = 0
99  colorindex(1) = n
100  do i=1,n
101  perm(i) = i
102  iperm(i) = i
103  end do
104  else
105  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
106  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
107  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
108  !write(*,*) 'DEBUG: RCM ordering done', hecmw_Wtime()-t0
109  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
110  hecmat%indexU, hecmat%itemU, perm_tmp, &
111  ncolor_in, ncolor, colorindex, perm, iperm)
112  !write(*,*) 'DEBUG: MC ordering done', hecmw_Wtime()-t0
113  deallocate(perm_tmp)
114 
115  !call write_debug_info
116  endif
117 #endif
118 
119  npl = hecmat%indexL(n)
120  npu = hecmat%indexU(n)
121  allocate(indexl(0:n), indexu(0:n), iteml(npl), itemu(npu))
122  call hecmw_matrix_reorder_profile(n, perm, iperm, &
123  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
124  indexl, indexu, iteml, itemu)
125  !write(*,*) 'DEBUG: reordering profile done', hecmw_Wtime()-t0
126 
127  !call check_ordering
128 
129  allocate(d(16*n), al(16*npl), au(16*npu))
130  call hecmw_matrix_reorder_values(n, 4, perm, iperm, &
131  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
132  hecmat%AL, hecmat%AU, hecmat%D, &
133  indexl, indexu, iteml, itemu, al, au, d)
134  !write(*,*) 'DEBUG: reordering values done', hecmw_Wtime()-t0
135 
136  call hecmw_matrix_reorder_renum_item(n, perm, indexl, iteml)
137  call hecmw_matrix_reorder_renum_item(n, perm, indexu, itemu)
138 
139  allocate(alu(16*n))
140  alu = 0.d0
141 
142  do ii= 1, 16*n
143  alu(ii) = d(ii)
144  enddo
145 
146 #ifdef _OPENACC
147  !$acc kernels
148  !$acc loop independent private(ALUtmp,PW)
149 #else
150  !$omp parallel default(none),private(ii,ALUtmp,k,i,j,PW),shared(N,ALU,SIGMA_DIAG)
151  !$omp do
152 #endif
153  do ii= 1, n
154  alutmp(1,1)= alu(16*ii-15) * sigma_diag
155  alutmp(1,2)= alu(16*ii-14)
156  alutmp(1,3)= alu(16*ii-13)
157  alutmp(1,4)= alu(16*ii-12)
158  alutmp(2,1)= alu(16*ii-11)
159  alutmp(2,2)= alu(16*ii-10) * sigma_diag
160  alutmp(2,3)= alu(16*ii- 9)
161  alutmp(2,4)= alu(16*ii- 8)
162  alutmp(3,1)= alu(16*ii- 7)
163  alutmp(3,2)= alu(16*ii- 6)
164  alutmp(3,3)= alu(16*ii- 5) * sigma_diag
165  alutmp(3,4)= alu(16*ii- 4)
166  alutmp(4,1)= alu(16*ii- 3)
167  alutmp(4,2)= alu(16*ii- 2)
168  alutmp(4,3)= alu(16*ii- 1)
169  alutmp(4,4)= alu(16*ii ) * sigma_diag
170 
171  do k= 1, 4
172  alutmp(k,k)= 1.d0/alutmp(k,k)
173  do i= k+1, 4
174  alutmp(i,k)= alutmp(i,k) * alutmp(k,k)
175  do j= k+1, 4
176  pw(j)= alutmp(i,j) - alutmp(i,k)*alutmp(k,j)
177  enddo
178  do j= k+1, 4
179  alutmp(i,j)= pw(j)
180  enddo
181  enddo
182  enddo
183  alu(16*ii-15)= alutmp(1,1)
184  alu(16*ii-14)= alutmp(1,2)
185  alu(16*ii-13)= alutmp(1,3)
186  alu(16*ii-12)= alutmp(1,4)
187  alu(16*ii-11)= alutmp(2,1)
188  alu(16*ii-10)= alutmp(2,2)
189  alu(16*ii- 9)= alutmp(2,3)
190  alu(16*ii- 8)= alutmp(2,4)
191  alu(16*ii- 7)= alutmp(3,1)
192  alu(16*ii- 6)= alutmp(3,2)
193  alu(16*ii- 5)= alutmp(3,3)
194  alu(16*ii- 4)= alutmp(3,4)
195  alu(16*ii- 3)= alutmp(4,1)
196  alu(16*ii- 2)= alutmp(4,2)
197  alu(16*ii- 1)= alutmp(4,3)
198  alu(16*ii )= alutmp(4,4)
199 
200  enddo
201 #ifdef _OPENACC
202  !$acc end kernels
203 #else
204  !$omp end do
205  !$omp end parallel
206 #endif
207 
208  isfirst = .true.
209 
210  initialized = .true.
211  hecmat%Iarray(98) = 0 ! symbolic setup done
212  hecmat%Iarray(97) = 0 ! numerical setup done
213 
214  !write(*,*) 'DEBUG: SSOR setup done', hecmw_Wtime()-t0
215 
216  end subroutine hecmw_precond_ssor_44_setup
217 
219  use hecmw_tuning_fx
220  implicit none
221  real(kind=kreal), intent(inout) :: zp(:)
222  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k
223  real(kind=kreal) :: sw1, sw2, sw3, sw4, x1, x2, x3, x4
224 
225  ! added for tuning >>>
226  integer(kind=kint), parameter :: numofblockperthread = 100
227  integer(kind=kint), save :: numofthread = 1, numofblock
228  integer(kind=kint), save, allocatable :: ictoblockindex(:)
229  integer(kind=kint), save, allocatable :: blockindextocolorindex(:)
230  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
231  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
232  real(kind=kreal) :: numofelementperblock
233  integer(kind=kint) :: my_rank
234 
235 #ifndef _OPENACC
236  if (isfirst) then
237  !$ numOfThread = omp_get_max_threads()
238  numofblock = numofthread * numofblockperthread
239  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
240  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
241  allocate (ictoblockindex(0:ncolor), &
242  blockindextocolorindex(0:numofblock + ncolor))
243  numofelement = n + indexl(n) + indexu(n)
244  numofelementperblock = dble(numofelement) / numofblock
245  blockindex = 0
246  ictoblockindex = -1
247  ictoblockindex(0) = 0
248  blockindextocolorindex = -1
249  blockindextocolorindex(0) = 0
250  my_rank = hecmw_comm_get_rank()
251  ! write(9000+my_rank,*) &
252  ! '# numOfElementPerBlock =', numOfElementPerBlock
253  ! write(9000+my_rank,*) &
254  ! '# ic, blockIndex, colorIndex, elementCount'
255  do ic = 1, ncolor
256  elementcount = 0
257  ii = 1
258  do i = colorindex(ic-1)+1, colorindex(ic)
259  elementcount = elementcount + 1
260  elementcount = elementcount + (indexl(i) - indexl(i-1))
261  elementcount = elementcount + (indexu(i) - indexu(i-1))
262  if (elementcount > ii * numofelementperblock &
263  .or. i == colorindex(ic)) then
264  ii = ii + 1
265  blockindex = blockindex + 1
266  blockindextocolorindex(blockindex) = i
267  ! write(9000+my_rank,*) ic, blockIndex, &
268  ! blockIndexToColorIndex(blockIndex), elementCount
269  endif
270  enddo
271  ictoblockindex(ic) = blockindex
272  enddo
273  numofblock = blockindex
274 
276  sectorcachesize0, sectorcachesize1 )
277 
278  isfirst = .false.
279  endif
280 #endif
281  ! <<< added for tuning
282 
283 #ifndef _OPENACC
284  !call start_collection("loopInPrecond44")
285 
286  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
287  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
288 
289  !$omp parallel default(none) &
290  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
291  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex) &
292  !$omp&private(SW1,SW2,SW3,SW4,X1,X2,X3,X4,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
293 #endif
294 
295  !C-- FORWARD
296  do ic=1,ncolor
297 #ifdef _OPENACC
298  !$acc kernels
299  !$acc loop independent
300  do i = colorindex(ic-1)+1, colorindex(ic)
301 #else
302  !$omp do schedule (static, 1)
303  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
304  do i = blockindextocolorindex(blockindex-1)+1, &
305  blockindextocolorindex(blockindex)
306 #endif
307  ! do i = startPos(threadNum, ic), endPos(threadNum, ic)
308  iold = perm(i)
309  sw1= zp(4*iold-3)
310  sw2= zp(4*iold-2)
311  sw3= zp(4*iold-1)
312  sw4= zp(4*iold )
313  isl= indexl(i-1)+1
314  iel= indexl(i)
315  do j= isl, iel
316  !k= perm(itemL(j))
317  k= iteml(j)
318  x1= zp(4*k-3)
319  x2= zp(4*k-2)
320  x3= zp(4*k-1)
321  x4= zp(4*k )
322  sw1= sw1 - al(16*j-15)*x1 - al(16*j-14)*x2 - al(16*j-13)*x3 - al(16*j-12)*x4
323  sw2= sw2 - al(16*j-11)*x1 - al(16*j-10)*x2 - al(16*j- 9)*x3 - al(16*j- 8)*x4
324  sw3= sw3 - al(16*j- 7)*x1 - al(16*j- 6)*x2 - al(16*j- 5)*x3 - al(16*j- 4)*x4
325  sw4= sw4 - al(16*j- 3)*x1 - al(16*j- 2)*x2 - al(16*j- 1)*x3 - al(16*j- 0)*x4
326  enddo ! j
327 
328  x1= sw1
329  x2= sw2
330  x3= sw3
331  x4= sw4
332  x2= x2 - alu(16*i-11)*x1
333  x3= x3 - alu(16*i- 7)*x1 - alu(16*i- 6)*x2
334  x4= x4 - alu(16*i- 3)*x1 - alu(16*i- 2)*x2 - alu(16*i- 1)*x3
335 
336  x4= alu(16*i )* x4
337  x3= alu(16*i- 5)*( x3 - alu(16*i- 4)*x4 )
338  x2= alu(16*i-10)*( x2 - alu(16*i- 8)*x4 - alu(16*i- 9)*x3 )
339  x1= alu(16*i-15)*( x1 - alu(16*i-12)*x4 - alu(16*i-13)*x3 - alu(16*i-14)*x2 )
340 
341  zp(4*iold-3)= x1
342  zp(4*iold-2)= x2
343  zp(4*iold-1)= x3
344  zp(4*iold )= x4
345 #ifdef _OPENACC
346  enddo
347  !$acc end kernels
348 #else
349  enddo ! i
350  enddo ! blockIndex
351  !$omp end do
352 #endif
353  enddo ! ic
354 
355  !C-- BACKWARD
356  do ic=ncolor, 1, -1
357 #ifdef _OPENACC
358  !$acc kernels
359  !$acc loop independent
360  do i = colorindex(ic-1)+1, colorindex(ic)
361 #else
362  !$omp do schedule (static, 1)
363  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
364  do i = blockindextocolorindex(blockindex), &
365  blockindextocolorindex(blockindex-1)+1, -1
366 #endif
367  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
368  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
369  ! blockIndexToColorIndex(blockIndex)
370  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
371  sw1= 0.d0
372  sw2= 0.d0
373  sw3= 0.d0
374  sw4= 0.d0
375  isu= indexu(i-1) + 1
376  ieu= indexu(i)
377  do j= ieu, isu, -1
378  !k= perm(itemU(j))
379  k= itemu(j)
380  x1= zp(4*k-3)
381  x2= zp(4*k-2)
382  x3= zp(4*k-1)
383  x4= zp(4*k )
384  sw1= sw1 + au(16*j-15)*x1 + au(16*j-14)*x2 + au(16*j-13)*x3 + au(16*j-12)*x4
385  sw2= sw2 + au(16*j-11)*x1 + au(16*j-10)*x2 + au(16*j- 9)*x3 + au(16*j- 8)*x4
386  sw3= sw3 + au(16*j- 7)*x1 + au(16*j- 6)*x2 + au(16*j- 5)*x3 + au(16*j- 4)*x4
387  sw4= sw4 + au(16*j- 3)*x1 + au(16*j- 2)*x2 + au(16*j- 1)*x3 + au(16*j- 0)*x4
388 
389  enddo ! j
390 
391  x1= sw1
392  x2= sw2
393  x3= sw3
394  x4= sw4
395  x2= x2 - alu(16*i-11)*x1
396  x3= x3 - alu(16*i- 7)*x1 - alu(16*i- 6)*x2
397  x4= x4 - alu(16*i- 3)*x1 - alu(16*i- 2)*x2 - alu(16*i- 1)*x3
398  x4= alu(16*i )* x4
399  x3= alu(16*i- 5)*( x3 - alu(16*i- 4)*x4 )
400  x2= alu(16*i-10)*( x2 - alu(16*i- 8)*x4 - alu(16*i- 9)*x3 )
401  x1= alu(16*i-15)*( x1 - alu(16*i-12)*x4 - alu(16*i-13)*x3 - alu(16*i-14)*x2 )
402  iold = perm(i)
403  zp(4*iold-3)= zp(4*iold-3) - x1
404  zp(4*iold-2)= zp(4*iold-2) - x2
405  zp(4*iold-1)= zp(4*iold-1) - x3
406  zp(4*iold )= zp(4*iold ) - x4
407 #ifdef _OPENACC
408  enddo
409  !$acc end kernels
410 #else
411  enddo ! i
412  enddo ! blockIndex
413  !$omp end do
414 #endif
415  enddo ! ic
416 #ifndef _OPENACC
417  !$omp end parallel
418 
419  !OCL END_CACHE_SUBSECTOR
420  !OCL END_CACHE_SECTOR_SIZE
421 
422  !call stop_collection("loopInPrecond44")
423 #endif
424 
425  end subroutine hecmw_precond_ssor_44_apply
426 
427  subroutine hecmw_precond_ssor_44_clear(hecMAT)
428  implicit none
429  type(hecmwst_matrix), intent(inout) :: hecmat
430  integer(kind=kint ) :: nthreads = 1
431 #ifndef _OPENACC
432  !$ nthreads = omp_get_max_threads()
433 #endif
434  if (associated(colorindex)) deallocate(colorindex)
435  if (associated(perm)) deallocate(perm)
436  if (associated(iperm)) deallocate(iperm)
437  if (associated(alu)) deallocate(alu)
438  if (nthreads >= 1) then
439  if (associated(d)) deallocate(d)
440  if (associated(al)) deallocate(al)
441  if (associated(au)) deallocate(au)
442  if (associated(indexl)) deallocate(indexl)
443  if (associated(indexu)) deallocate(indexu)
444  if (associated(iteml)) deallocate(iteml)
445  if (associated(itemu)) deallocate(itemu)
446  end if
447  nullify(colorindex)
448  nullify(perm)
449  nullify(iperm)
450  nullify(alu)
451  nullify(d)
452  nullify(al)
453  nullify(au)
454  nullify(indexl)
455  nullify(indexu)
456  nullify(iteml)
457  nullify(itemu)
458  end subroutine hecmw_precond_ssor_44_clear
459 
460  subroutine write_debug_info
461  implicit none
462  integer(kind=kint) :: my_rank, ic, in
463  my_rank = hecmw_comm_get_rank()
464  !--------------------> debug: shizawa
465  if (my_rank.eq.0) then
466  write(*,*) 'DEBUG: Output fort.19000+myrank and fort.29000+myrank for coloring information'
467  endif
468  write(19000+my_rank,'(a)') '#NCOLORTot'
469  write(19000+my_rank,*) ncolor
470  write(19000+my_rank,'(a)') '#ic COLORindex(ic-1)+1 COLORindex(ic)'
471  do ic=1,ncolor
472  write(19000+my_rank,*) ic, colorindex(ic-1)+1,colorindex(ic)
473  enddo ! ic
474  write(29000+my_rank,'(a)') '#n_node'
475  write(29000+my_rank,*) n
476  write(29000+my_rank,'(a)') '#in OLDtoNEW(in) NEWtoOLD(in)'
477  do in=1,n
478  write(29000+my_rank,*) in, iperm(in), perm(in)
479  if (perm(iperm(in)) .ne. in) then
480  write(29000+my_rank,*) '** WARNING **: NEWtoOLD and OLDtoNEW: ',in
481  endif
482  enddo
483  end subroutine write_debug_info
484 
485  subroutine check_ordering
486  implicit none
487  integer(kind=kint) :: ic, i, j, k
488  integer(kind=kint), allocatable :: iicolor(:)
489  ! check color dependence of neighbouring nodes
490  if (ncolor.gt.1) then
491  allocate(iicolor(n))
492  do ic=1,ncolor
493  do i= colorindex(ic-1)+1, colorindex(ic)
494  iicolor(i) = ic
495  enddo ! i
496  enddo ! ic
497  ! FORWARD: L-part
498  do ic=1,ncolor
499  do i= colorindex(ic-1)+1, colorindex(ic)
500  do j= indexl(i-1)+1, indexl(i)
501  k= iteml(j)
502  if (iicolor(i).eq.iicolor(k)) then
503  write(*,*) .eq.'** ERROR **: L-part: iicolor(i)iicolor(k)',i,k,iicolor(i)
504  endif
505  enddo ! j
506  enddo ! i
507  enddo ! ic
508  ! BACKWARD: U-part
509  do ic=ncolor, 1, -1
510  do i= colorindex(ic), colorindex(ic-1)+1, -1
511  do j= indexu(i-1)+1, indexu(i)
512  k= itemu(j)
513  if (iicolor(i).eq.iicolor(k)) then
514  write(*,*) .eq.'** ERROR **: U-part: iicolor(i)iicolor(k)',i,k,iicolor(i)
515  endif
516  enddo ! j
517  enddo ! i
518  enddo ! ic
519  deallocate(iicolor)
520  endif ! if (NColor.gt.1)
521  !--------------------< debug: shizawa
522  end subroutine check_ordering
523 
524 end module hecmw_precond_ssor_44
real(kind=kreal) function, public hecmw_mat_get_sigma_diag(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_ncolor_in(hecMAT)
subroutine, public hecmw_matrix_reorder_values(N, NDOF, perm, iperm, indexL, indexU, itemL, itemU, AL, AU, D, indexLp, indexUp, itemLp, itemUp, ALp, AUp, Dp)
subroutine, public hecmw_matrix_reorder_renum_item(N, perm, indexXp, itemXp)
subroutine, public hecmw_matrix_reorder_profile(N, perm, iperm, indexL, indexU, itemL, itemU, indexLp, indexUp, itemLp, itemUp)
subroutine, public hecmw_precond_ssor_44_clear(hecMAT)
subroutine, public hecmw_precond_ssor_44_apply(ZP)
subroutine, public hecmw_precond_ssor_44_setup(hecMAT)
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()
subroutine, public hecmw_matrix_ordering_rcm(N, indexL, itemL, indexU, itemU, perm, iperm)
subroutine, public hecmw_matrix_ordering_mc(N, indexL, itemL, indexU, itemU, perm_cur, ncolor_in, ncolor_out, COLORindex, perm, iperm)