8 # define WITH_CLUSTERMKL
12 #ifdef WITH_CLUSTERMKL
13 include
'mkl_cluster_sparse_solver.f90'
21 #ifdef WITH_CLUSTERMKL
22 use mkl_cluster_sparse_solver
30 logical,
save :: INITIALIZED = .false.
31 #ifdef WITH_CLUSTERMKL
32 type(MKL_CLUSTER_SPARSE_SOLVER_HANDLE) :: pt(64)
34 integer maxfct, mnum, mtype, nrhs, msglvl
36 data nrhs /1/, maxfct /1/, mnum /1/
38 integer,
save :: iparm(64)
39 integer(kind=kint),
save :: nn
40 integer(kind=kint),
pointer,
save :: irow(:), jcol(:)
41 real(kind=
kreal),
pointer,
save :: aval(:), rhs(:), solx(:)
43 integer(kind=kint),
parameter :: debug=0
49 type (sparse_matrix),
intent(inout) :: spmat
50 integer(kind=kint),
intent(in) :: phase_start
51 integer(kind=kint),
intent(out) :: istat
52 real(kind=
kreal),
pointer,
intent(inout) :: solution(:)
54 integer(kind=kint) ::
myrank, phase
55 real(kind=
kreal) :: t1,t2,t3,t4,t5
57 #ifdef WITH_CLUSTERMKL
61 if (.not. initialized)
then
82 if( phase_start == 1 )
then
84 call cluster_sparse_solver ( &
85 pt, maxfct, mnum, mtype, phase, nn, aval, irow, jcol, &
88 write(*,*)
'ERROR: MKL returned with error in phase -1', istat
97 if ( phase_start == 1 )
then
109 iparm(41) = spmat%DISPLS(
myrank+1)+1
110 iparm(42) = spmat%DISPLS(
myrank+1)+spmat%N_COUNTS(
myrank+1)
111 call sort_column_ascending_order(spmat,
myrank)
121 call export_spmat_to_centralizedcrs(spmat,
myrank,nn,irow,jcol,aval,rhs,solx)
125 if (
myrank==0 .and. spmat%timelog > 0) &
126 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: Additional Setup completed. time(sec)=',t2-t1
128 if ( phase_start == 1 )
then
133 call cluster_sparse_solver ( &
134 pt, maxfct, mnum, mtype, phase, nn, aval, irow, jcol, &
137 if (
myrank==0 .and. spmat%timelog > 0)
call print_iparm_parameters()
138 write(*,*)
'ERROR: MKL returned with error in phase 1', istat
143 if (
myrank==0 .and. spmat%timelog > 0) &
144 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: Analysis completed. time(sec)=',t3-t2
148 if ( phase_start .le. 2 )
then
152 call cluster_sparse_solver ( &
153 pt, maxfct, mnum, mtype, phase, nn, aval, irow, jcol, &
156 if (
myrank==0 .and. spmat%timelog > 0)
call print_iparm_parameters()
157 write(*,*)
'ERROR: MKL returned with error in phase 2', istat
161 if (
myrank==0 .and. spmat%timelog > 0) &
162 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: Factorization completed. time(sec)=',t4-t3
169 call cluster_sparse_solver ( &
170 pt, maxfct, mnum, mtype, phase, nn, aval, irow, jcol, &
173 if (
myrank==0 .and. spmat%timelog > 0)
call print_iparm_parameters()
174 write(*,*)
'ERROR: MKL returned with error in phase 3', istat
181 solution(i) = spmat%rhs(i)
189 if (
myrank==0 .and. spmat%timelog > 0)
then
190 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: Solution completed. time(sec)=',t5-t4
192 if( debug>0 .and.
myrank==0 )
call print_iparm_parameters()
195 stop
"MKL Pardiso not available"
199 #ifdef WITH_CLUSTERMKL
200 subroutine print_iparm_parameters()
201 write(*,
'(A60,I8)')
'Number of iterative refinement steps performed: ',iparm(7)
202 write(*,
'(A60,I8)')
'Number of perturbed pivots: ',iparm(14)
203 write(*,
'(A60,I8)')
'Peak memory on symbolic factorization: ',iparm(15)
204 write(*,
'(A60,I8)')
'Permanent memory on symbolic factorization: ',iparm(16)
205 write(*,
'(A60,I8)')
'Size of factors/Peak memory on num. fact. and sol: ',iparm(17)
206 write(*,
'(A60,I8)')
'The number of non-zero elements in the factors: ',iparm(18)
207 if( mtype < 11 )
then
208 write(*,
'(A60,I8)')
'Number of positive eigenvalues: ',iparm(22)
209 write(*,
'(A60,I8)')
'Number of negative eigenvalues: ',iparm(23)
213 subroutine export_spmat_to_centralizedcrs(spMAT,myrank,n,ia,ja,a,b,x)
214 type (sparse_matrix),
intent(in) :: spmat
215 integer(kind=kint),
intent(in) ::
myrank
216 integer(kind=kint),
intent(out) :: n
217 integer(kind=kint),
pointer,
intent(inout) :: ia(:), ja(:)
218 real(kind=
kreal),
pointer,
intent(inout) :: a(:), b(:), x(:)
220 integer(kind=kint) :: i,
nprocs, ierr, nnz
221 integer(kind=kint),
allocatable :: dispmat(:), ncounts(:)
222 real(kind=
kreal) :: t1,t2,t3,t4
235 dispmat(i+1)=dispmat(i)+ncounts(i)
236 nnz = nnz + ncounts(i)
238 nnz = nnz + ncounts(
nprocs)
242 if( .not.
associated(ia) )
allocate(ia(nnz+n), stat=ierr)
244 write(*,*)
" Allocation error in Setup Cluster MKL, ia",ierr,nnz
247 if( .not.
associated(ja) )
allocate(ja(nnz+n), stat=ierr)
249 write(*,*)
" Allocation error in Setup Cluster MKL, ja",ierr,nnz
252 if( .not.
associated(a) )
allocate(a(nnz+n), stat=ierr)
254 write(*,*)
" Allocation error in Setup Cluster MKL, a",ierr,nnz
257 if( .not.
associated(b) )
allocate(b(n), stat=ierr)
259 write(*,*)
" Allocation error in Setup Cluster MKL, b",ierr,n
262 if( .not.
associated(x) )
allocate(x(n), stat=ierr)
264 write(*,*)
" Allocation error in Setup Cluster MKL, x",ierr,n
268 allocate(ia(1),ja(1),a(1),b(1),x(1))
272 if (
myrank==0 .and. spmat%timelog > 0 .and. debug > 0 ) &
273 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: - Allocate Matrix time(sec)=',t2-t1
291 if (
myrank==0 .and. spmat%timelog > 0 .and. debug > 0 ) &
292 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: - Gather Matrix time(sec)=',t3-t2
296 call coo2csr(n, nnz, ia, ja, a)
297 if( debug>0 )
call check_csr(n, nnz, ia, ja, a)
301 if (
myrank==0 .and. spmat%timelog > 0 .and. debug > 0 ) &
302 write(*,
'(A,f10.3)')
' [Cluster Pardiso]: - Convert Matrix Format time(sec)=',t4-t3
304 deallocate(dispmat,ncounts)
307 subroutine coo2csr(n, nnz, ia, ja, a)
308 integer(kind=kint),
intent(in) :: n
309 integer(kind=kint),
intent(inout) :: nnz
310 integer(kind=kint),
pointer,
intent(inout) :: ia(:)
311 integer(kind=kint),
pointer,
intent(inout) :: ja(:)
312 real(kind=
kreal),
pointer,
intent(inout) :: a(:)
314 integer(kind=kint) :: i, k, idx, is, ie, nnz_new, prev
315 integer(kind=kint),
allocatable :: counter(:), counter_curr(:), ia0(:), ja0(:)
316 real(kind=
kreal),
allocatable :: a0(:)
318 allocate(counter(0:n),counter_curr(n),ia0(n+1),ja0(nnz),a0(nnz))
323 counter(idx) = counter(idx) + 1
327 ia0(i+1) = ia0(i)+counter(i)
333 counter_curr(idx) = counter_curr(idx) + 1
334 idx = ia0(idx)+counter_curr(idx)
344 call sort_column_ascending_order0(ie-is+1,ja0(is:ie),a0(is:ie))
351 ia(i+1) = ia(i)+counter(i)
358 do k=ia0(i)+1,ia0(i+1)
359 if( ja0(k) == prev )
then
360 a(nnz_new) = a(nnz_new) + a0(k)
362 nnz_new = nnz_new + 1
368 ia(i+1) = nnz_new + 1
374 deallocate(counter,counter_curr,ia0,ja0,a0)
378 subroutine check_csr(n, nnz, ia, ja, a)
379 integer(kind=kint),
intent(in) :: n
380 integer(kind=kint),
intent(in) :: nnz
381 integer(kind=kint),
pointer,
intent(in) :: ia(:)
382 integer(kind=kint),
pointer,
intent(in) :: ja(:)
383 real(kind=
kreal),
pointer,
intent(in) :: a(:)
387 if( ia(n+1)-1 /= nnz )
then
388 write(*,*)
"Error in check_csr(1): ia(n+1)-1 /= nnz"
394 if( ja(k) <= 0 )
then
395 write(*,*)
"Error in check_csr(2): ja(k) <= 0"
399 write(*,*)
"Error in check_csr(3): ja(k) > n"
403 if( ja(k) <= ja(k-1) )
then
404 write(*,*)
"Error in check_csr(4): ja(k) <= ja(k-1)"
413 subroutine sort_column_ascending_order(spMAT,myrank)
414 type (sparse_matrix),
intent(inout) :: spmat
415 integer(kind=kint),
intent(in) ::
myrank
417 integer(kind=kint) :: i, is, ie
420 if(spmat%IRN(i)-spmat%IRN(i-1)>10000) &
421 &
write(*,*)
'warning: n may be too large for set_mkl_set_prof0 for row ',i-1
428 ie = spmat%IRN(i+1)-1
429 call sort_column_ascending_order0(ie-is+1,spmat%JCN(is:ie),spmat%A(is:ie))
433 end subroutine sort_column_ascending_order
435 subroutine sort_column_ascending_order0(n,ja,a)
436 integer(kind=kint),
intent(in) :: n
437 integer(kind=kint),
intent(inout) :: ja(:)
438 real(kind=
kreal),
intent(inout) :: a(:)
440 integer(kind=kint) :: i, work(2,n)
441 real(kind=
kreal) :: oa(n)
456 end subroutine sort_column_ascending_order0
458 recursive subroutine myqsort(n,work)
459 integer(kind=kint),
intent(in) :: n
460 integer(kind=kint),
intent(inout) :: work(:,:)
462 integer(kind=kint) :: i, key, work1(2,n), n_low, n_high, next, minidx, maxidx
472 if( work(1,i) > next ) sorted = .false.
473 if( next < minidx ) minidx = next
474 if( next > maxidx ) maxidx = next
478 if( n<5 .or. maxidx-minidx < 2)
then
479 call myinssort(n,work)
483 key = (minidx+maxidx)/2
487 if(work(1,i)<key)
then
489 work1(1:2,n_low) = work(1:2,i)
495 if(work(1,i)>=key)
then
497 work1(1:2,n_low+n_high) = work(1:2,i)
501 if(n_low>0)
call myqsort(n_low,work1(1:2,1:n_low))
502 if(n_high>0)
call myqsort(n_high,work1(1:2,n_low+1:n_low+n_high))
505 work(1:2,i) = work1(1:2,i)
508 end subroutine myqsort
510 subroutine myinssort(n,work)
511 integer(kind=kint),
intent(in) :: n
512 integer(kind=kint),
intent(inout) :: work(:,:)
514 integer(kind=kint) :: i,j,tmp(2)
518 if(work(1,j)<work(1,j-1))
then
519 tmp(1:2) = work(1:2,j)
520 work(1:2,j) = work(1:2,j-1)
521 work(1:2,j-1) = tmp(1:2)
526 end subroutine myinssort