FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_solver_las_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 
7  use hecmw_util
8  implicit none
9 
10  private
11 
12  public :: hecmw_matvec_nn
13  public :: hecmw_matresid_nn
14  public :: hecmw_rel_resid_l2_nn
15  public :: hecmw_tvec_nn
16  public :: hecmw_ttvec_nn
17 
18 contains
19 
20  !C
21  !C***
22  !C*** hecmw_matvec_nn
23  !C***
24  !C
25  subroutine hecmw_matvec_nn (hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
26  use hecmw_util
27  use m_hecmw_comm_f
28  use hecmw_jad_type
29  use hecmw_tuning_fx
30  !$ use omp_lib
31 
32  implicit none
33  type (hecmwst_local_mesh), intent(in) :: hecmesh
34  type (hecmwst_matrix), intent(in), target :: hecmat
35  real(kind=kreal), intent(inout) :: x(:)
36  real(kind=kreal), intent(out) :: y(:)
37  real(kind=kreal), intent(inout) :: time_ax
38  real(kind=kreal), intent(inout), optional :: commtime
39 
40  real(kind=kreal) :: start_time, end_time, tcomm
41  integer(kind=kint) :: i, j, k, l, js, je, in
42  real(kind=kreal) :: yv(hecmat%NDOF), xv(hecmat%NDOF)
43 
44  integer(kind=kint) :: n, np, ndof, ndof2
45  integer(kind=kint), pointer :: indexl(:), iteml(:), indexu(:), itemu(:), indexa(:), itema(:)
46  real(kind=kreal), pointer :: al(:), au(:), d(:), a(:)
47 
48  ! added for tuning >>>
49  integer, parameter :: numofblockperthread = 100
50  logical, save :: isfirst = .true.
51  integer, save :: numofthread = 1
52  integer, save, allocatable :: startpos(:), endpos(:)
53  integer(kind=kint), save :: sectorcachesize0, sectorcachesize1
54  integer(kind=kint) :: threadnum, blocknum, numofblock
55  integer(kind=kint) :: numofelement, elementcount, blockindex
56  real(kind=kreal) :: numofelementperblock
57  ! <<< added for tuning
58 
59  if (hecmw_jad_is_initialized().ne.0) then
60  tcomm = 0.d0
61  start_time = hecmw_wtime()
62  call hecmw_jad_matvec(hecmesh, hecmat, x, y, tcomm)
63  end_time = hecmw_wtime()
64  time_ax = time_ax + end_time - start_time - tcomm
65  if (present(commtime)) commtime = commtime + tcomm
66  else
67 
68  n = hecmat%N
69  np = hecmat%NP
70  indexl => hecmat%indexL
71  indexu => hecmat%indexU
72  indexa => hecmat%indexA
73  iteml => hecmat%itemL
74  itemu => hecmat%itemU
75  itema => hecmat%itemA
76  al => hecmat%AL
77  au => hecmat%AU
78  d => hecmat%D
79  a => hecmat%A
80  ndof = hecmat%NDOF
81  ndof2 = ndof*ndof
82 
83  ! added for tuning >>>
84 #ifndef _OPENACC
85  if (.not. isfirst) then
86  numofblock = numofthread * numofblockperthread
87  if (endpos(numofblock-1) .ne. n-1) then
88  deallocate(startpos, endpos)
89  isfirst = .true.
90  endif
91  endif
92  if (isfirst) then
93  !$ numOfThread = omp_get_max_threads()
94  numofblock = numofthread * numofblockperthread
95  allocate (startpos(0 : numofblock - 1), endpos(0 : numofblock - 1))
96  numofelement = n + indexl(n) + indexu(n)
97  numofelementperblock = dble(numofelement) / numofblock
98  blocknum = 0
99  elementcount = 0
100  startpos(blocknum) = 1
101  do i= 1, n
102  elementcount = elementcount + 1
103  elementcount = elementcount + (indexl(i) - indexl(i-1))
104  elementcount = elementcount + (indexu(i) - indexu(i-1))
105  if (elementcount > (blocknum + 1) * numofelementperblock) then
106  endpos(blocknum) = i
107  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
108  ! startPos(blockNum), endPos(blockNum)
109  blocknum = blocknum + 1
110  startpos(blocknum) = i + 1
111  if (blocknum == (numofblock - 1)) exit
112  endif
113  enddo
114  endpos(blocknum) = n
115  ! write(9000+hecMESH%my_rank,*) mod(blockNum, numOfThread), &
116  ! startPos(blockNum), endPos(blockNum)
117  ! for irregular data
118  do i= blocknum+1, numofblock-1
119  startpos(i) = n
120  endpos(i) = n-1
121  ! write(9000+hecMESH%my_rank,*) mod(i, numOfThread), &
122  ! startPos(i), endPos(i)
123  end do
124 
125  call hecmw_tuning_fx_calc_sector_cache(np, ndof, &
126  sectorcachesize0, sectorcachesize1)
127 
128  isfirst = .false.
129  endif
130 #endif
131  ! <<< added for tuning
132 
133  start_time= hecmw_wtime()
134  call hecmw_update_r (hecmesh, x, np, ndof)
135  end_time= hecmw_wtime()
136  if (present(commtime)) commtime = commtime + end_time - start_time
137 
138  start_time = hecmw_wtime()
139 
140 #ifdef _OPENACC
141  !$acc kernels
142  !$acc loop independent
143  do i = 1, n
144  do k=1,ndof
145  xv(k) = x(ndof*(i-1)+k)
146  end do
147  yv(:)=0.0d0
148  js= indexa(i-1) + 1
149  je= indexa(i)
150  do j= js, je
151  in = itema(j)
152  do k=1,ndof
153  xv(k) = x(ndof*(in-1)+k)
154  end do
155  do k=1,ndof
156  do l=1,ndof
157  yv(k)=yv(k)+a(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
158  end do
159  end do
160  enddo
161  do k=1,ndof
162  y(ndof*(i-1)+k) = yv(k)
163  end do
164  enddo
165  !$acc end kernels
166 #else
167  !call fapp_start("loopInMatvecnn", 1, 0)
168  !call start_collection("loopInMatvecnn")
169 
170  !OCL CACHE_SECTOR_SIZE(sectorCacheSize0,sectorCacheSize1)
171  !OCL CACHE_SUBSECTOR_ASSIGN(X)
172 
173  !$OMP PARALLEL DEFAULT(NONE) &
174  !$OMP&PRIVATE(i,XV,YV,jS,jE,j,k,l,in,threadNum,blockNum,blockIndex) &
175  !$OMP&SHARED(D,AL,AU,indexL,itemL,indexU,itemU,X,Y,startPos,endPos,numOfThread,N,NDOF,NDOF2)
176  threadnum = 0
177  !$ threadNum = omp_get_thread_num()
178  do blocknum = 0 , numofblockperthread - 1
179  blockindex = blocknum * numofthread + threadnum
180  do i = startpos(blockindex), endpos(blockindex)
181  do k=1,ndof
182  xv(k) = x(ndof*(i-1)+k)
183  end do
184  yv(:)=0.0d0
185  do k=1,ndof
186  do l=1,ndof
187  yv(k)=yv(k)+d(ndof2*(i-1)+(k-1)*ndof+l)*xv(l)
188  end do
189  end do
190  js= indexl(i-1) + 1
191  je= indexl(i )
192  do j= js, je
193  in = iteml(j)
194  do k=1,ndof
195  xv(k) = x(ndof*(in-1)+k)
196  end do
197  do k=1,ndof
198  do l=1,ndof
199  yv(k)=yv(k)+al(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
200  end do
201  end do
202  enddo
203  js= indexu(i-1) + 1
204  je= indexu(i )
205  do j= js, je
206  in = itemu(j)
207  do k=1,ndof
208  xv(k) = x(ndof*(in-1)+k)
209  end do
210  do k=1,ndof
211  do l=1,ndof
212  yv(k)=yv(k)+au(ndof2*(j-1)+(k-1)*ndof+l)*xv(l)
213  end do
214  end do
215  enddo
216  do k=1,ndof
217  y(ndof*(i-1)+k) = yv(k)
218  end do
219  enddo
220  enddo
221  !$OMP END PARALLEL
222 
223  !OCL END_CACHE_SUBSECTOR
224  !OCL END_CACHE_SECTOR_SIZE
225 
226  !call stop_collection("loopInMatvecnn")
227  !call fapp_stop("loopInMatvecnn", 1, 0)
228 #endif
229 
230  end_time = hecmw_wtime()
231  time_ax = time_ax + end_time - start_time
232  endif
233 
234  end subroutine hecmw_matvec_nn
235 
236 
237 
238  !C
239  !C***
240  !C*** hecmw_matresid_nn
241  !C***
242  !C
243  subroutine hecmw_matresid_nn (hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
244  use hecmw_util
245  implicit none
246  type (hecmwst_local_mesh), intent(in) :: hecmesh
247  type (hecmwst_matrix), intent(in) :: hecmat
248  real(kind=kreal), intent(in) :: b(:)
249  real(kind=kreal), intent(inout) :: x(:)
250  real(kind=kreal), intent(out) :: r(:)
251  real(kind=kreal), intent(inout) :: time_ax
252  real(kind=kreal), intent(inout), optional :: commtime
253 
254  integer(kind=kint) :: i
255  real(kind=kreal) :: tcomm
256 
257  tcomm = 0.d0
258  call hecmw_matvec_nn (hecmesh, hecmat, x, r, time_ax, tcomm)
259  if (present(commtime)) commtime = commtime + tcomm
260 #ifdef _OPENACC
261  !$acc kernels
262  !$acc loop independent
263 #else
264  !$omp parallel default(none),private(i),shared(hecMAT,R,B)
265  !$omp do
266 #endif
267  do i = 1, hecmat%N * hecmat%NDOF
268  r(i) = b(i) - r(i)
269  enddo
270 #ifdef _OPENACC
271  !$acc end kernels
272 #else
273  !$omp end do
274  !$omp end parallel
275 #endif
276  end subroutine hecmw_matresid_nn
277 
278  !C
279  !C***
280  !C*** hecmw_rel_resid_L2_nn
281  !C***
282  !C
283  function hecmw_rel_resid_l2_nn (hecMESH, hecMAT, time_Ax, COMMtime)
284  use hecmw_util
286  implicit none
287  real(kind=kreal) :: hecmw_rel_resid_l2_nn
288  type ( hecmwst_local_mesh ), intent(in) :: hecmesh
289  type ( hecmwst_matrix ), intent(in) :: hecmat
290  real(kind=kreal), intent(inout) :: time_ax
291  real(kind=kreal), intent(inout), optional :: commtime
292 
293  real(kind=kreal), allocatable :: r(:)
294  real(kind=kreal) :: bnorm2, rnorm2
295  real(kind=kreal) :: tcomm
296 
297  allocate(r(hecmat%NDOF*hecmat%NP))
298 
299  tcomm = 0.d0
300  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, &
301  hecmat%B, hecmat%B, bnorm2, tcomm)
302  if (bnorm2 == 0.d0) then
303  bnorm2 = 1.d0
304  endif
305  call hecmw_matresid_nn(hecmesh, hecmat, hecmat%X, hecmat%B, r, time_ax, tcomm)
306  call hecmw_innerproduct_r(hecmesh, hecmat%NDOF, r, r, rnorm2, tcomm)
307  hecmw_rel_resid_l2_nn = sqrt(rnorm2 / bnorm2)
308 
309  if (present(commtime)) commtime = commtime + tcomm
310 
311  deallocate(r)
312  end function hecmw_rel_resid_l2_nn
313 
314  !C
315  !C***
316  !C*** hecmw_Tvec_nn
317  !C***
318  !C
319  subroutine hecmw_tvec_nn (hecMESH, ndof, X, Y, COMMtime)
320  use hecmw_util
321  use m_hecmw_comm_f
322  implicit none
323  type (hecmwst_local_mesh), intent(in) :: hecmesh
324  integer(kind=kint), intent(in) :: ndof
325  real(kind=kreal), intent(inout) :: x(:)
326  real(kind=kreal), intent(out) :: y(:)
327  real(kind=kreal), intent(inout) :: commtime
328 
329  real(kind=kreal) :: start_time, end_time
330  integer(kind=kint) :: i, j, jj, k, kk
331 
332  start_time= hecmw_wtime()
333  call hecmw_update_r (hecmesh, x, hecmesh%n_node, ndof)
334  end_time= hecmw_wtime()
335  commtime = commtime + end_time - start_time
336 
337 #ifdef _OPENACC
338  !$acc kernels
339  !$acc loop independent
340 #else
341  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y),firstprivate(ndof)
342  !$omp do
343 #endif
344  do i= 1, hecmesh%nn_internal * ndof
345  y(i)= x(i)
346  enddo
347 #ifndef _OPENACC
348  !$omp end do
349 #endif
350 
351 #ifdef _OPENACC
352  !$acc loop independent
353 #else
354  !$omp do
355 #endif
356  outer: do i= 1, hecmesh%mpc%n_mpc
357  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
358  if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
359  enddo
360  k = hecmesh%mpc%mpc_index(i-1) + 1
361  kk = ndof * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
362  y(kk) = 0.d0
363  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
364  jj = ndof * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
365  y(kk) = y(kk) - hecmesh%mpc%mpc_val(j) * x(jj)
366  enddo
367  enddo outer
368 #ifdef _OPENACC
369  !$acc end kernels
370 #else
371  !$omp end do
372  !$omp end parallel
373 #endif
374 
375  end subroutine hecmw_tvec_nn
376 
377  !C
378  !C***
379  !C*** hecmw_Ttvec_nn
380  !C***
381  !C
382  subroutine hecmw_ttvec_nn (hecMESH, ndof, X, Y, COMMtime)
383  use hecmw_util
384  use m_hecmw_comm_f
385  implicit none
386  type (hecmwst_local_mesh), intent(in) :: hecmesh
387  integer(kind=kint), intent(in) :: ndof
388  real(kind=kreal), intent(inout) :: x(:)
389  real(kind=kreal), intent(inout) :: y(:)
390  real(kind=kreal), intent(inout) :: commtime
391 
392  real(kind=kreal) :: start_time, end_time
393  integer(kind=kint) :: i, j, jj, k, kk
394 
395  start_time= hecmw_wtime()
396  call hecmw_update_r (hecmesh, x, hecmesh%n_node,ndof)
397  end_time= hecmw_wtime()
398  commtime = commtime + end_time - start_time
399 
400 #ifdef _OPENACC
401  !$acc kernels
402  !$acc loop independent
403 #else
404  !$omp parallel default(none),private(i,k,kk,j,jj),shared(hecMESH,X,Y),firstprivate(ndof)
405  !$omp do
406 #endif
407  do i= 1, hecmesh%nn_internal * ndof
408  y(i)= x(i)
409  enddo
410 #ifndef _OPENACC
411  !$omp end do
412 #endif
413 
414 #ifdef _OPENACC
415  !$acc loop independent
416 #else
417  !$omp do
418 #endif
419  outer: do i= 1, hecmesh%mpc%n_mpc
420  do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
421  if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
422  enddo
423  k = hecmesh%mpc%mpc_index(i-1) + 1
424  kk = ndof * (hecmesh%mpc%mpc_item(k) - 1) + hecmesh%mpc%mpc_dof(k)
425  y(kk) = 0.d0
426  do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
427  jj = ndof * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
428 #ifdef _OPENACC
429  !$acc atomic update
430 #else
431  !$omp atomic
432 #endif
433  y(jj) = y(jj) - hecmesh%mpc%mpc_val(j) * x(kk)
434  enddo
435  enddo outer
436 #ifdef _OPENACC
437  !$acc end kernels
438 #else
439  !$omp end do
440  !$omp end parallel
441 #endif
442 
443 
444  end subroutine hecmw_ttvec_nn
445 
446  !C
447  !C***
448  !C*** hecmw_mat_diag_sr_nn
449  !C***
450  !C
451  subroutine hecmw_mat_diag_sr_nn(hecMESH, hecMAT, COMMtime)
452  use hecmw_util
453  use m_hecmw_comm_f
454  implicit none
455  type (hecmwST_local_mesh), intent(in) :: hecMESH
456  type (hecmwST_matrix), intent(inout), target :: hecMAT
457  real(kind=kreal), intent(inout), optional :: commtime
458  real(kind=kreal), allocatable :: w(:,:)
459  real(kind=kreal), pointer :: d(:)
460  integer(kind=kint) :: ip, NDOF, i, j
461  real(kind=kreal) :: start_time, end_time
462  ndof = hecmat%NDOF
463  allocate(w(ndof*hecmat%NP,ndof))
464  d => hecmat%D
465  do ip= 1, hecmat%N
466  do i=1,ndof
467  do j=1,ndof
468  w(ndof*(ip-1)+i,j) = d(ndof*ndof*(ip-1)+(i-1)*ndof+j)
469  end do
470  end do
471  enddo
472  start_time= hecmw_wtime()
473  do i=1,ndof
474  call hecmw_update_r (hecmesh, w(:,i), hecmat%NP, ndof)
475  end do
476  end_time= hecmw_wtime()
477  if (present(commtime)) commtime = commtime + end_time - start_time
478  do ip= hecmat%N+1, hecmat%NP
479  do i=1,ndof
480  do j=1,ndof
481  d(ndof*ndof*(ip-1)+(i-1)*ndof+j) = w(ndof*(ip-1)+i,j)
482  end do
483  end do
484  enddo
485  deallocate(w)
486  end subroutine hecmw_mat_diag_sr_nn
487 
488  subroutine hecmw_mat_add_nn(hecMAT1, hecMAT2, hecMAT3)
489  use hecmw_util
490  implicit none
491  type (hecmwST_matrix) :: hecMAT1, hecMAT2, hecMAT3
492  integer(kind=kint) :: i
493 
494  do i = 1, hecmat1%NP*hecmat1%NDOF*hecmat1%NDOF
495  hecmat3%D(i) = hecmat1%D(i) + hecmat2%D(i)
496  enddo
497 
498  do i = 1, hecmat1%NPU*hecmat1%NDOF*hecmat1%NDOF
499  hecmat3%AU(i) = hecmat1%AU(i) + hecmat2%AU(i)
500  enddo
501 
502  do i = 1, hecmat1%NPL*hecmat1%NDOF*hecmat1%NDOF
503  hecmat3%AL(i) = hecmat1%AL(i) + hecmat2%AL(i)
504  enddo
505  end subroutine hecmw_mat_add_nn
506 
507  subroutine hecmw_mat_multiple_nn(hecMAT, alpha)
508  use hecmw_util
509  implicit none
510  type (hecmwST_matrix) :: hecMAT
511  real(kind=kreal), intent(in) :: alpha
512  integer(kind=kint) :: i
513 
514  do i = 1, hecmat%NP*hecmat%NDOF*hecmat%NDOF
515  hecmat%D(i) = alpha*hecmat%D(i)
516  enddo
517 
518  do i = 1, hecmat%NPU*hecmat%NDOF*hecmat%NDOF
519  hecmat%AU(i) = alpha*hecmat%AU(i)
520  enddo
521 
522  do i = 1, hecmat%NPL*hecmat%NDOF*hecmat%NDOF
523  hecmat%AL(i) = alpha*hecmat%AL(i)
524  enddo
525  end subroutine hecmw_mat_multiple_nn
526 end module hecmw_solver_las_nn
Jagged Diagonal Matrix storage for vector processors. Original code was provided by JAMSTEC.
Definition: hecmw_jadm.f90:8
subroutine, public hecmw_jad_matvec(hecMESH, hecMAT, X, Y, COMMtime)
Definition: hecmw_jadm.f90:61
integer(kind=kint) function, public hecmw_jad_is_initialized()
Definition: hecmw_jadm.f90:56
subroutine hecmw_mat_multiple_nn(hecMAT, alpha)
subroutine hecmw_mat_add_nn(hecMAT1, hecMAT2, hecMAT3)
subroutine, public hecmw_ttvec_nn(hecMESH, ndof, X, Y, COMMtime)
real(kind=kreal) function, public hecmw_rel_resid_l2_nn(hecMESH, hecMAT, time_Ax, COMMtime)
subroutine, public hecmw_tvec_nn(hecMESH, ndof, X, Y, COMMtime)
subroutine, public hecmw_matvec_nn(hecMESH, hecMAT, X, Y, time_Ax, COMMtime)
subroutine, public hecmw_matresid_nn(hecMESH, hecMAT, X, B, R, time_Ax, COMMtime)
subroutine hecmw_mat_diag_sr_nn(hecMESH, hecMAT, COMMtime)
subroutine hecmw_innerproduct_r(hecMESH, ndof, X, Y, sum, COMMtime)
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 hecmw_update_r(hecMESH, val, n, m)