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  !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(n), al(npl), au(npu))
130  call hecmw_matrix_reorder_values(n, 1, 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(n))
140  alu = 0.d0
141 
142  do ii= 1, n
143  alu(ii) = d(ii)
144  enddo
145 
146 #ifdef _OPENACC
147  !$acc kernels
148  !$acc loop independent private(ALUtmp)
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(ii) * sigma_diag
155  alutmp(1,1)= 1.d0/alutmp(1,1)
156  alu(ii)= alutmp(1,1)
157  enddo
158 #ifdef _OPENACC
159  !$acc end kernels
160 #else
161  !$omp end do
162  !$omp end parallel
163 #endif
164 
165  isfirst = .true.
166 
167  initialized = .true.
168  hecmat%Iarray(98) = 0 ! symbolic setup done
169  hecmat%Iarray(97) = 0 ! numerical setup done
170 
171  !write(*,*) 'DEBUG: SSOR setup done', hecmw_Wtime()-t0
172 
173  end subroutine hecmw_precond_ssor_11_setup
174 
176  use hecmw_tuning_fx
177  implicit none
178  real(kind=kreal), intent(inout) :: zp(:)
179  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k
180  real(kind=kreal) :: sw(1), x(1)
181 
182  ! added for tuning >>>
183  integer(kind=kint), parameter :: numofblockperthread = 100
184  integer(kind=kint), save :: numofthread = 1, numofblock
185  integer(kind=kint), save, allocatable :: ictoblockindex(:)
186  integer(kind=kint), save, allocatable :: blockindextocolorindex(:)
187  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
188  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
189  real(kind=kreal) :: numofelementperblock
190  integer(kind=kint) :: my_rank
191 
192 #ifndef _OPENACC
193  if (isfirst) then
194  !$ numOfThread = omp_get_max_threads()
195  numofblock = numofthread * numofblockperthread
196  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
197  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
198  allocate (ictoblockindex(0:ncolor), &
199  blockindextocolorindex(0:numofblock + ncolor))
200  numofelement = n + indexl(n) + indexu(n)
201  numofelementperblock = dble(numofelement) / numofblock
202  blockindex = 0
203  ictoblockindex = -1
204  ictoblockindex(0) = 0
205  blockindextocolorindex = -1
206  blockindextocolorindex(0) = 0
207  my_rank = hecmw_comm_get_rank()
208  ! write(9000+my_rank,*) &
209  ! '# numOfElementPerBlock =', numOfElementPerBlock
210  ! write(9000+my_rank,*) &
211  ! '# ic, blockIndex, colorIndex, elementCount'
212  do ic = 1, ncolor
213  elementcount = 0
214  ii = 1
215  do i = colorindex(ic-1)+1, colorindex(ic)
216  elementcount = elementcount + 1
217  elementcount = elementcount + (indexl(i) - indexl(i-1))
218  elementcount = elementcount + (indexu(i) - indexu(i-1))
219  if (elementcount > ii * numofelementperblock &
220  .or. i == colorindex(ic)) then
221  ii = ii + 1
222  blockindex = blockindex + 1
223  blockindextocolorindex(blockindex) = i
224  ! write(9000+my_rank,*) ic, blockIndex, &
225  ! blockIndexToColorIndex(blockIndex), elementCount
226  endif
227  enddo
228  ictoblockindex(ic) = blockindex
229  enddo
230  numofblock = blockindex
231 
233  sectorcachesize0, sectorcachesize1 )
234 
235  isfirst = .false.
236  endif
237 #endif
238  ! <<< added for tuning
239 
240 #ifndef _OPENACC
241  !call start_collection("loopInPrecond33")
242 
243  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
244  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
245 
246  !$omp parallel default(none) &
247  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
248  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex) &
249  !$omp&private(SW,X,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex)
250 #endif
251 
252  !C-- FORWARD
253  do ic=1,ncolor
254 #ifdef _OPENACC
255  !$acc kernels
256  !$acc loop independent private(X,SW)
257  do i = colorindex(ic-1)+1, colorindex(ic)
258 #else
259  !$omp do schedule (static, 1)
260  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
261  do i = blockindextocolorindex(blockindex-1)+1, &
262  blockindextocolorindex(blockindex)
263 #endif
264  iold = perm(i)
265  sw(1)= zp(iold)
266  isl= indexl(i-1)+1
267  iel= indexl(i)
268  do j= isl, iel
269  k= iteml(j)
270  x(1)= zp(k)
271  sw(1)= sw(1) - al(j)*x(1)
272  enddo ! j
273 
274  x = sw
275  x(1)= alu(i )* x(1)
276  zp(iold)= x(1)
277 #ifdef _OPENACC
278  enddo
279  !$acc end kernels
280 #else
281  enddo ! i
282  enddo ! blockIndex
283  !$omp end do
284 #endif
285  enddo ! ic
286 
287  !C-- BACKWARD
288  do ic=ncolor, 1, -1
289 #ifdef _OPENACC
290  !$acc kernels
291  !$acc loop independent private(X,SW)
292  do i = colorindex(ic-1)+1, colorindex(ic)
293 #else
294  !$omp do schedule (static, 1)
295  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
296  do i = blockindextocolorindex(blockindex), &
297  blockindextocolorindex(blockindex-1)+1, -1
298 #endif
299  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
300  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
301  ! blockIndexToColorIndex(blockIndex)
302  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
303  sw= 0.d0
304  isu= indexu(i-1) + 1
305  ieu= indexu(i)
306  do j= ieu, isu, -1
307  k= itemu(j)
308  x(1)= zp(k)
309  sw(1)= sw(1) + au(j)*x(1)
310  enddo ! j
311 
312  x = sw
313  x(1)= alu(i)* x(1)
314 
315  iold = perm(i)
316  zp(iold)= zp(iold) - x(1)
317 #ifdef _OPENACC
318  enddo
319  !$acc end kernels
320 #else
321  enddo ! i
322  enddo ! blockIndex
323  !$omp end do
324 #endif
325  enddo ! ic
326 #ifndef _OPENACC
327  !$omp end parallel
328 
329  !OCL END_CACHE_SUBSECTOR
330  !OCL END_CACHE_SECTOR_SIZE
331 
332  !call stop_collection("loopInPrecond33")
333 #endif
334 
335  end subroutine hecmw_precond_ssor_11_apply
336 
337  subroutine hecmw_precond_ssor_11_clear(hecMAT)
338  implicit none
339  type(hecmwst_matrix), intent(inout) :: hecmat
340  integer(kind=kint ) :: nthreads = 1
341 #ifndef _OPENACC
342  !$ nthreads = omp_get_max_threads()
343 #endif
344  if (associated(colorindex)) deallocate(colorindex)
345  if (associated(perm)) deallocate(perm)
346  if (associated(iperm)) deallocate(iperm)
347  if (associated(alu)) deallocate(alu)
348  if (nthreads >= 1) then
349  if (associated(d)) deallocate(d)
350  if (associated(al)) deallocate(al)
351  if (associated(au)) deallocate(au)
352  if (associated(indexl)) deallocate(indexl)
353  if (associated(indexu)) deallocate(indexu)
354  if (associated(iteml)) deallocate(iteml)
355  if (associated(itemu)) deallocate(itemu)
356  end if
357  nullify(colorindex)
358  nullify(perm)
359  nullify(iperm)
360  nullify(alu)
361  nullify(d)
362  nullify(al)
363  nullify(au)
364  nullify(indexl)
365  nullify(indexu)
366  nullify(iteml)
367  nullify(itemu)
368  initialized = .false.
369  end subroutine hecmw_precond_ssor_11_clear
370 
371  subroutine write_debug_info
372  implicit none
373  integer(kind=kint) :: my_rank, ic, in
374  my_rank = hecmw_comm_get_rank()
375  !--------------------> debug: shizawa
376  if (my_rank.eq.0) then
377  write(*,*) 'DEBUG: Output fort.19000+myrank and fort.29000+myrank for coloring information'
378  endif
379  write(19000+my_rank,'(a)') '#NCOLORTot'
380  write(19000+my_rank,*) ncolor
381  write(19000+my_rank,'(a)') '#ic COLORindex(ic-1)+1 COLORindex(ic)'
382  do ic=1,ncolor
383  write(19000+my_rank,*) ic, colorindex(ic-1)+1,colorindex(ic)
384  enddo ! ic
385  write(29000+my_rank,'(a)') '#n_node'
386  write(29000+my_rank,*) n
387  write(29000+my_rank,'(a)') '#in OLDtoNEW(in) NEWtoOLD(in)'
388  do in=1,n
389  write(29000+my_rank,*) in, iperm(in), perm(in)
390  if (perm(iperm(in)) .ne. in) then
391  write(29000+my_rank,*) '** WARNING **: NEWtoOLD and OLDtoNEW: ',in
392  endif
393  enddo
394  end subroutine write_debug_info
395 
396  subroutine check_ordering
397  implicit none
398  integer(kind=kint) :: ic, i, j, k
399  integer(kind=kint), allocatable :: iicolor(:)
400  ! check color dependence of neighbouring nodes
401  if (ncolor.gt.1) then
402  allocate(iicolor(n))
403  do ic=1,ncolor
404  do i= colorindex(ic-1)+1, colorindex(ic)
405  iicolor(i) = ic
406  enddo ! i
407  enddo ! ic
408  ! FORWARD: L-part
409  do ic=1,ncolor
410  do i= colorindex(ic-1)+1, colorindex(ic)
411  do j= indexl(i-1)+1, indexl(i)
412  k= iteml(j)
413  if (iicolor(i).eq.iicolor(k)) then
414  write(*,*) .eq.'** ERROR **: L-part: iicolor(i)iicolor(k)',i,k,iicolor(i)
415  endif
416  enddo ! j
417  enddo ! i
418  enddo ! ic
419  ! BACKWARD: U-part
420  do ic=ncolor, 1, -1
421  do i= colorindex(ic), colorindex(ic-1)+1, -1
422  do j= indexu(i-1)+1, indexu(i)
423  k= itemu(j)
424  if (iicolor(i).eq.iicolor(k)) then
425  write(*,*) .eq.'** ERROR **: U-part: iicolor(i)iicolor(k)',i,k,iicolor(i)
426  endif
427  enddo ! j
428  enddo ! i
429  enddo ! ic
430  deallocate(iicolor)
431  endif ! if (NColor.gt.1)
432  !--------------------< debug: shizawa
433  end subroutine check_ordering
434 
435 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)