legacy_complex.F90 10.2 KB
Newer Older
1
2
!    This file is part of ELPA.
!
3
!    The ELPA library was originally created by the ELPA consortium,
4
5
!    consisting of the following organizations:
!
6
7
!    - Max Planck Computing and Data Facility (MPCDF), formerly known as
!      Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
8
9
10
!    - Bergische Universität Wuppertal, Lehrstuhl für angewandte
!      Informatik,
!    - Technische Universität München, Lehrstuhl für Informatik mit
11
12
!      Schwerpunkt Wissenschaftliches Rechnen ,
!    - Fritz-Haber-Institut, Berlin, Abt. Theorie,
13
!    - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
14
15
!      Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
!      and
16
17
18
19
!    - IBM Deutschland GmbH
!
!
!    More information can be found here:
20
!    http://elpa.mpcdf.mpg.de/
21
22
!
!    ELPA is free software: you can redistribute it and/or modify
23
24
!    it under the terms of the version 3 of the license of the
!    GNU Lesser General Public License as published by the Free
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
!    Software Foundation.
!
!    ELPA is distributed in the hope that it will be useful,
!    but WITHOUT ANY WARRANTY; without even the implied warranty of
!    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!    GNU Lesser General Public License for more details.
!
!    You should have received a copy of the GNU Lesser General Public License
!    along with ELPA.  If not, see <http://www.gnu.org/licenses/>
!
!    ELPA reflects a substantial effort on the part of the original
!    ELPA consortium, and we ask you to respect the spirit of the
!    license that we chose: i.e., please contribute any changes you
!    may have back to the original ELPA library distribution, and keep
!    any derivatives of ELPA under the same license that we chose for
!    the original distribution, the GNU Lesser General Public License.
!
!
#include "config-f90.h"
44
45
46
47
48
49
50
51
52
53
54
55
!>
!> Fortran test programm to demonstrates the use of
!> ELPA 1 complex case library.
!> If "HAVE_REDIRECT" was defined at build time
!> the stdout and stderr output of each MPI task
!> can be redirected to files if the environment
!> variable "REDIRECT_ELPA_TEST_OUTPUT" is set
!> to "true".
!>
!> By calling executable [arg1] [arg2] [arg3] [arg4]
!> one can define the size (arg1), the number of
!> Eigenvectors to compute (arg2), and the blocking (arg3).
56
!> If these values are not set default values (500, 150, 16)
57
58
59
60
61
!> are choosen.
!> If these values are set the 4th argument can be
!> "output", which specifies that the EV's are written to
!> an ascii file.
!>
62
program test_complex_double_precision
63
64
65
66
67
68

!-------------------------------------------------------------------------------
! Standard eigenvalue problem - COMPLEX version
!
! This program demonstrates the use of the ELPA module
! together with standard scalapack routines
69
!
70
71
72
73
74
! Copyright of the original code rests with the authors inside the ELPA
! consortium. The copyright of any additional modifications shall rest
! with their original authors, but shall adhere to the licensing terms
! distributed along with the original code in the file "COPYING".
!-------------------------------------------------------------------------------
75
   use elpa1
76
   use elpa_utilities, only : error_unit
77

78
79
80
81
82
83
   use test_util
   use test_read_input_parameters
   use test_check_correctness
   use test_setup_mpi
   use test_blacs_infrastructure
   use test_prepare_matrix
84
#ifdef HAVE_REDIRECT
85
   use test_redirect
86
#endif
87

88
   use test_output_type
89
90
91
92
93
94
95
96
97
   implicit none

   !-------------------------------------------------------------------------------
   ! Please set system size parameters below!
   ! na:   System size
   ! nev:  Number of eigenvectors to be calculated
   ! nblk: Blocking factor in block cyclic distribution
   !-------------------------------------------------------------------------------

98
99
   integer(kind=ik)              :: nblk
   integer(kind=ik)              :: na, nev
100

101
   integer(kind=ik)              :: np_rows, np_cols, na_rows, na_cols
102

103
104
   integer(kind=ik)              :: myid, nprocs, my_prow, my_pcol, mpi_comm_rows, mpi_comm_cols
   integer(kind=ik)              :: i, mpierr, my_blacs_ctxt, sc_desc(9), info, nprow, npcol
