FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SSOR_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 
6 !C
7 !C***
8 !C*** module hecmw_precond_SSOR_33
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  ! taken from hecMAT at setup: _apply receives only ZP and cannot read it back
43  integer(kind=kint) :: precond_impl = hecmw_precond_impl_bsr
44 
45  ! a format may be selected on a build that carries no SSOR for it; saying so once
46  ! per run keeps the fallback from looking like the requested format took effect
47  logical, save :: precond_impl_missing_reported = .false.
48 
49  logical, save :: isFirst = .true.
50 
51  logical, save :: INITIALIZED = .false.
52 
53  ! for tuning
54  integer(kind=kint), parameter :: numOfBlockPerThread = 100
55  integer(kind=kint), save :: numOfThread = 1, numofblock
56  integer(kind=kint), save, allocatable :: icToBlockIndex(:)
57  integer(kind=kint), save, allocatable :: blockIndexToColorIndex(:)
58  integer(kind=kint), save :: sectorCacheSize0, sectorCacheSize1
59 
60  integer(kind=kint), parameter :: DEBUG = 0
61 
62 contains
63 
64  subroutine hecmw_precond_ssor_33_setup(hecMAT)
65  implicit none
66  type(hecmwst_matrix), intent(inout) :: hecmat
67  integer(kind=kint ) :: npl, npu
68  integer(kind=kint ) :: ncolor_in
69  real (kind=kreal) :: sigma_diag
70  real (kind=kreal) :: alutmp(3,3), pw(3)
71  integer(kind=kint ) :: ii, i, j, k
72  integer(kind=kint ) :: nthreads = 1
73  integer(kind=kint ), allocatable :: perm_tmp(:)
74  real (kind=kreal) :: t0
75 
76  if (debug >= 1) then
77  t0 = hecmw_wtime()
78  write(*,*) 'DEBUG: SSOR setup start', hecmw_wtime()-t0
79  endif
80 
81  if (initialized) then
82  if (hecmat%Iarray(98) == 1) then ! need symbolic and numerical setup
83  call hecmw_precond_ssor_33_clear(hecmat)
84  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
85  call hecmw_precond_ssor_33_clear(hecmat) ! TEMPORARY
86  else
87  return
88  endif
89  endif
90 
91 #ifndef _OPENACC
92  !$ nthreads = omp_get_max_threads()
93 #endif
94 
95  n = hecmat%N
96  ! N = hecMAT%NP
97  ncolor_in = hecmw_mat_get_ncolor_in(hecmat)
98  sigma_diag = hecmw_mat_get_sigma_diag(hecmat)
99  precond_impl = hecmw_mat_get_precond_impl(hecmat)
100 
101 #ifdef _OPENACC
102  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
103  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
104  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
105  if (debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
106  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
107  hecmat%indexU, hecmat%itemU, perm_tmp, &
108  ncolor_in, ncolor, colorindex, perm, iperm)
109  if (debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
110  deallocate(perm_tmp)
111 
112 #else
113  if (nthreads == 1) then
114  ncolor = 1
115  allocate(colorindex(0:1), perm(n), iperm(n))
116  colorindex(0) = 0
117  colorindex(1) = n
118  do i=1,n
119  perm(i) = i
120  iperm(i) = i
121  end do
122  else
123  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
124  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
125  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
126  if (debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
127  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
128  hecmat%indexU, hecmat%itemU, perm_tmp, &
129  ncolor_in, ncolor, colorindex, perm, iperm)
130  if (debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
131  deallocate(perm_tmp)
132 
133  endif
134 #endif
135 
136  npl = 0
137  do i=1,n
138  do j=hecmat%indexU(i-1)+1,hecmat%indexU(i)
139  if( hecmat%itemU(j) > n ) exit
140  npl = npl + 1
141  enddo
142  enddo
143  npl = max(hecmat%indexL(n),npl)
144  npu = hecmat%indexU(n)
145  allocate(indexl(0:n), indexu(0:n), iteml(npl), itemu(npu))
146  call hecmw_matrix_reorder_profile(n, perm, iperm, &
147  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
148  indexl, indexu, iteml, itemu)
149  if (debug >= 1) write(*,*) 'DEBUG: reordering profile done', hecmw_wtime()-t0
150 
151 
152  allocate(d(9*n), al(9*npl), au(9*npu))
153  call hecmw_matrix_reorder_values(n, 3, perm, iperm, &
154  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
155  hecmat%AL, hecmat%AU, hecmat%D, &
156  indexl, indexu, iteml, itemu, al, au, d)
157  if (debug >= 1) write(*,*) 'DEBUG: reordering values done', hecmw_wtime()-t0
158 
159  call hecmw_matrix_reorder_renum_item(n, perm, indexl, iteml)
160  call hecmw_matrix_reorder_renum_item(n, perm, indexu, itemu)
161 
162  allocate(alu(9*n))
163  alu = 0.d0
164 
165  do ii= 1, 9*n
166  alu(ii) = d(ii)
167  enddo
168 
169 #ifdef _OPENACC
170  !$acc kernels
171  !$acc loop independent private(ALUtmp,PW)
172 #else
173  !$omp parallel default(none),private(ii,ALUtmp,k,i,j,PW),shared(N,ALU,SIGMA_DIAG)
174  !$omp do
175 #endif
176  do ii= 1, n
177  alutmp(1,1)= alu(9*ii-8) * sigma_diag
178  alutmp(1,2)= alu(9*ii-7)
179  alutmp(1,3)= alu(9*ii-6)
180  alutmp(2,1)= alu(9*ii-5)
181  alutmp(2,2)= alu(9*ii-4) * sigma_diag
182  alutmp(2,3)= alu(9*ii-3)
183  alutmp(3,1)= alu(9*ii-2)
184  alutmp(3,2)= alu(9*ii-1)
185  alutmp(3,3)= alu(9*ii ) * sigma_diag
186  do k= 1, 3
187  alutmp(k,k)= 1.d0/alutmp(k,k)
188  do i= k+1, 3
189  alutmp(i,k)= alutmp(i,k) * alutmp(k,k)
190  do j= k+1, 3
191  pw(j)= alutmp(i,j) - alutmp(i,k)*alutmp(k,j)
192  enddo
193  do j= k+1, 3
194  alutmp(i,j)= pw(j)
195  enddo
196  enddo
197  enddo
198  alu(9*ii-8)= alutmp(1,1)
199  alu(9*ii-7)= alutmp(1,2)
200  alu(9*ii-6)= alutmp(1,3)
201  alu(9*ii-5)= alutmp(2,1)
202  alu(9*ii-4)= alutmp(2,2)
203  alu(9*ii-3)= alutmp(2,3)
204  alu(9*ii-2)= alutmp(3,1)
205  alu(9*ii-1)= alutmp(3,2)
206  alu(9*ii )= alutmp(3,3)
207  enddo
208 #ifdef _OPENACC
209  !$acc end kernels
210 #else
211  !$omp end do
212  !$omp end parallel
213 #endif
214 
215  isfirst = .true.
216 
217  initialized = .true.
218  hecmat%Iarray(98) = 0 ! symbolic setup done
219  hecmat%Iarray(97) = 0 ! numerical setup done
220 
221  if (debug >= 1) write(*,*) 'DEBUG: SSOR setup done', hecmw_wtime()-t0
222 
223  end subroutine hecmw_precond_ssor_33_setup
224 
225  subroutine setup_tuning_parameters
226  use hecmw_tuning_fx
227  implicit none
228  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
229  real(kind=kreal) :: numofelementperblock
230  integer(kind=kint) :: my_rank
231  integer(kind=kint) :: ic, i
232  if (debug >= 1) write(*,*) 'DEBUG: setting up tuning parameters for SSOR'
233 #ifndef _OPENACC
234  !$ numOfThread = omp_get_max_threads()
235 #endif
236 
237  numofblock = numofthread * numofblockperthread
238  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
239  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
240  allocate (ictoblockindex(0:ncolor), &
241  blockindextocolorindex(0:numofblock + ncolor))
242  numofelement = n + indexl(n) + indexu(n)
243  numofelementperblock = dble(numofelement) / numofblock
244  blockindex = 0
245  ictoblockindex = -1
246  ictoblockindex(0) = 0
247  blockindextocolorindex = -1
248  blockindextocolorindex(0) = 0
249  my_rank = hecmw_comm_get_rank()
250  ! write(9000+my_rank,*) &
251  ! '# numOfElementPerBlock =', numOfElementPerBlock
252  ! write(9000+my_rank,*) &
253  ! '# ic, blockIndex, colorIndex, elementCount'
254  do ic = 1, ncolor
255  elementcount = 0
256  ii = 1
257  do i = colorindex(ic-1)+1, colorindex(ic)
258  elementcount = elementcount + 1
259  elementcount = elementcount + (indexl(i) - indexl(i-1))
260  elementcount = elementcount + (indexu(i) - indexu(i-1))
261  if (elementcount > ii * numofelementperblock &
262  .or. i == colorindex(ic)) then
263  ii = ii + 1
264  blockindex = blockindex + 1
265  blockindextocolorindex(blockindex) = i
266  ! write(9000+my_rank,*) ic, blockIndex, &
267  ! blockIndexToColorIndex(blockIndex), elementCount
268  endif
269  enddo
270  ictoblockindex(ic) = blockindex
271  enddo
272  numofblock = blockindex
273 
275  sectorcachesize0, sectorcachesize1 )
276  end subroutine setup_tuning_parameters
277 
279  use m_hecmw_comm_f
280  implicit none
281  real(kind=kreal), intent(inout) :: zp(:)
282 
283  select case (precond_impl)
286  case default
287  if (.not. precond_impl_missing_reported) then
288  precond_impl_missing_reported = .true.
289  if (hecmw_comm_get_rank() == 0) write(*,'(a)') &
290  '#### MATRIXFORMAT: this build has no SSOR preconditioner for the selected '// &
291  'format -- running the BSR implementation'
292  endif
294  end select
295  end subroutine hecmw_precond_ssor_33_apply
296 
298  implicit none
299  real(kind=kreal), intent(inout) :: zp(:)
300  integer(kind=kint) :: ic, i, iold, j, isL, ieL, isU, ieU, k
301  real(kind=kreal) :: sw1, sw2, sw3, x1, x2, x3
302 
303  ! added for tuning >>>
304  integer(kind=kint) :: blockIndex
305 
306 #ifndef _OPENACC
307  if (isfirst) then
308  call setup_tuning_parameters
309  isfirst = .false.
310  endif
311 #endif
312  ! <<< added for tuning
313 
314 #ifndef _OPENACC
315  !call start_collection("loopInPrecond33")
316 
317  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
318  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
319 
320  !$omp parallel default(none) &
321  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
322  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex) &
323  !$omp&private(SW1,SW2,SW3,X1,X2,X3,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
324 #endif
325 
326  !C-- FORWARD
327  do ic=1,ncolor
328 #ifdef _OPENACC
329  !$acc kernels
330  !$acc loop independent
331  do i = colorindex(ic-1)+1, colorindex(ic)
332 #else
333  !$omp do schedule (static, 1)
334  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
335  do i = blockindextocolorindex(blockindex-1)+1, &
336  blockindextocolorindex(blockindex)
337 #endif
338  ! do i = startPos(threadNum, ic), endPos(threadNum, ic)
339  iold = perm(i)
340  sw1= zp(3*iold-2)
341  sw2= zp(3*iold-1)
342  sw3= zp(3*iold )
343  isl= indexl(i-1)+1
344  iel= indexl(i)
345  do j= isl, iel
346  !k= perm(itemL(j))
347  k= iteml(j)
348  x1= zp(3*k-2)
349  x2= zp(3*k-1)
350  x3= zp(3*k )
351  sw1= sw1 - al(9*j-8)*x1 - al(9*j-7)*x2 - al(9*j-6)*x3
352  sw2= sw2 - al(9*j-5)*x1 - al(9*j-4)*x2 - al(9*j-3)*x3
353  sw3= sw3 - al(9*j-2)*x1 - al(9*j-1)*x2 - al(9*j )*x3
354  enddo ! j
355 
356  x1= sw1
357  x2= sw2
358  x3= sw3
359  x2= x2 - alu(9*i-5)*x1
360  x3= x3 - alu(9*i-2)*x1 - alu(9*i-1)*x2
361  x3= alu(9*i )* x3
362  x2= alu(9*i-4)*( x2 - alu(9*i-3)*x3 )
363  x1= alu(9*i-8)*( x1 - alu(9*i-6)*x3 - alu(9*i-7)*x2)
364  zp(3*iold-2)= x1
365  zp(3*iold-1)= x2
366  zp(3*iold )= x3
367 #ifdef _OPENACC
368  enddo
369  !$acc end kernels
370 #else
371  enddo ! i
372  enddo ! blockIndex
373  !$omp end do
374 #endif
375  enddo ! ic
376 
377  !C-- BACKWARD
378  do ic=ncolor, 1, -1
379 #ifdef _OPENACC
380  !$acc kernels
381  !$acc loop independent
382  do i = colorindex(ic-1)+1, colorindex(ic)
383 #else
384  !$omp do schedule (static, 1)
385  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
386  do i = blockindextocolorindex(blockindex), &
387  blockindextocolorindex(blockindex-1)+1, -1
388 #endif
389  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
390  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
391  ! blockIndexToColorIndex(blockIndex)
392  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
393  sw1= 0.d0
394  sw2= 0.d0
395  sw3= 0.d0
396  isu= indexu(i-1) + 1
397  ieu= indexu(i)
398  do j= ieu, isu, -1
399  !k= perm(itemU(j))
400  k= itemu(j)
401  x1= zp(3*k-2)
402  x2= zp(3*k-1)
403  x3= zp(3*k )
404  sw1= sw1 + au(9*j-8)*x1 + au(9*j-7)*x2 + au(9*j-6)*x3
405  sw2= sw2 + au(9*j-5)*x1 + au(9*j-4)*x2 + au(9*j-3)*x3
406  sw3= sw3 + au(9*j-2)*x1 + au(9*j-1)*x2 + au(9*j )*x3
407  enddo ! j
408 
409  x1= sw1
410  x2= sw2
411  x3= sw3
412  x2= x2 - alu(9*i-5)*x1
413  x3= x3 - alu(9*i-2)*x1 - alu(9*i-1)*x2
414  x3= alu(9*i )* x3
415  x2= alu(9*i-4)*( x2 - alu(9*i-3)*x3 )
416  x1= alu(9*i-8)*( x1 - alu(9*i-6)*x3 - alu(9*i-7)*x2)
417  iold = perm(i)
418  zp(3*iold-2)= zp(3*iold-2) - x1
419  zp(3*iold-1)= zp(3*iold-1) - x2
420  zp(3*iold )= zp(3*iold ) - x3
421 #ifdef _OPENACC
422  enddo
423  !$acc end kernels
424 #else
425  enddo ! i
426  enddo ! blockIndex
427  !$omp end do
428 #endif
429  enddo ! ic
430 #ifndef _OPENACC
431  !$omp end parallel
432 
433  !OCL END_CACHE_SUBSECTOR
434  !OCL END_CACHE_SECTOR_SIZE
435 
436  !call stop_collection("loopInPrecond33")
437 #endif
438 
440 
441  subroutine hecmw_precond_ssor_33_clear(hecMAT)
442  implicit none
443  type(hecmwst_matrix), intent(inout) :: hecmat
444  integer(kind=kint ) :: nthreads = 1
445 #ifndef _OPENACC
446  !$ nthreads = omp_get_max_threads()
447 #endif
448  if (associated(colorindex)) deallocate(colorindex)
449  if (associated(perm)) deallocate(perm)
450  if (associated(iperm)) deallocate(iperm)
451  if (associated(alu)) deallocate(alu)
452  if (nthreads >= 1) then
453  if (associated(d)) deallocate(d)
454  if (associated(al)) deallocate(al)
455  if (associated(au)) deallocate(au)
456  if (associated(indexl)) deallocate(indexl)
457  if (associated(indexu)) deallocate(indexu)
458  if (associated(iteml)) deallocate(iteml)
459  if (associated(itemu)) deallocate(itemu)
460  end if
461  nullify(colorindex)
462  nullify(perm)
463  nullify(iperm)
464  nullify(alu)
465  nullify(d)
466  nullify(al)
467  nullify(au)
468  nullify(indexl)
469  nullify(indexu)
470  nullify(iteml)
471  nullify(itemu)
472  initialized = .false.
473  end subroutine hecmw_precond_ssor_33_clear
474 
475 
476 
477 end module hecmw_precond_ssor_33
real(kind=kreal) function, public hecmw_mat_get_sigma_diag(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_precond_impl(hecMAT)
integer(kind=kint), parameter, public hecmw_precond_impl_bsr
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_33_apply(ZP)
subroutine hecmw_precond_ssor_33_apply_generic(ZP)
subroutine, public hecmw_precond_ssor_33_setup(hecMAT)
subroutine, public hecmw_precond_ssor_33_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()
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)