FrontISTR  6.0.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  ! relaxation parameter of
47  ! M = 1/(2-OMEGA) (D/OMEGA + L) (D/OMEGA)^-1 (D/OMEGA + U)
48  ! OMEGA = 1 is the classic (D+L) D^-1 (D+U). _apply is handed only ZP, so setup
49  ! leaves the value here for it.
50  real(kind=kreal), save :: omega = 1.d0
51 
52  ! for tuning
53  integer(kind=kint), parameter :: numOfBlockPerThread = 100
54  integer(kind=kint), save :: numOfThread = 1, numofblock
55  integer(kind=kint), save, allocatable :: icToBlockIndex(:)
56  integer(kind=kint), save, allocatable :: blockIndexToColorIndex(:)
57  integer(kind=kint), save :: sectorCacheSize0, sectorCacheSize1
58 
59  integer(kind=kint), parameter :: SSOR_DEBUG = 0
60 
61 contains
62 
63  subroutine hecmw_precond_ssor_22_setup(hecMAT)
64  implicit none
65  type(hecmwst_matrix), intent(inout) :: hecmat
66  integer(kind=kint ) :: npl, npu
67  integer(kind=kint ) :: ncolor_in
68  real (kind=kreal) :: omega_inv
69  real (kind=kreal) :: alutmp(2,2), pw(2)
70  integer(kind=kint ) :: ii, i, j, k
71  integer(kind=kint ) :: nthreads = 1
72  integer(kind=kint ), allocatable :: perm_tmp(:)
73  real (kind=kreal) :: t0
74 
75  if (ssor_debug >= 1) then
76  t0 = hecmw_wtime()
77  write(*,*) 'DEBUG: SSOR setup start', hecmw_wtime()-t0
78  endif
79 
80  if (initialized) then
81  if (hecmat%Iarray(98) == 1) then ! need symbolic and numerical setup
82  call hecmw_precond_ssor_22_clear(hecmat)
83  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
84  call hecmw_precond_ssor_22_clear(hecmat) ! TEMPORARY
85  else
86  return
87  endif
88  endif
89 
90 #ifndef _OPENACC
91  !$ nthreads = omp_get_max_threads()
92 #endif
93 
94  n = hecmat%N
95  ! N = hecMAT%NP
96  ncolor_in = hecmw_mat_get_ncolor_in(hecmat)
97  omega = hecmw_mat_get_omega(hecmat)
98  omega_inv = 1.d0 / omega
99 
100 #ifdef _OPENACC
101  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
102  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
103  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
104  if (ssor_debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
105  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
106  hecmat%indexU, hecmat%itemU, perm_tmp, &
107  ncolor_in, ncolor, colorindex, perm, iperm)
108  if (ssor_debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
109  deallocate(perm_tmp)
110 
111 #else
112  if (nthreads == 1) then
113  ncolor = 1
114  allocate(colorindex(0:1), perm(n), iperm(n))
115  colorindex(0) = 0
116  colorindex(1) = n
117  do i=1,n
118  perm(i) = i
119  iperm(i) = i
120  end do
121  else
122  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
123  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
124  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
125  if (ssor_debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
126  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
127  hecmat%indexU, hecmat%itemU, perm_tmp, &
128  ncolor_in, ncolor, colorindex, perm, iperm)
129  if (ssor_debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
130  deallocate(perm_tmp)
131 
132  endif
133 #endif
134 
135  npl = 0
136  do i=1,n
137  do j=hecmat%indexU(i-1)+1,hecmat%indexU(i)
138  if( hecmat%itemU(j) > n ) exit
139  npl = npl + 1
140  enddo
141  enddo
142  npl = max(hecmat%indexL(n),npl)
143  npu = hecmat%indexU(n)
144  allocate(indexl(0:n), indexu(0:n), iteml(npl), itemu(npu))
145  call hecmw_matrix_reorder_profile(n, perm, iperm, &
146  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
147  indexl, indexu, iteml, itemu)
148  if (ssor_debug >= 1) write(*,*) 'DEBUG: reordering profile done', hecmw_wtime()-t0
149 
150 
151  allocate(d(4*n), al(4*npl), au(4*npu))
152  call hecmw_matrix_reorder_values(n, 2, perm, iperm, &
153  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
154  hecmat%AL, hecmat%AU, hecmat%D, &
155  indexl, indexu, iteml, itemu, al, au, d)
156  if (ssor_debug >= 1) write(*,*) 'DEBUG: reordering values done', hecmw_wtime()-t0
157 
158  call hecmw_matrix_reorder_renum_item(n, perm, indexl, iteml)
159  call hecmw_matrix_reorder_renum_item(n, perm, indexu, itemu)
160 
161  allocate(alu(4*n))
162  alu = 0.d0
163 
164  do ii= 1, 4*n
165  alu(ii) = d(ii)
166  enddo
167 
168 #ifdef _OPENACC
169  !$acc kernels
170  !$acc loop independent private(ALUtmp,PW)
171 #else
172  !$omp parallel default(none),private(ii,ALUtmp,k,i,j,PW),shared(N,ALU,OMEGA_INV)
173  !$omp do
174 #endif
175  do ii= 1, n
176  alutmp(1,1)= alu(4*ii-3) * omega_inv
177  alutmp(1,2)= alu(4*ii-2) * omega_inv
178  alutmp(2,1)= alu(4*ii-1) * omega_inv
179  alutmp(2,2)= alu(4*ii-0) * omega_inv
180  do k= 1, 2
181  alutmp(k,k)= 1.d0/alutmp(k,k)
182  do i= k+1, 2
183  alutmp(i,k)= alutmp(i,k) * alutmp(k,k)
184  do j= k+1, 2
185  pw(j)= alutmp(i,j) - alutmp(i,k)*alutmp(k,j)
186  enddo
187  do j= k+1, 2
188  alutmp(i,j)= pw(j)
189  enddo
190  enddo
191  enddo
192  alu(4*ii-3)= alutmp(1,1)
193  alu(4*ii-2)= alutmp(1,2)
194  alu(4*ii-1)= alutmp(2,1)
195  alu(4*ii-0)= alutmp(2,2)
196  enddo
197 #ifdef _OPENACC
198  !$acc end kernels
199 #else
200  !$omp end do
201  !$omp end parallel
202 #endif
203 
204  isfirst = .true.
205 
206  initialized = .true.
207  hecmat%Iarray(98) = 0 ! symbolic setup done
208  hecmat%Iarray(97) = 0 ! numerical setup done
209 
210  if (ssor_debug >= 1) write(*,*) 'DEBUG: SSOR setup done', hecmw_wtime()-t0
211 
212  end subroutine hecmw_precond_ssor_22_setup
213 
214  subroutine setup_tuning_parameters
215  use hecmw_tuning_fx
216  implicit none
217  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
218  real(kind=kreal) :: numofelementperblock
219  integer(kind=kint) :: ic, i
220  if (ssor_debug >= 1) write(*,*) 'DEBUG: setting up tuning parameters for SSOR'
221 #ifndef _OPENACC
222  !$ numOfThread = omp_get_max_threads()
223 #endif
224 
225  numofblock = numofthread * numofblockperthread
226  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
227  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
228  allocate (ictoblockindex(0:ncolor), &
229  blockindextocolorindex(0:numofblock + ncolor))
230  numofelement = n + indexl(n) + indexu(n)
231  numofelementperblock = dble(numofelement) / numofblock
232  blockindex = 0
233  ictoblockindex = -1
234  ictoblockindex(0) = 0
235  blockindextocolorindex = -1
236  blockindextocolorindex(0) = 0
237  do ic = 1, ncolor
238  elementcount = 0
239  ii = 1
240  do i = colorindex(ic-1)+1, colorindex(ic)
241  elementcount = elementcount + 1
242  elementcount = elementcount + (indexl(i) - indexl(i-1))
243  elementcount = elementcount + (indexu(i) - indexu(i-1))
244  if (elementcount > ii * numofelementperblock &
245  .or. i == colorindex(ic)) then
246  ii = ii + 1
247  blockindex = blockindex + 1
248  blockindextocolorindex(blockindex) = i
249  endif
250  enddo
251  ictoblockindex(ic) = blockindex
252  enddo
253  numofblock = blockindex
254 
256  sectorcachesize0, sectorcachesize1 )
257  end subroutine setup_tuning_parameters
258 
260  implicit none
261  real(kind=kreal), intent(inout) :: zp(:)
262  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k
263  real(kind=kreal) :: sw1, sw2, x1, x2
264 
265  real(kind=kreal) :: omega_fac
266 
267  ! added for tuning >>>
268  integer(kind=kint) :: blockindex
269 
270 #ifndef _OPENACC
271  if (isfirst) then
272  call setup_tuning_parameters
273  isfirst = .false.
274  endif
275 #endif
276  ! <<< added for tuning
277 
278  omega_fac = 2.d0 - omega
279 
280 #ifndef _OPENACC
281  !call start_collection("loopInPrecond22")
282 
283  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
284  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
285 
286  !$omp parallel default(none) &
287  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
288  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex,OMEGA_FAC) &
289  !$omp&private(SW1,SW2,X1,X2,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
290 #endif
291 
292  !C-- FORWARD
293  do ic=1,ncolor
294 #ifdef _OPENACC
295  !$acc kernels
296  !$acc loop independent
297  do i = colorindex(ic-1)+1, colorindex(ic)
298 #else
299  !$omp do schedule (static, 1)
300  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
301  do i = blockindextocolorindex(blockindex-1)+1, &
302  blockindextocolorindex(blockindex)
303 #endif
304  iold = perm(i)
305  sw1= omega_fac * zp(2*iold-1)
306  sw2= omega_fac * zp(2*iold-0)
307  isl= indexl(i-1)+1
308  iel= indexl(i)
309  do j= isl, iel
310  k= iteml(j)
311  x1= zp(2*k-1)
312  x2= zp(2*k-0)
313  sw1= sw1 - al(4*j-3)*x1 - al(4*j-2)*x2
314  sw2= sw2 - al(4*j-1)*x1 - al(4*j-0)*x2
315  enddo ! j
316 
317  x1= sw1
318  x2= sw2
319  x2= x2 - alu(4*i-1)*x1
320  x2= alu(4*i )* x2
321  x1= alu(4*i-3)*( x1 - alu(4*i-2)*x2)
322  zp(2*iold-1)= x1
323  zp(2*iold-0)= x2
324 #ifdef _OPENACC
325  enddo
326  !$acc end kernels
327 #else
328  enddo ! i
329  enddo ! blockIndex
330  !$omp end do
331 #endif
332  enddo ! ic
333 
334  !C-- BACKWARD
335  do ic=ncolor, 1, -1
336 #ifdef _OPENACC
337  !$acc kernels
338  !$acc loop independent
339  do i = colorindex(ic-1)+1, colorindex(ic)
340 #else
341  !$omp do schedule (static, 1)
342  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
343  do i = blockindextocolorindex(blockindex), &
344  blockindextocolorindex(blockindex-1)+1, -1
345 #endif
346  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
347  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
348  ! blockIndexToColorIndex(blockIndex)
349  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
350  sw1= 0.d0
351  sw2= 0.d0
352  isu= indexu(i-1) + 1
353  ieu= indexu(i)
354  do j= ieu, isu, -1
355  k= itemu(j)
356  x1= zp(2*k-1)
357  x2= zp(2*k-0)
358  sw1= sw1 + au(4*j-3)*x1 + au(4*j-2)*x2
359  sw2= sw2 + au(4*j-1)*x1 + au(4*j-0)*x2
360  enddo ! j
361 
362  x1= sw1
363  x2= sw2
364  x2= x2 - alu(4*i-1)*x1
365  x2= alu(4*i )* x2
366  x1= alu(4*i-3)*( x1 - alu(4*i-2)*x2 )
367 
368  iold = perm(i)
369  zp(2*iold-1)= zp(2*iold-1) - x1
370  zp(2*iold )= zp(2*iold ) - x2
371 #ifdef _OPENACC
372  enddo
373  !$acc end kernels
374 #else
375  enddo ! i
376  enddo ! blockIndex
377  !$omp end do
378 #endif
379  enddo ! ic
380 #ifndef _OPENACC
381  !$omp end parallel
382 
383  !OCL END_CACHE_SUBSECTOR
384  !OCL END_CACHE_SECTOR_SIZE
385 
386  !call stop_collection("loopInPrecond22")
387 #endif
388 
389  end subroutine hecmw_precond_ssor_22_apply
390 
391  subroutine hecmw_precond_ssor_22_clear(hecMAT)
392  implicit none
393  type(hecmwst_matrix), intent(inout) :: hecmat
394  if (associated(colorindex)) deallocate(colorindex)
395  if (associated(perm)) deallocate(perm)
396  if (associated(iperm)) deallocate(iperm)
397  if (associated(alu)) deallocate(alu)
398  if (associated(d)) deallocate(d)
399  if (associated(al)) deallocate(al)
400  if (associated(au)) deallocate(au)
401  if (associated(indexl)) deallocate(indexl)
402  if (associated(indexu)) deallocate(indexu)
403  if (associated(iteml)) deallocate(iteml)
404  if (associated(itemu)) deallocate(itemu)
405  nullify(colorindex)
406  nullify(perm)
407  nullify(iperm)
408  nullify(alu)
409  nullify(d)
410  nullify(al)
411  nullify(au)
412  nullify(indexl)
413  nullify(indexu)
414  nullify(iteml)
415  nullify(itemu)
416  initialized = .false.
417  end subroutine hecmw_precond_ssor_22_clear
418 
419 end module hecmw_precond_ssor_22
real(kind=kreal) function, public hecmw_mat_get_omega(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
real(kind=kreal) function hecmw_wtime()
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)