LCOV - code coverage report
Current view: top level - test/Fortran/elpa1/legacy_interface - legacy_toeplitz.F90 (source / functions) Hit Total Coverage
Test: coverage_50ab7a7628bba174fc62cee3ab72b26e81f87fe5.info Lines: 84 91 92.3 %
Date: 2018-01-10 09:29:53 Functions: 2 2 100.0 %

          Line data    Source code
       1             : !    This file is part of ELPA.
       2             : !
       3             : !    The ELPA library was originally created by the ELPA consortium,
       4             : !    consisting of the following organizations:
       5             : !
       6             : !    - Max Planck Computing and Data Facility (MPCDF), formerly known as
       7             : !      Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
       8             : !    - Bergische Universität Wuppertal, Lehrstuhl für angewandte
       9             : !      Informatik,
      10             : !    - Technische Universität München, Lehrstuhl für Informatik mit
      11             : !      Schwerpunkt Wissenschaftliches Rechnen ,
      12             : !    - Fritz-Haber-Institut, Berlin, Abt. Theorie,
      13             : !    - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
      14             : !      Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
      15             : !      and
      16             : !    - IBM Deutschland GmbH
      17             : !
      18             : !
      19             : !    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             : !    it under the terms of the version 3 of the license of the
      24             : !    GNU Lesser General Public License as published by the Free
      25             : !    Software Foundation.
      26             : !
      27             : !    ELPA is distributed in the hope that it will be useful,
      28             : !    but WITHOUT ANY WARRANTY; without even the implied warranty of
      29             : !    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      30             : !    GNU Lesser General Public License for more details.
      31             : !
      32             : !    You should have received a copy of the GNU Lesser General Public License
      33             : !    along with ELPA.  If not, see <http://www.gnu.org/licenses/>
      34             : !
      35             : !    ELPA reflects a substantial effort on the part of the original
      36             : !    ELPA consortium, and we ask you to respect the spirit of the
      37             : !    license that we chose: i.e., please contribute any changes you
      38             : !    may have back to the original ELPA library distribution, and keep
      39             : !    any derivatives of ELPA under the same license that we chose for
      40             : !    the original distribution, the GNU Lesser General Public License.
      41             : !
      42             : !
      43             : #include "config-f90.h"
      44             : !>
      45             : !> Fortran test programm to demonstrates the use of
      46             : !> the elpa_solve_tridi library function
      47             : !>
      48         192 : program test_solve_tridi
      49             : 
      50             : !
      51             : ! Copyright of the original code rests with the authors inside the ELPA
      52             : ! consortium. The copyright of any additional modifications shall rest
      53             : ! with their original authors, but shall adhere to the licensing terms
      54             : ! distributed along with the original code in the file "COPYING".
      55             : !
      56             : !-------------------------------------------------------------------------------
      57         192 :    use elpa1
      58             :    use test_util
      59             : 
      60             :    use test_read_input_parameters
      61             :    use test_check_correctness
      62             :    use test_setup_mpi
      63             :    use test_blacs_infrastructure
      64             :    use test_prepare_matrix
      65             : 
      66             : #ifdef HAVE_REDIRECT
      67             :    use test_redirect
      68             : #endif
      69             :   use test_output_type
      70             : 
      71             :    implicit none
      72             : 
      73             :    !-------------------------------------------------------------------------------
      74             :    ! Please set system size parameters below!
      75             :    ! na:   System size
      76             :    ! nev:  Number of eigenvectors to be calculated
      77             :    ! nblk: Blocking factor in block cyclic distribution
      78             :    !-------------------------------------------------------------------------------
      79             :    integer(kind=ik)           :: nblk
      80             :    integer(kind=ik)           :: na, nev
      81             : 
      82             :    integer(kind=ik)           :: np_rows, np_cols, na_rows, na_cols
      83             : 
      84             :    integer(kind=ik)           :: myid, nprocs, my_prow, my_pcol, mpi_comm_rows, mpi_comm_cols
      85             :    integer(kind=ik)           :: i, mpierr, my_blacs_ctxt, sc_desc(9), info, nprow, npcol
      86             : 
      87             :    integer, external          :: numroc
      88             : 
      89         384 :    real(kind=rk8), allocatable :: a(:,:), d(:), e(:), ev_analytic(:), ev(:)
      90             :    real(kind=rk8)              :: diagonalELement, subdiagonalElement
      91             : 
      92         192 :    real(kind=rk8), allocatable :: as(:,:)
      93             :    real(kind=rk8)              :: tmp
      94             :    integer(kind=ik)           :: loctmp ,rowLocal, colLocal
      95             : 
      96             : 
      97             :    real(kind=rk8)              :: maxerr
      98             : 
      99             :    logical                    :: wantDebug
     100             : 
     101             :    real(kind=rk8), parameter   :: pi = 3.141592653589793238462643383279_rk8
     102             : 
     103             :    integer(kind=ik)           :: STATUS
     104             : #ifdef WITH_OPENMP
     105             :    integer(kind=ik)           :: omp_get_max_threads,  required_mpi_thread_level, &
     106             :                                  provided_mpi_thread_level
     107             : #endif
     108             :    type(output_t)             :: write_to_file
     109             :    logical                    :: success
     110             :    character(len=8)           :: task_suffix
     111             :    integer(kind=ik)           :: j
     112             :    !-------------------------------------------------------------------------------
     113             : 
     114         192 :    success = .true.
     115             : 
     116         192 :    call read_input_parameters(na, nev, nblk, write_to_file)
     117             : 
     118             :    !-------------------------------------------------------------------------------
     119             :    !  MPI Initialization
     120         192 :    call setup_mpi(myid, nprocs)
     121             : 
     122         192 :    STATUS = 0
     123             : 
     124             : !#define DATATYPE REAL
     125             : !#define ELPA1
     126             : !#include "../../elpa_print_headers.F90"
     127             : 
     128         192 :    do np_cols = NINT(SQRT(REAL(nprocs))),2,-1
     129           0 :       if(mod(nprocs,np_cols) == 0 ) exit
     130             :    enddo
     131             : 
     132             :    ! at the end of the above loop, nprocs is always divisible by np_cols
     133             : 
     134         192 :    np_rows = nprocs/np_cols
     135             : 
     136         192 :    if(myid==0) then
     137         128 :       print *
     138         128 :       print '(a)','Test program for elpa_solve_tridi with a Toeplitz matrix'
     139         128 :       print *
     140         128 :       print '(3(a,i0))','Matrix size=',na,', Number of eigenvectors=',nev,', Block size=',nblk
     141         128 :       print '(3(a,i0))','Number of processor rows=',np_rows,', cols=',np_cols,', total=',nprocs
     142         128 :       print *
     143             :    endif
     144             : 
     145             :    !-------------------------------------------------------------------------------
     146             :    ! Set up BLACS context and MPI communicators
     147             :    !
     148             :    ! The BLACS context is only necessary for using Scalapack.
     149             :    !
     150             :    ! For ELPA, the MPI communicators along rows/cols are sufficient,
     151             :    ! and the grid setup may be done in an arbitrary way as long as it is
     152             :    ! consistent (i.e. 0<=my_prow<np_rows, 0<=my_pcol<np_cols and every
     153             :    ! process has a unique (my_prow,my_pcol) pair).
     154             : 
     155             :    call set_up_blacsgrid(mpi_comm_world, np_rows, np_cols, 'C', &
     156         192 :                          my_blacs_ctxt, my_prow, my_pcol)
     157             : 
     158         192 :    if (myid==0) then
     159         128 :      print '(a)','| Past BLACS_Gridinfo.'
     160             :    end if
     161             : 
     162             :    ! All ELPA routines need MPI communicators for communicating within
     163             :    ! rows or columns of processes, these are set in elpa_get_communicators.
     164             : 
     165             :    mpierr = elpa_get_communicators(mpi_comm_world, my_prow, my_pcol, &
     166         192 :                                    mpi_comm_rows, mpi_comm_cols)
     167             : 
     168         192 :    if (myid==0) then
     169         128 :      print '(a)','| Past split communicator setup for rows and columns.'
     170             :    end if
     171             : 
     172             :    call set_up_blacs_descriptor(na ,nblk, my_prow, my_pcol, np_rows, np_cols, &
     173         192 :                                 na_rows, na_cols, sc_desc, my_blacs_ctxt, info)
     174             : 
     175         192 :    if (myid==0) then
     176         128 :      print '(a)','| Past scalapack descriptor setup.'
     177             :    end if
     178             : 
     179             :    !-------------------------------------------------------------------------------
     180             :    ! Allocate matrices and set up a test toeplitz matrix for solve_tridi
     181             : 
     182         192 :    allocate(a (na_rows,na_cols))
     183         192 :    allocate(as(na_rows,na_cols))
     184             : 
     185         192 :    allocate(d (na))
     186         192 :    allocate(e (na))
     187         192 :    allocate(ev_analytic(na))
     188         192 :    allocate(ev(na))
     189             : 
     190         192 :    a(:,:) = 0.0_rk8
     191             : 
     192             : 
     193             :    ! changeable numbers here would be nice
     194         192 :    diagonalElement = 0.45_rk8
     195         192 :    subdiagonalElement =  0.78_rk8
     196             : 
     197         192 :    d(:) = diagonalElement
     198         192 :    e(:) = subdiagonalElement
     199             : 
     200             : 
     201             :    ! set up the diagonal and subdiagonals (for general solver test)
     202       28992 :    do i=1, na ! for diagonal elements
     203       28800 :      if (map_global_array_index_to_local_index(i, i, rowLocal, colLocal, nblk, np_rows, np_cols, my_prow, my_pcol)) then
     204       19200 :        a(rowLocal,colLocal) = diagonalElement
     205             :      endif
     206             :    enddo
     207             : 
     208       28800 :    do i=1, na-1
     209       28608 :      if (map_global_array_index_to_local_index(i, i+1, rowLocal, colLocal, nblk, np_rows, np_cols, my_prow, my_pcol)) then
     210       19072 :        a(rowLocal,colLocal) = subdiagonalElement
     211             :      endif
     212             :    enddo
     213             : 
     214       28800 :    do i=2, na
     215       28608 :      if (map_global_array_index_to_local_index(i, i-1, rowLocal, colLocal, nblk, np_rows, np_cols, my_prow, my_pcol)) then
     216       19072 :        a(rowLocal,colLocal) = subdiagonalElement
     217             :      endif
     218             :    enddo
     219             : 
     220         192 :    as = a
     221             : 
     222             : 
     223             : 
     224             :    !-------------------------------------------------------------------------------
     225             :    ! Calculate eigenvalues/eigenvectors
     226             : 
     227         192 :    if (myid==0) then
     228         128 :      print '(a)','| Entering elpa_solve_tridi ... '
     229         128 :      print *
     230             :    end if
     231             : 
     232             : #ifdef WITH_MPI
     233         128 :    call mpi_barrier(mpi_comm_world, mpierr) ! for correct timings only
     234             : #endif
     235             : 
     236             :    success = elpa_solve_tridi_double(na, nev, d, e, a, na_rows, nblk, na_cols, mpi_comm_rows, &
     237         192 :                               mpi_comm_cols, wantDebug)
     238             : 
     239         192 :    if (.not.(success)) then
     240           0 :       write(error_unit,*) "elpa_solve_tridi produced an error! Aborting..."
     241             : #ifdef WITH_MPI
     242           0 :       call MPI_ABORT(mpi_comm_world, 1, mpierr)
     243             : #else
     244           0 :       call exit(1)
     245             : #endif
     246             :    endif
     247             : 
     248         192 :    if (myid==0) then
     249         128 :      print '(a)','| elpa_solve_tridi complete.'
     250         128 :      print *
     251             :    end if
     252             : 
     253             : 
     254         192 :    ev = d
     255             : 
     256             : !
     257             : !   if(myid == 0) print *,'Time tridiag_real     :',time_evp_fwd
     258             : !   if(myid == 0) print *,'Time solve_tridi      :',time_evp_solve
     259             : !   if(myid == 0) print *,'Time trans_ev_real    :',time_evp_back
     260             : !   if(myid == 0) print *,'Total time (sum above):',time_evp_back+time_evp_solve+time_evp_fwd
     261             : !
     262             : !   if(write_to_file%eigenvectors) then
     263             : !     write(unit = task_suffix, fmt = '(i8.8)') myid
     264             : !     open(17,file="EVs_real_out_task_"//task_suffix(1:8)//".txt",form='formatted',status='new')
     265             : !     write(17,*) "Part of eigenvectors: na_rows=",na_rows,"of na=",na," na_cols=",na_cols," of na=",na
     266             : !
     267             : !     do i=1,na_rows
     268             : !       do j=1,na_cols
     269             : !         write(17,*) "row=",i," col=",j," element of eigenvector=",z(i,j)
     270             : !       enddo
     271             : !     enddo
     272             : !     close(17)
     273             : !   endif
     274             : !
     275             : !   if(write_to_file%eigenvalues) then
     276             : !      if (myid == 0) then
     277             : !         open(17,file="Eigenvalues_real_out.txt",form='formatted',status='new')
     278             : !         do i=1,na
     279             : !            write(17,*) i,ev(i)
     280             : !         enddo
     281             : !         close(17)
     282             : !      endif
     283             : !   endif
     284             : !
     285             : !
     286             :    !-------------------------------------------------------------------------------
     287             : 
     288             :    ! analytic solution
     289       28992 :    do i=1, na
     290       28800 :      ev_analytic(i) = diagonalElement + 2.0_rk8 * subdiagonalElement *cos( pi*real(i,kind=rk8)/ real(na+1,kind=rk8) )
     291             :    enddo
     292             : 
     293             :    ! sort analytic solution:
     294             : 
     295             :    ! this hack is neihter elegant, nor optimized: for huge matrixes it might be expensive
     296             :    ! a proper sorting algorithmus might be implemented here
     297             : 
     298         192 :    tmp    = minval(ev_analytic)
     299         192 :    loctmp = minloc(ev_analytic, 1)
     300             : 
     301         192 :    ev_analytic(loctmp) = ev_analytic(1)
     302         192 :    ev_analytic(1) = tmp
     303             : 
     304       28800 :    do i=2, na
     305       28608 :      tmp = ev_analytic(i)
     306     2174208 :      do j= i, na
     307     2145600 :        if (ev_analytic(j) .lt. tmp) then
     308     1051392 :          tmp    = ev_analytic(j)
     309     1051392 :          loctmp = j
     310             :        endif
     311             :      enddo
     312       28608 :      ev_analytic(loctmp) = ev_analytic(i)
     313       28608 :      ev_analytic(i) = tmp
     314             :    enddo
     315             : 
     316             :    ! compute a simple error max of eigenvalues
     317         192 :    maxerr = 0.0_rk8
     318         192 :    maxerr = maxval( (d(:) - ev_analytic(:))/ev_analytic(:) , 1)
     319             : 
     320         192 :    if (maxerr .gt. 8.e-13) then
     321           0 :      if (myid .eq. 0) then
     322           0 :        print *,"Eigenvalues differ from analytic solution: maxerr = ",maxerr
     323             :      endif
     324             : 
     325           0 :    status = 1
     326             : 
     327             :    endif
     328             : 
     329             :    ! Test correctness of result (using plain scalapack routines)
     330         192 :    status = check_correctness_evp_numeric_residuals(na, nev, as, a, ev, sc_desc, nblk, myid, np_rows, np_cols, my_prow, my_pcol)
     331             : 
     332         192 :    deallocate(a)
     333             : 
     334         192 :    deallocate(as)
     335         192 :    deallocate(d)
     336             : 
     337         192 :    deallocate(e)
     338         192 :    deallocate(ev)
     339         192 :    deallocate(ev_analytic)
     340             : 
     341             : #ifdef WITH_MPI
     342         128 :    call blacs_gridexit(my_blacs_ctxt)
     343         128 :    call mpi_finalize(mpierr)
     344             : #endif
     345             : 
     346         192 :    call EXIT(STATUS)
     347             : 
     348             : 
     349             : end
     350             : 
     351             : !-------------------------------------------------------------------------------

Generated by: LCOV version 1.12