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