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