FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SSOR_11.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_11
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_11_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(1,1), pw(1)
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_11_clear(hecmat)
66  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
67  call hecmw_precond_ssor_11_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 #else
94  if (nthreads == 1) then
95  ncolor = 1
96  allocate(colorindex(0:1), perm(n), iperm(n))
97  colorindex(0) = 0
98  colorindex(1) = n
99  do i=1,n
100  perm(i) = i
101  iperm(i) = i
102  end do
103  else
104  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
105  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
106  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
107  !write(*,*) 'DEBUG: RCM ordering done', hecmw_Wtime()-t0
108  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
109  hecmat%indexU, hecmat%itemU, perm_tmp, &
110  ncolor_in, ncolor, colorindex, perm, iperm)
111  !write(*,*) 'DEBUG: MC ordering done', hecmw_Wtime()-t0
112  deallocate(perm_tmp)
113 
114  endif
115 #endif
116 
117  npl = hecmat%indexL(n)
118  npu = hecmat%indexU(n)
119  allocate(indexl(0:n), indexu(0:n), iteml(npl), itemu(npu))
120  call hecmw_matrix_reorder_profile(n, perm, iperm, &
121  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
122  indexl, indexu, iteml, itemu)
123  !write(*,*) 'DEBUG: reordering profile done', hecmw_Wtime()-t0
124 
125 
126  allocate(d(n), al(npl), au(npu))
127  call hecmw_matrix_reorder_values(n, 1, perm, iperm, &
128  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
129  hecmat%AL, hecmat%AU, hecmat%D, &
130  indexl, indexu, iteml, itemu, al, au, d)
131  !write(*,*) 'DEBUG: reordering values done', hecmw_Wtime()-t0
132 
133  call hecmw_matrix_reorder_renum_item(n, perm, indexl, iteml)
134  call hecmw_matrix_reorder_renum_item(n, perm, indexu, itemu)
135 
136  allocate(alu(n))
137  alu = 0.d0
138 
139  do ii= 1, n
140  alu(ii) = d(ii)
141  enddo
142 
143 #ifdef _OPENACC
144  !$acc kernels
145  !$acc loop independent private(ALUtmp)
146 #else
147  !$omp parallel default(none),private(ii,ALUtmp,k,i,j,PW),shared(N,ALU,SIGMA_DIAG)
148  !$omp do
149 #endif
150  do ii= 1, n
151  alutmp(1,1)= alu(ii) * sigma_diag
152  alutmp(1,1)= 1.d0/alutmp(1,1)
153  alu(ii)= alutmp(1,1)
154  enddo
155 #ifdef _OPENACC
156  !$acc end kernels
157 #else
158  !$omp end do
159  !$omp end parallel
160 #endif
161 
162  isfirst = .true.
163 
164  initialized = .true.
165  hecmat%Iarray(98) = 0 ! symbolic setup done
166  hecmat%Iarray(97) = 0 ! numerical setup done
167 
168  !write(*,*) 'DEBUG: SSOR setup done', hecmw_Wtime()-t0
169 
170  end subroutine hecmw_precond_ssor_11_setup
171 
173  use hecmw_tuning_fx
174  implicit none
175  real(kind=kreal), intent(inout) :: zp(:)
176  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k
177  real(kind=kreal) :: sw(1), x(1)
178 
179  ! added for tuning >>>
180  integer(kind=kint), parameter :: numofblockperthread = 100
181  integer(kind=kint), save :: numofthread = 1, numofblock
182  integer(kind=kint), save, allocatable :: ictoblockindex(:)
183  integer(kind=kint), save, allocatable :: blockindextocolorindex(:)
184  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
185  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
186  real(kind=kreal) :: numofelementperblock
187  integer(kind=kint) :: my_rank
188 
189 #ifndef _OPENACC
190  if (isfirst) then
191  !$ numOfThread = omp_get_max_threads()
192  numofblock = numofthread * numofblockperthread
193  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
194  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
195  allocate (ictoblockindex(0:ncolor), &
196  blockindextocolorindex(0:numofblock + ncolor))
197  numofelement = n + indexl(n) + indexu(n)
198  numofelementperblock = dble(numofelement) / numofblock
199  blockindex = 0
200  ictoblockindex = -1
201  ictoblockindex(0) = 0
202  blockindextocolorindex = -1
203  blockindextocolorindex(0) = 0
204  my_rank = hecmw_comm_get_rank()
205  ! write(9000+my_rank,*) &
206  ! '# numOfElementPerBlock =', numOfElementPerBlock
207  ! write(9000+my_rank,*) &
208  ! '# ic, blockIndex, colorIndex, elementCount'
209  do ic = 1, ncolor
210  elementcount = 0
211  ii = 1
212  do i = colorindex(ic-1)+1, colorindex(ic)
213  elementcount = elementcount + 1
214  elementcount = elementcount + (indexl(i) - indexl(i-1))
215  elementcount = elementcount + (indexu(i) - indexu(i-1))
216  if (elementcount > ii * numofelementperblock &
217  .or. i == colorindex(ic)) then
218  ii = ii + 1
219  blockindex = blockindex + 1
220  blockindextocolorindex(blockindex) = i
221  ! write(9000+my_rank,*) ic, blockIndex, &
222  ! blockIndexToColorIndex(blockIndex), elementCount
223  endif
224  enddo
225  ictoblockindex(ic) = blockindex
226  enddo
227  numofblock = blockindex
228 
230  sectorcachesize0, sectorcachesize1 )
231 
232  isfirst = .false.
233  endif
234 #endif
235  ! <<< added for tuning
236 
237 #ifndef _OPENACC
238  !call start_collection("loopInPrecond33")
239 
240  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
241  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
242 
243  !$omp parallel default(none) &
244  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
245  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex) &
246  !$omp&private(SW,X,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
247 #endif
248 
249  !C-- FORWARD
250  do ic=1,ncolor
251 #ifdef _OPENACC
252  !$acc kernels
253  !$acc loop independent private(X,SW)
254  do i = colorindex(ic-1)+1, colorindex(ic)
255 #else
256  !$omp do schedule (static, 1)
257  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
258  do i = blockindextocolorindex(blockindex-1)+1, &
259  blockindextocolorindex(blockindex)
260 #endif
261  iold = perm(i)
262  sw(1)= zp(iold)
263  isl= indexl(i-1)+1
264  iel= indexl(i)
265  do j= isl, iel
266  k= iteml(j)
267  x(1)= zp(k)
268  sw(1)= sw(1) - al(j)*x(1)
269  enddo ! j
270 
271  x = sw
272  x(1)= alu(i )* x(1)
273  zp(iold)= x(1)
274 #ifdef _OPENACC
275  enddo
276  !$acc end kernels
277 #else
278  enddo ! i
279  enddo ! blockIndex
280  !$omp end do
281 #endif
282  enddo ! ic
283 
284  !C-- BACKWARD
285  do ic=ncolor, 1, -1
286 #ifdef _OPENACC
287  !$acc kernels
288  !$acc loop independent private(X,SW)
289  do i = colorindex(ic-1)+1, colorindex(ic)
290 #else
291  !$omp do schedule (static, 1)
292  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
293  do i = blockindextocolorindex(blockindex), &
294  blockindextocolorindex(blockindex-1)+1, -1
295 #endif
296  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
297  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
298  ! blockIndexToColorIndex(blockIndex)
299  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
300  sw= 0.d0
301  isu= indexu(i-1) + 1
302  ieu= indexu(i)
303  do j= ieu, isu, -1
304  k= itemu(j)
305  x(1)= zp(k)
306  sw(1)= sw(1) + au(j)*x(1)
307  enddo ! j
308 
309  x = sw
310  x(1)= alu(i)* x(1)
311 
312  iold = perm(i)
313  zp(iold)= zp(iold) - x(1)
314 #ifdef _OPENACC
315  enddo
316  !$acc end kernels
317 #else
318  enddo ! i
319  enddo ! blockIndex
320  !$omp end do
321 #endif
322  enddo ! ic
323 #ifndef _OPENACC
324  !$omp end parallel
325 
326  !OCL END_CACHE_SUBSECTOR
327  !OCL END_CACHE_SECTOR_SIZE
328 
329  !call stop_collection("loopInPrecond33")
330 #endif
331 
332  end subroutine hecmw_precond_ssor_11_apply
333 
334  subroutine hecmw_precond_ssor_11_clear(hecMAT)
335  implicit none
336  type(hecmwst_matrix), intent(inout) :: hecmat
337  integer(kind=kint ) :: nthreads = 1
338 #ifndef _OPENACC
339  !$ nthreads = omp_get_max_threads()
340 #endif
341  if (associated(colorindex)) deallocate(colorindex)
342  if (associated(perm)) deallocate(perm)
343  if (associated(iperm)) deallocate(iperm)
344  if (associated(alu)) deallocate(alu)
345  if (nthreads >= 1) then
346  if (associated(d)) deallocate(d)
347  if (associated(al)) deallocate(al)
348  if (associated(au)) deallocate(au)
349  if (associated(indexl)) deallocate(indexl)
350  if (associated(indexu)) deallocate(indexu)
351  if (associated(iteml)) deallocate(iteml)
352  if (associated(itemu)) deallocate(itemu)
353  end if
354  nullify(colorindex)
355  nullify(perm)
356  nullify(iperm)
357  nullify(alu)
358  nullify(d)
359  nullify(al)
360  nullify(au)
361  nullify(indexl)
362  nullify(indexu)
363  nullify(iteml)
364  nullify(itemu)
365  initialized = .false.
366  end subroutine hecmw_precond_ssor_11_clear
367 
368 
369 
370 end module hecmw_precond_ssor_11
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_11_setup(hecMAT)
subroutine, public hecmw_precond_ssor_11_clear(hecMAT)
subroutine, public hecmw_precond_ssor_11_apply(ZP)
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)