FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_precond_SSOR_nn.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_nn
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_nn_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(hecmat%NDOF,hecmat%NDOF), pw(hecmat%NDOF)
70  integer(kind=kint ) :: ii, i, j, k, ndof, ndof2
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_nn_clear(hecmat)
83  else if (hecmat%Iarray(97) == 1) then ! need numerical setup only
84  call hecmw_precond_ssor_nn_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  ndof=hecmat%NDOF
96  ndof2=ndof*ndof
97 
98  ncolor_in = hecmw_mat_get_ncolor_in(hecmat)
99  omega = hecmw_mat_get_omega(hecmat)
100  omega_inv = 1.d0 / omega
101 
102 #ifdef _OPENACC
103  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
104  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
105  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
106  if (ssor_debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
107  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
108  hecmat%indexU, hecmat%itemU, perm_tmp, &
109  ncolor_in, ncolor, colorindex, perm, iperm)
110  if (ssor_debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
111  deallocate(perm_tmp)
112 
113 #else
114  if (nthreads == 1) then
115  ncolor = 1
116  allocate(colorindex(0:1), perm(n), iperm(n))
117  colorindex(0) = 0
118  colorindex(1) = n
119  do i=1,n
120  perm(i) = i
121  iperm(i) = i
122  end do
123  else
124  allocate(colorindex(0:n), perm_tmp(n), perm(n), iperm(n))
125  call hecmw_matrix_ordering_rcm(n, hecmat%indexL, hecmat%itemL, &
126  hecmat%indexU, hecmat%itemU, perm_tmp, iperm)
127  if (ssor_debug >= 1) write(*,*) 'DEBUG: RCM ordering done', hecmw_wtime()-t0
128  call hecmw_matrix_ordering_mc(n, hecmat%indexL, hecmat%itemL, &
129  hecmat%indexU, hecmat%itemU, perm_tmp, &
130  ncolor_in, ncolor, colorindex, perm, iperm)
131  if (ssor_debug >= 1) write(*,*) 'DEBUG: MC ordering done', hecmw_wtime()-t0
132  deallocate(perm_tmp)
133 
134  endif
135 #endif
136 
137  npl = 0
138  do i=1,n
139  do j=hecmat%indexU(i-1)+1,hecmat%indexU(i)
140  if( hecmat%itemU(j) > n ) exit
141  npl = npl + 1
142  enddo
143  enddo
144  npl = max(hecmat%indexL(n),npl)
145  npu = hecmat%indexU(n)
146  allocate(indexl(0:n), indexu(0:n), iteml(npl), itemu(npu))
147  call hecmw_matrix_reorder_profile(n, perm, iperm, &
148  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
149  indexl, indexu, iteml, itemu)
150  if (ssor_debug >= 1) write(*,*) 'DEBUG: reordering profile done', hecmw_wtime()-t0
151 
152 
153  allocate(d(ndof2*n), al(ndof2*npl), au(ndof2*npu))
154  call hecmw_matrix_reorder_values(n, ndof, perm, iperm, &
155  hecmat%indexL, hecmat%indexU, hecmat%itemL, hecmat%itemU, &
156  hecmat%AL, hecmat%AU, hecmat%D, &
157  indexl, indexu, iteml, itemu, al, au, d)
158  if (ssor_debug >= 1) write(*,*) 'DEBUG: reordering values done', hecmw_wtime()-t0
159 
160  call hecmw_matrix_reorder_renum_item(n, perm, indexl, iteml)
161  call hecmw_matrix_reorder_renum_item(n, perm, indexu, itemu)
162 
163  allocate(alu(ndof2*n))
164  alu = 0.d0
165 
166  do ii= 1, ndof2*n
167  alu(ii) = d(ii)
168  enddo
169 
170 #ifdef _OPENACC
171  !$acc kernels
172  !$acc loop independent private(ALUtmp,PW)
173 #else
174  !$omp parallel default(none),private(ii,ALUtmp,k,i,j,PW),shared(N,NDOF,NDOF2,ALU,OMEGA_INV)
175  !$omp do
176 #endif
177  do ii= 1, n
178  do i = 1, ndof
179  do j = 1, ndof
180  alutmp(i,j) = alu(ndof2*(ii-1)+(i-1)*ndof+j) * omega_inv
181  end do
182  end do
183  do k= 1, ndof
184  alutmp(k,k)= 1.d0/alutmp(k,k)
185  do i= k+1, ndof
186  alutmp(i,k)= alutmp(i,k) * alutmp(k,k)
187  do j= k+1, ndof
188  pw(j)= alutmp(i,j) - alutmp(i,k)*alutmp(k,j)
189  enddo
190  do j= k+1, ndof
191  alutmp(i,j)= pw(j)
192  enddo
193  enddo
194  enddo
195  do i = 1, ndof
196  do j = 1, ndof
197  alu(ndof2*(ii-1)+(i-1)*ndof+j)= alutmp(i,j)
198  end do
199  end do
200  enddo
201 #ifdef _OPENACC
202  !$acc end kernels
203 #else
204  !$omp end do
205  !$omp end parallel
206 #endif
207 
208  isfirst = .true.
209 
210  initialized = .true.
211  hecmat%Iarray(98) = 0 ! symbolic setup done
212  hecmat%Iarray(97) = 0 ! numerical setup done
213 
214  if (ssor_debug >= 1) write(*,*) 'DEBUG: SSOR setup done', hecmw_wtime()-t0
215 
216  end subroutine hecmw_precond_ssor_nn_setup
217 
218  subroutine setup_tuning_parameters(NDOF)
219  use hecmw_tuning_fx
220  implicit none
221  integer(kind=kint), intent(in) :: ndof
222  integer(kind=kint) :: blockindex, elementcount, numofelement, ii
223  real(kind=kreal) :: numofelementperblock
224  integer(kind=kint) :: ic, i
225  if (ssor_debug >= 1) write(*,*) 'DEBUG: setting up tuning parameters for SSOR'
226 #ifndef _OPENACC
227  !$ numOfThread = omp_get_max_threads()
228 #endif
229 
230  numofblock = numofthread * numofblockperthread
231  if (allocated(ictoblockindex)) deallocate(ictoblockindex)
232  if (allocated(blockindextocolorindex)) deallocate(blockindextocolorindex)
233  allocate (ictoblockindex(0:ncolor), &
234  blockindextocolorindex(0:numofblock + ncolor))
235  numofelement = n + indexl(n) + indexu(n)
236  numofelementperblock = dble(numofelement) / numofblock
237  blockindex = 0
238  ictoblockindex = -1
239  ictoblockindex(0) = 0
240  blockindextocolorindex = -1
241  blockindextocolorindex(0) = 0
242  do ic = 1, ncolor
243  elementcount = 0
244  ii = 1
245  do i = colorindex(ic-1)+1, colorindex(ic)
246  elementcount = elementcount + 1
247  elementcount = elementcount + (indexl(i) - indexl(i-1))
248  elementcount = elementcount + (indexu(i) - indexu(i-1))
249  if (elementcount > ii * numofelementperblock &
250  .or. i == colorindex(ic)) then
251  ii = ii + 1
252  blockindex = blockindex + 1
253  blockindextocolorindex(blockindex) = i
254  endif
255  enddo
256  ictoblockindex(ic) = blockindex
257  enddo
258  numofblock = blockindex
259 
260  call hecmw_tuning_fx_calc_sector_cache( n, ndof, &
261  sectorcachesize0, sectorcachesize1 )
262  end subroutine setup_tuning_parameters
263 
264  subroutine hecmw_precond_ssor_nn_apply(ZP, NDOF)
265  implicit none
266  real(kind=kreal), intent(inout) :: zp(:)
267  integer(kind=kint) :: ic, i, iold, j, isl, iel, isu, ieu, k, ndof, ndof2, idof,jdof
268  real(kind=kreal) :: sw(ndof), x(ndof)
269 
270  real(kind=kreal) :: omega_fac
271 
272  ! added for tuning >>>
273  integer(kind=kint) :: blockindex
274 
275  ndof2=ndof*ndof
276 #ifndef _OPENACC
277  if (isfirst) then
278  call setup_tuning_parameters(ndof)
279  isfirst = .false.
280  endif
281 #endif
282  ! <<< added for tuning
283 
284  omega_fac = 2.d0 - omega
285 
286 #ifndef _OPENACC
287  !call start_collection("loopInPrecondnn")
288 
289  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
290  !OCL CACHE_SUBSECTOR_ASSIGN(ZP)
291 
292  !$omp parallel default(none) &
293  !$omp&shared(NColor,indexL,itemL,indexU,itemU,AL,AU,D,ALU,perm,&
294  !$omp& ZP,icToBlockIndex,blockIndexToColorIndex,NDOF,NDOF2,OMEGA_FAC) &
295  !$omp&private(SW,X,ic,i,iold,isL,ieL,isU,ieU,j,k,blockIndex,idof,jdof)
296 #endif
297 
298  !C-- FORWARD
299  do ic=1,ncolor
300 #ifdef _OPENACC
301  !$acc kernels
302  !$acc loop independent private(X,SW)
303  do i = colorindex(ic-1)+1, colorindex(ic)
304 #else
305  !$omp do schedule (static, 1)
306  do blockindex = ictoblockindex(ic-1)+1, ictoblockindex(ic)
307  do i = blockindextocolorindex(blockindex-1)+1, &
308  blockindextocolorindex(blockindex)
309 #endif
310  iold = perm(i)
311  do idof = 1, ndof
312  sw(idof) = omega_fac * zp(ndof*(iold-1)+idof)
313  end do
314  isl= indexl(i-1)+1
315  iel= indexl(i)
316  do j= isl, iel
317  k= iteml(j)
318  do idof = 1, ndof
319  x(idof) = zp(ndof*(k-1)+idof)
320  end do
321  do idof = 1, ndof
322  do jdof = 1, ndof
323  sw(idof) = sw(idof) - al(ndof2*(j-1)+ndof*(idof-1)+jdof)*x(jdof)
324  end do
325  end do
326  enddo ! j
327 
328  x = sw
329  do idof = 2,ndof
330  do jdof = 1, idof-1
331  x(idof) = x(idof) - alu(ndof2*(i-1)+ndof*(idof-1)+jdof )*x(jdof)
332  end do
333  end do
334  do idof = ndof, 1, -1
335  do jdof = ndof, idof+1, -1
336  x(idof) = x(idof) - alu(ndof2*(i-1)+ndof*(idof-1)+jdof)*x(jdof)
337  end do
338  x(idof) = alu(ndof2*(i-1)+(ndof+1)*(idof-1)+1)*x(idof)
339  end do
340  zp(ndof*(iold-1)+1:ndof*(iold-1)+ndof) = x(1:ndof)
341 
342 #ifdef _OPENACC
343  enddo
344  !$acc end kernels
345 #else
346  enddo ! i
347  enddo ! blockIndex
348  !$omp end do
349 #endif
350  enddo ! ic
351 
352  !C-- BACKWARD
353  do ic=ncolor, 1, -1
354 #ifdef _OPENACC
355  !$acc kernels
356  !$acc loop independent private(X,SW)
357  do i = colorindex(ic-1)+1, colorindex(ic)
358 #else
359  !$omp do schedule (static, 1)
360  do blockindex = ictoblockindex(ic), ictoblockindex(ic-1)+1, -1
361  do i = blockindextocolorindex(blockindex), &
362  blockindextocolorindex(blockindex-1)+1, -1
363 #endif
364  ! do blockIndex = icToBlockIndex(ic-1)+1, icToBlockIndex(ic)
365  ! do i = blockIndexToColorIndex(blockIndex-1)+1, &
366  ! blockIndexToColorIndex(blockIndex)
367  ! do i = endPos(threadNum, ic), startPos(threadNum, ic), -1
368  sw= 0.d0
369  isu= indexu(i-1) + 1
370  ieu= indexu(i)
371  do j= ieu, isu, -1
372  k= itemu(j)
373  do idof = 1, ndof
374  x(idof) = zp(ndof*(k-1)+idof)
375  end do
376  do idof = 1, ndof
377  do jdof = 1, ndof
378  sw(idof) = sw(idof) + au(ndof2*(j-1)+ndof*(idof-1)+jdof)*x(jdof)
379  end do
380  end do
381  enddo ! j
382 
383  x = sw
384  do idof = 2, ndof
385  do k = 1,idof-1
386  x(idof) = x(idof) - alu(ndof2*(i-1)+ndof*(idof-1)+k)*x(k)
387  end do
388  end do
389  do idof = ndof, 1, -1
390  do k = ndof, idof+1, -1
391  x(idof) = x(idof) - alu(ndof2*(i-1)+ndof*(idof-1)+k)*x(k)
392  end do
393  x(idof) = alu(ndof2*(i-1)+(ndof+1)*(idof-1)+1)*x(idof)
394  end do
395  iold = perm(i)
396  do idof = 1, ndof
397  zp(ndof*(iold-1)+idof) = zp(ndof*(iold-1)+idof) - x(idof)
398  end do
399 #ifdef _OPENACC
400  enddo
401  !$acc end kernels
402 #else
403  enddo ! i
404  enddo ! blockIndex
405  !$omp end do
406 #endif
407  enddo ! ic
408 #ifndef _OPENACC
409  !$omp end parallel
410 
411  !OCL END_CACHE_SUBSECTOR
412  !OCL END_CACHE_SECTOR_SIZE
413 
414  !call stop_collection("loopInPrecondnn")
415 #endif
416 
417  end subroutine hecmw_precond_ssor_nn_apply
418 
419  subroutine hecmw_precond_ssor_nn_clear(hecMAT)
420  implicit none
421  type(hecmwst_matrix), intent(inout) :: hecmat
422  if (associated(colorindex)) deallocate(colorindex)
423  if (associated(perm)) deallocate(perm)
424  if (associated(iperm)) deallocate(iperm)
425  if (associated(alu)) deallocate(alu)
426  if (associated(d)) deallocate(d)
427  if (associated(al)) deallocate(al)
428  if (associated(au)) deallocate(au)
429  if (associated(indexl)) deallocate(indexl)
430  if (associated(indexu)) deallocate(indexu)
431  if (associated(iteml)) deallocate(iteml)
432  if (associated(itemu)) deallocate(itemu)
433  nullify(colorindex)
434  nullify(perm)
435  nullify(iperm)
436  nullify(alu)
437  nullify(d)
438  nullify(al)
439  nullify(au)
440  nullify(indexl)
441  nullify(indexu)
442  nullify(iteml)
443  nullify(itemu)
444  initialized = .false.
445  end subroutine hecmw_precond_ssor_nn_clear
446 
447 end module hecmw_precond_ssor_nn
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_nn_setup(hecMAT)
subroutine, public hecmw_precond_ssor_nn_clear(hecMAT)
subroutine, public hecmw_precond_ssor_nn_apply(ZP, NDOF)
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)