105

106
   real(kind=rk8), allocatable    :: ev(:)
Andreas Marek's avatar
Andreas Marek committed
107

108
   complex(kind=ck8), allocatable :: a(:,:), z(:,:), as(:,:)
109

110
   complex(kind=ck8), parameter   :: CZERO = (0._rk8,0.0_rk8), CONE = (1._rk8,0._rk8)
111

112
   integer(kind=ik)              :: STATUS
113
#ifdef WITH_OPENMP
114
   integer(kind=ik)              :: omp_get_max_threads,  required_mpi_thread_level, provided_mpi_thread_level
115
#endif
116
   type(output_t)                :: write_to_file
117
   logical                       :: success
118
119
   character(len=8)              :: task_suffix
   integer(kind=ik)              :: j
120

121
122
#define DOUBLE_PRECISION_COMPLEX 1

123
   success = .true.
Andreas Marek's avatar
Andreas Marek committed
124
125
   ! read input parameters if they are provided
   call read_input_parameters(na, nev, nblk, write_to_file)
126
127
128

   !-------------------------------------------------------------------------------
   !  MPI Initialization
Andreas Marek's avatar
Andreas Marek committed
129
   call setup_mpi(myid, nprocs)
130

131
   STATUS = 0
132

Andreas Marek's avatar
Andreas Marek committed
133
#define COMPLEXCASE
134
#define ELPA1
135
#include "../../elpa_print_headers.F90"
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

   !-------------------------------------------------------------------------------
   ! Selection of number of processor rows/columns
   ! We try to set up the grid square-like, i.e. start the search for possible
   ! divisors of nprocs with a number next to the square root of nprocs
   ! and decrement it until a divisor is found.

   do np_cols = NINT(SQRT(REAL(nprocs))),2,-1
      if(mod(nprocs,np_cols) == 0 ) exit
   enddo
   ! at the end of the above loop, nprocs is always divisible by np_cols

   np_rows = nprocs/np_cols

   if(myid==0) then
      print *
Pavel Kus's avatar
Pavel Kus committed
152
153
154
155
156
157
158
159
160
161
      print '(a)','Standard eigenvalue problem - ELPA1, COMPLEX version'
      print *
      print '((a,i0))', 'Matrix size: ', na 
      print '((a,i0))', 'Num eigenvectors: ', nev
      print '((a,i0))', 'Blocksize: ', nblk 
      print '((a,i0))', 'Num MPI proc: ', nprocs 
      print '((a))', 'Using gpu: NO'
      print '((a,i0))', 'Num gpu devices: ', 0
      print '((a))', 'Number type: complex'
      print '((a))', 'Number precision: double'
162
163
164
165
166
      print *
      print '(3(a,i0))','Number of processor rows=',np_rows,', cols=',np_cols,', total=',nprocs
      print *
   endif

Pavel Kus's avatar
Pavel Kus committed
167
  !-------------------------------------------------------------------------------
168
169
170
171
172
173
174
175
176
   ! Set up BLACS context and MPI communicators
   !
   ! The BLACS context is only necessary for using Scalapack.
   !
   ! For ELPA, the MPI communicators along rows/cols are sufficient,
   ! and the grid setup may be done in an arbitrary way as long as it is
   ! consistent (i.e. 0<=my_prow<np_rows, 0<=my_pcol<np_cols and every
   ! process has a unique (my_prow,my_pcol) pair).

177
178
   call set_up_blacsgrid(mpi_comm_world, np_rows, np_cols, 'C', &
                         my_blacs_ctxt, my_prow, my_pcol)
179
180
181
182
183
184

   if (myid==0) then
     print '(a)','| Past BLACS_Gridinfo.'
   end if

   ! All ELPA routines need MPI communicators for communicating within
185
   ! rows or columns of processes, these are set in elpa_get_communicators.
186

187
   mpierr = elpa_get_communicators(mpi_comm_world, my_prow, my_pcol, &
188
                                   mpi_comm_rows, mpi_comm_cols)
