FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SSOR_22.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_22
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_22_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(2,2), pw(2)
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_22_clear(hecmat)
66  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
67  call hecmw_precond_ssor_22_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(4*n), al(4*npl), au(4*npu))
127  call hecmw_matrix_reorder_values(n, 2, 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(4*n))
137  alu = 0.d0
138 
139  do ii= 1, 4*n
140  alu(ii) = d(ii)
141  enddo
142 
143 #ifdef _OPENACC
144  !$acc kernels
145  !$acc loop independent private(ALUtmp,PW)
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(4*ii-3) * sigma_diag
152  alutmp(1,2)= alu(4*ii-2)
153  alutmp(2,1)= alu(4*ii-1)
154  alutmp(2,2)= alu(4*ii-0) * sigma_diag
155  do k= 1, 2
156  alutmp(k,k)= 1.d0/alutmp(k,k)
157  do i= k+1, 2
158  alutmp(i,k)= alutmp(i,k) * alutmp(k,k)
159  do j= k+1, 2
160  pw(j)= alutmp(i,j) - alutmp(i,k)*alutmp(k,j)
161  enddo
162  do j= k+1, 2
163  alutmp(i,j)= pw(j)
164  enddo
165  enddo
166  enddo
167  alu(4*ii-3)= alutmp(1,1)
168  alu(4*ii-2)= alutmp(1,2)
169  alu(4*ii-1)= alutmp(2,1)
170  alu(4*ii-0)= alutmp(2,2)
171  enddo
172 #ifdef _OPENACC
173  !$acc end kernels
174 #else
175  !$omp end do
176  !$omp end parallel
177 #endif
178 
179  isfirst = .true.
180 
181  initialized = .true.
182  hecmat%Iarray(98) = 0 ! symbolic setup done
183  hecmat%Iarray(97) = 0 ! numerical setup done
184 
185  !write(*,*) 'DEBUG: SSOR setup done', hecmw_Wtime()-t0
186 
187  end subroutine hecmw_precond_ssor_22_setup
188 
190  use hecmw_tuning_fx
191  implicit none
192  real(kind=kreal), intent(inout) :: zp(:)
193  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k
194  real(kind=kreal) :: sw(2), x(2)
195 
196  ! added for tuning >>>
197  integer(kind=kint), parameter :: numofblockperthread = 100
198  integer(kind=kint), save :: numofthread = 1, numofblock
199  integer(kind=kint), save, allocatable :: ictoblockindex(:)
200  integer(kind=kint), save, allocatable :: blockindextocolorindex(:)
201  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
202  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
203  real(kind=kreal) :: numofelementperblock
204  integer(kind=kint) :: my_rank
205 
206 #ifndef _OPENACC
207  if (isfirst) then
208  !$ numOfThread = omp_get_max_threads()
209  numofblock = numofthread * numofblockperthread
210  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
211  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
212  allocate (ictoblockindex(0:ncolor), &
213  blockindextocolorindex(0:numofblock + ncolor))
214  numofelement = n + indexl(n) + indexu(n)
215  numofelementperblock = dble(numofelement) / numofblock
216  blockindex = 0
217  ictoblockindex = -1
218  ictoblockindex(0) = 0
219  blockindextocolorindex = -1
220  blockindextocolorindex(0) = 0
221  my_rank = hecmw_comm_get_rank()
222  ! write(9000+my_rank,*) &
223  ! '# numOfElementPerBlock =', numOfElementPerBlock
224  ! write(9000+my_rank,*) &
225  ! '# ic, blockIndex, colorIndex, elementCount'
226  do ic = 1, ncolor
227  elementcount = 0
228  ii = 1
229  do i = colorindex(ic-1)+1, colorindex(ic)
230  elementcount = elementcount + 1
231  elementcount = elementcount + (indexl(i) - indexl(i-1))
232  elementcount = elementcount + (indexu(i) - indexu(i-1))
233  if (elementcount > ii * numofelementperblock &
234  .or. i == colorindex(ic)) then
235  ii = ii + 1
236  blockindex = blockindex + 1
237  blockindextocolorindex(blockindex) = i
238  ! write(9000+my_rank,*) ic, blockIndex, &
239  ! blockIndexToColorIndex(blockIndex), elementCount
240  endif
241  enddo
242  ictoblockindex(ic) = blockindex
243  enddo
244  numofblock = blockindex
245 
247  sectorcachesize0, sectorcachesize1 )
248 
249  isfirst = .false.
250  endif
251 #endif
252  ! <<< added for tuning
253 
254 #ifndef _OPENACC
255  !call start_collection("loopInPrecond33")
256 
257  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
258  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
259 
260  !$omp parallel default(none) &
261  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
262  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex) &
263  !$omp&private(SW,X,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
264 #endif
265 
266  !C-- FORWARD
267  do ic=1,ncolor
268 #ifdef _OPENACC
269  !$acc kernels
270  !$acc loop independent private(X,SW)
271  do i = colorindex(ic-1)+1, colorindex(ic)
272 #else
273  !$omp do schedule (static, 1)
274  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
275  do i = blockindextocolorindex(blockindex-1)+1, &
276  blockindextocolorindex(blockindex)
277 #endif
278  iold = perm(i)
279  sw(1)= zp(2*iold-1)
280  sw(2)= zp(2*iold-0)
281  isl= indexl(i-1)+1
282  iel= indexl(i)
283  do j= isl, iel
284  k= iteml(j)
285  x(1)= zp(2*k-1)
286  x(2)= zp(2*k-0)
287  sw(1)= sw(1) - al(4*j-3)*x(1) - al(4*j-2)*x(2)
288  sw(2)= sw(2) - al(4*j-1)*x(1) - al(4*j-0)*x(2)
289  enddo ! j
290 
291  x = sw
292  x(2)= x(2) - alu(4*i-1)*x(1)
293  x(2)= alu(4*i )* x(2)
294  x(1)= alu(4*i-3)*( x(1) - alu(4*i-2)*x(2))
295  zp(2*iold-1)= x(1)
296  zp(2*iold-0)= x(2)
297 #ifdef _OPENACC
298  enddo
299  !$acc end kernels
300 #else
301  enddo ! i
302  enddo ! blockIndex
303  !$omp end do
304 #endif
305  enddo ! ic
306 
307  !C-- BACKWARD
308  do ic=ncolor, 1, -1
309 #ifdef _OPENACC
310  !$acc kernels
311  !$acc loop independent private(X,SW)
312  do i = colorindex(ic-1)+1, colorindex(ic)
313 #else
314  !$omp do schedule (static, 1)
315  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
316  do i = blockindextocolorindex(blockindex), &
317  blockindextocolorindex(blockindex-1)+1, -1
318 #endif
319  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
320  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
321  ! blockIndexToColorIndex(blockIndex)
322  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
323  sw= 0.d0
324  isu= indexu(i-1) + 1
325  ieu= indexu(i)
326  do j= ieu, isu, -1
327  k= itemu(j)
328  x(1)= zp(2*k-1)
329  x(2)= zp(2*k-0)
330  sw(1)= sw(1) + au(4*j-3)*x(1) + au(4*j-2)*x(2)
331  sw(2)= sw(2) + au(4*j-1)*x(1) + au(4*j-0)*x(2)
332  enddo ! j
333 
334  x = sw
335  x(2)= x(2) - alu(4*i-1)*x(1)
336 
337 
338  x(2)= alu(4*i )* x(2)
339  x(1)= alu(4*i-3)*( x(1) - alu(4*i-2)*x(2) )
340 
341  iold = perm(i)
342  zp(2*iold-1)= zp(2*iold-1) - x(1)
343  zp(2*iold )= zp(2*iold ) - x(2)
344 #ifdef _OPENACC
345  enddo
346  !$acc end kernels
347 #else
348  enddo ! i
349  enddo ! blockIndex
350  !$omp end do
351 #endif
352  enddo ! ic
353 #ifndef _OPENACC
354  !$omp end parallel
355 
356  !OCL END_CACHE_SUBSECTOR
357  !OCL END_CACHE_SECTOR_SIZE
358 
359  !call stop_collection("loopInPrecond33")
360 #endif
361 
362  end subroutine hecmw_precond_ssor_22_apply
363 
364  subroutine hecmw_precond_ssor_22_clear(hecMAT)
365  implicit none
366  type(hecmwst_matrix), intent(inout) :: hecmat
367  integer(kind=kint ) :: nthreads = 1
368 #ifndef _OPENACC
369  !$ nthreads = omp_get_max_threads()
370 #endif
371  if (associated(colorindex)) deallocate(colorindex)
372  if (associated(perm)) deallocate(perm)
373  if (associated(iperm)) deallocate(iperm)
374  if (associated(alu)) deallocate(alu)
375  if (nthreads >= 1) then
376  if (associated(d)) deallocate(d)
377  if (associated(al)) deallocate(al)
378  if (associated(au)) deallocate(au)
379  if (associated(indexl)) deallocate(indexl)
380  if (associated(indexu)) deallocate(indexu)
381  if (associated(iteml)) deallocate(iteml)
382  if (associated(itemu)) deallocate(itemu)
383  end if
384  nullify(colorindex)
385  nullify(perm)
386  nullify(iperm)
387  nullify(alu)
388  nullify(d)
389  nullify(al)
390  nullify(au)
391  nullify(indexl)
392  nullify(indexu)
393  nullify(iteml)
394  nullify(itemu)
395  initialized = .false.
396  end subroutine hecmw_precond_ssor_22_clear
397 
398 
399 
400 end module hecmw_precond_ssor_22
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_22_apply(ZP)
subroutine, public hecmw_precond_ssor_22_setup(hecMAT)
subroutine, public hecmw_precond_ssor_22_clear(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)