189
190
191
192
193
194
195
196

   if (myid==0) then
     print '(a)','| Past split communicator setup for rows and columns.'
   end if

   ! Determine the necessary size of the distributed matrices,
   ! we use the Scalapack tools routine NUMROC for that.

Andreas Marek's avatar
Andreas Marek committed
197
198
   call set_up_blacs_descriptor(na ,nblk, my_prow, my_pcol, np_rows, np_cols, &
                                na_rows, na_cols, sc_desc, my_blacs_ctxt, info)
199
200
201
202
203
204
205
206
207
208
209
210
211
212

   if (myid==0) then
     print '(a)','| Past scalapack descriptor setup.'
   end if

   !-------------------------------------------------------------------------------
   ! Allocate matrices and set up a test matrix for the eigenvalue problem

   allocate(a (na_rows,na_cols))
   allocate(z (na_rows,na_cols))
   allocate(as(na_rows,na_cols))

   allocate(ev(na))

213
   call prepare_matrix_random(na, myid, sc_desc, a, z, as)
214
   elpa_print_times = .true.
215
216
217
218
219
220
221
   !-------------------------------------------------------------------------------
   ! Calculate eigenvalues/eigenvectors

   if (myid==0) then
     print '(a)','| Entering one-step ELPA solver ... '
     print *
   end if
222
#ifdef WITH_MPI
223
   call mpi_barrier(mpi_comm_world, mpierr) ! for correct timings only
224
#endif
225
   success = elpa_solve_evp_complex_1stage_double(na, nev, a, na_rows, ev, z, na_rows, nblk, &
226
                               na_cols, mpi_comm_rows, mpi_comm_cols, mpi_comm_world)
227

228
229
   if (.not.(success)) then
      write(error_unit,*) "solve_evp_complex produced an error! Aborting..."
230
#ifdef WITH_MPI
Andreas Marek's avatar
Andreas Marek committed
231
      call MPI_ABORT(mpi_comm_world, 1, mpierr)
232
233
#else
      call exit(1)
234
#endif
235
236
   endif

237
238
239
240
241
242
243
244
245
246
   if (myid==0) then
     print '(a)','| One-step ELPA solver complete.'
     print *
   end if

   if(myid == 0) print *,'Time tridiag_complex  :',time_evp_fwd
   if(myid == 0) print *,'Time solve_tridi      :',time_evp_solve
   if(myid == 0) print *,'Time trans_ev_complex :',time_evp_back
   if(myid == 0) print *,'Total time (sum above):',time_evp_back+time_evp_solve+time_evp_fwd

247
   if(write_to_file%eigenvectors) then
248
249
250
251
252
253
254
255
256
257
     write(unit = task_suffix, fmt = '(i8.8)') myid
     open(17,file="EVs_complex_out_task_"//task_suffix(1:8)//".txt",form='formatted',status='new')
     write(17,*) "Part of eigenvectors: na_rows=",na_rows,"of na=",na," na_cols=",na_cols," of na=",na

     do i=1,na_rows
       do j=1,na_cols
         write(17,*) "row=",i," col=",j," element of eigenvector=",z(i,j)
       enddo
     enddo
     close(17)
258
   endif
259
260
261
262
263
264
265
266
267
268
269
270

   if(write_to_file%eigenvalues) then
      if (myid == 0) then
         open(17,file="Eigenvalues_complex_out.txt",form='formatted',status='new')
         do i=1,na
            write(17,*) i,ev(i)
         enddo
         close(17)
      endif
   endif


271
272
273
   !-------------------------------------------------------------------------------
   ! Test correctness of result (using plain scalapack routines)

274
   status = check_correctness_evp_numeric_residuals(na, nev, as, z, ev, sc_desc, nblk, myid, np_rows, np_cols, my_prow, my_pcol)
275

Andreas Marek's avatar
Andreas Marek committed
276
277
   deallocate(a)
   deallocate(as)
278
279
280

   deallocate(z)
   deallocate(ev)
281

282
#ifdef WITH_MPI
283
284
   call blacs_gridexit(my_blacs_ctxt)
   call mpi_finalize(mpierr)
285
#endif
286
287
288
289
   call EXIT(STATUS)
end

!-------------------------------------------------------------------------------