LCOV - code coverage report
Current view: top level - main - fleur_job.F90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 92 161 57.1 %
Date: 2024-04-19 04:21:58 Functions: 8 11 72.7 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------
       2             : ! Copyright (c) 2016 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
       3             : ! This file is part of FLEUR and available as free software under the conditions
       4             : ! of the MIT license as expressed in the LICENSE file in more detail.
       5             : !--------------------------------------------------------------------------------
       6             : MODULE m_fleur_jobs
       7             : #ifdef CPP_MPI
       8             :     use mpi
       9             : #endif
      10             :     USE m_juDFT
      11             :     IMPLICIT NONE
      12             :     PRIVATE
      13             :     CHARACTER(LEN=30),PARAMETER:: NOT_A_JOBFILE=".__NOT__A__JOBFILE__"
      14             : 
      15             :     TYPE t_job
      16             :         INTEGER           :: PE_requested
      17             :         INTEGER           :: mpi_comm
      18             :         CHARACTER(LEN=20) :: directory
      19             :     END TYPE
      20             : 
      21             :     PUBLIC:: t_job,fleur_job_arguments,fleur_job_init,fleur_job_distribute,fleur_job_execute
      22             : 
      23             : CONTAINS
      24         160 :     SUBROUTINE fleur_job_single(jobs)
      25             :         TYPE(t_job),ALLOCATABLE,INTENT(OUT)::jobs(:)
      26             : 
      27         160 :         ALLOCATE(jobs(1))
      28         160 :         jobs(1)%PE_requested=0
      29         160 :         jobs(1)%directory="."
      30         160 :     END SUBROUTINE
      31             : 
      32           0 :     SUBROUTINE read_jobfile(jobs,file)
      33             :         TYPE(t_job),ALLOCATABLE,INTENT(OUT)::jobs(:)
      34             :         CHARACTER(LEN=*)::file
      35             : 
      36             :         LOGICAL:: l_file
      37             :         INTEGER:: njobs,i
      38           0 :         INQUIRE(FILE=file,EXIST=l_file)
      39           0 :         IF (l_file) THEN
      40           0 :             OPEN(99,FILE=file,STATUS="old")
      41             :         ELSE
      42           0 :             WRITE(*,*) "job input file not found"
      43           0 :             WRITE(*,*) "You specified an invalid filename:",file
      44           0 :             STOP "JOB FILE MISSING"
      45             :         ENDIF
      46             :         !Count the number of lines in job-file
      47           0 :         njobs=0
      48             :         DO
      49           0 :             READ(99,*,END=100)
      50           0 :             njobs=njobs+1
      51             :         ENDDO
      52           0 : 100     REWIND(99)
      53           0 :         ALLOCATE(jobs(njobs))
      54           0 :         DO i=1,njobs
      55           0 :             READ(99,*) jobs(i)%PE_REQUESTED,jobs(i)%directory
      56             :         ENDDO
      57           0 :         CLOSE(99)
      58           0 :     END SUBROUTINE
      59             : 
      60           0 :     SUBROUTINE jobs_fromcommandline(jobs,no_jobs)
      61             :         TYPE(t_job),ALLOCATABLE,INTENT(INOUT)::jobs(:)
      62             :         INTEGER,INTENT(INOUT):: no_jobs
      63             : 
      64           0 :         TYPE(t_job),ALLOCATABLE ::jobs_tmp(:)
      65             :         INTEGER:: i
      66             :         CHARACTER(LEN=30)::str
      67             : 
      68           0 :         IF(ALLOCATED(jobs)) THEN
      69           0 :             no_jobs=size(jobs)+no_jobs
      70           0 :             ALLOCATE(jobs_tmp(size(jobs)))
      71           0 :             jobs_tmp=jobs
      72           0 :             DEALLOCATE(jobs)
      73           0 :             ALLOCATE(jobs(no_jobs))
      74           0 :             jobs(:size(jobs_tmp))=jobs_tmp
      75           0 :             no_jobs=size(jobs_tmp)+1
      76           0 :             DEALLOCATE(jobs_tmp)
      77             :         ELSE
      78           0 :             ALLOCATE(jobs(no_jobs))
      79           0 :             no_jobs=1
      80             :         ENDIF
      81             : 
      82           0 :         DO i=1,command_argument_count()
      83           0 :             CALL get_command_argument(i,str)
      84           0 :             IF(adjustl(str)=="-j") THEN
      85           0 :                 CALL get_command_argument(i+1,str)
      86           0 :                 IF (index(str,":")>1) THEN
      87           0 :                     READ(str(:index(str,":")-1),*) jobs(no_jobs)%PE_requested
      88           0 :                     jobs(no_jobs)%directory=str(index(str,":")+1:)
      89           0 :                     no_jobs=no_jobs+1
      90             :                 ELSE
      91           0 :                     PRINT *,"Illegal job-description"
      92           0 :                     PRINT *,"You specified:",str
      93           0 :                     STOP "ILLEGAL DESCRIPTION"
      94             :                 ENDIF
      95             :             ENDIF
      96             :         ENDDO
      97           0 :     END SUBROUTINE
      98             : 
      99         160 :     SUBROUTINE jobs_on_commandine(jobfile,no_jobs)
     100             :         INTEGER,INTENT(OUT)::no_jobs
     101             :         CHARACTER(LEN=*)::jobfile
     102             : 
     103             :         INTEGER i
     104             :         CHARACTER(LEN=30)::str
     105         160 :         jobfile=NOT_A_JOBFILE
     106         160 :         no_jobs=0
     107         320 :         DO i=1,command_argument_count()
     108         160 :             CALL get_command_argument(i,str)
     109         160 :             IF(adjustl(str)=="-j") THEN
     110           0 :                 no_jobs=no_jobs+1
     111             :             ENDIF
     112         320 :             IF (adjustl(str)=="-f") THEN
     113           0 :                 CALL get_command_argument(i+1,jobfile)
     114             :             ENDIF
     115             :         ENDDO
     116         160 :     END SUBROUTINE
     117             : 
     118         160 :     SUBROUTINE fleur_job_arguments(jobs)
     119             :         TYPE(t_job),ALLOCATABLE,INTENT(OUT)::jobs(:)
     120             : 
     121             :         CHARACTER(LEN=30):: file
     122             :         INTEGER          :: no_jobs_commandline
     123             : 
     124         160 :         CALL jobs_on_commandine(file,no_jobs_commandline)
     125         160 :         IF (file.NE.NOT_A_JOBFILE)  &
     126           0 :             CALL read_jobfile(jobs,file)
     127         160 :         IF (no_jobs_commandline>0) &
     128           0 :             CALL jobs_fromcommandline(jobs,no_jobs_commandline)
     129         160 :         IF (.NOT.allocated(jobs)) &
     130             :             CALL fleur_job_single(jobs)
     131         160 :     END SUBROUTINE
     132             : 
     133         160 :     SUBROUTINE fleur_job_init(l_mpi_multithreaded)
     134             :       USE m_fleur_help
     135             :       use m_fleur_version
     136             :       use m_fleur_dropxmlschema
     137             :       use m_judft
     138             :       USE m_constants
     139             :         logical, intent(out) :: l_mpi_multithreaded
     140             :         INTEGER :: irank=0
     141             : #ifdef CPP_MPI
     142             :         INTEGER ierr, i
     143         160 :         CALL MPI_INIT_THREAD(MPI_THREAD_MULTIPLE,i,ierr)
     144         160 :         if(ierr /= 0) call judft_error("MPI init failed.")
     145             : #endif
     146         160 :         l_mpi_multithreaded = .FALSE.
     147         160 :         CALL judft_init(oUnit,.FALSE.)
     148             : #ifdef CPP_MPI
     149         160 :         CALL MPI_COMM_RANK(MPI_COMM_WORLD,irank,ierr)
     150           0 :         select case (i)
     151             :             case (MPI_THREAD_SINGLE)
     152           0 :                 l_mpi_multithreaded = .False.
     153           0 :                 call judft_error("Fleur does not support: 'MPI_THREAD_SINGLE'. The minimum is 'MPI_THREAD_FUNNELED'")
     154             :             case (MPI_THREAD_FUNNELED )
     155           0 :                 l_mpi_multithreaded = .False.
     156             :             case (MPI_THREAD_SERIALIZED)
     157           0 :                 l_mpi_multithreaded = .False.
     158             :             case (MPI_THREAD_MULTIPLE)
     159         160 :                 l_mpi_multithreaded = .True.
     160             :             case default 
     161         160 :                 call judft_error("Can't identify MPI_Thread lvl")
     162             :         end select 
     163             : 
     164         160 :         if(judft_was_argument("-disable_progress_thread")) then 
     165           0 :             l_mpi_multithreaded = .False.
     166             :         endif
     167             :         
     168         160 :         IF(irank.EQ.0) THEN
     169          80 :            if(.not. l_mpi_multithreaded) then 
     170           0 :             write (*,*) "MPI_THREAD_MULTIPLE is not avalible. This might lead to performance problems"
     171             :            endif
     172             : 
     173          80 :            !$    IF (i<MPI_THREAD_FUNNELED) THEN
     174           0 :            !$       WRITE(*,*) ""
     175           0 :            !$       WRITE(*,*) "Linked MPI version does not support multithreading."
     176           0 :            !$       WRITE(*,*) ""
     177           0 :            !$       WRITE(*,*) "To solve this problem please do one of:"
     178           0 :            !$       WRITE(*,*) "   1. Link an adequate MPI version."
     179           0 :            !$       WRITE(*,*) "   2. Use fleur without MPI."
     180           0 :            !$       WRITE(*,*) "   3. Compile and use fleur without OpenMP."
     181           0 :            !$       WRITE(*,*) ""
     182           0 :            !$       CALL juDFT_error("MPI not usable with OpenMP")
     183             :            !$    END IF
     184             :         END IF
     185             : #endif
     186         160 :         IF (irank==0) THEN
     187          80 :            CALL fleur_help()
     188          80 :            call fleur_version()
     189          80 :            call fleur_dropxmlschema()
     190             :         END IF
     191         160 :     END SUBROUTINE
     192             : 
     193         160 :     SUBROUTINE fleur_job_execute(jobs, l_mpi_multithreaded)
     194             :         USE m_fleur
     195             :         USE m_types
     196             :         USE m_fleur_init
     197             : 
     198             :         TYPE(t_job),INTENT(IN) ::jobs(:)
     199             :         logical, intent(in)    :: l_mpi_multithreaded
     200             : 
     201             :         !local variables for FLEUR
     202       10080 :         type(t_fleurinput) :: fi
     203         160 :         TYPE(t_mpi)      :: fmpi
     204         160 :         TYPE(t_sphhar)   :: sphhar
     205         640 :         TYPE(t_stars)    :: stars
     206         160 :         TYPE(t_enpara)   :: enpara
     207         160 :         TYPE(t_results)  :: results
     208         640 :         TYPE(t_nococonv) :: nococonv
     209        2720 :         type(t_wann)     :: wann
     210         160 :         TYPE(t_hybdat)   :: hybdat
     211         160 :         type(t_mpdata)   :: mpdata
     212         160 :         CLASS(t_forcetheo),ALLOCATABLE::forcetheo
     213         160 :         class(t_xcpot), allocatable :: xcpot
     214             : 
     215             :         !local variables for jobcontrol
     216             :         INTEGER:: njob=1
     217             :         INTEGER:: irank=0
     218             : 
     219             :         CHARACTER(len=100) :: filename_add
     220             : 
     221             : #ifdef CPP_MPI
     222             :         INTEGER:: ierr
     223         160 :         CALL MPI_COMM_RANK(MPI_COMM_WORLD,irank,ierr)
     224             : 
     225             :         !find the number of the job for this PE
     226         160 :         DO njob=1,size(jobs)
     227         160 :             IF (jobs(njob)%mpi_comm==MPI_UNDEFINED) CYCLE
     228         160 :             CALL MPI_COMM_RANK(jobs(njob)%mpi_comm,irank,ierr)
     229         160 :             IF (irank.NE.MPI_UNDEFINED) EXIT
     230             :         ENDDO
     231             : #endif
     232         160 :         if (njob>size(jobs)) THEN
     233           0 :             print *, "GLOBAL-PE:",irank," does nothing"
     234             :             return
     235             :         endif
     236             :         !change directory
     237         160 :         CALL chdir(jobs(njob)%directory)
     238             :         !Call FLEUR
     239         160 :         fmpi%l_mpi_multithreaded = l_mpi_multithreaded
     240         160 :         fmpi%mpi_comm = jobs(njob)%mpi_comm
     241             : 
     242         160 :         call log_start()
     243             : 
     244         160 :         CALL timestart("Initialization")
     245         160 :         filename_add = ""
     246         160 :         IF (judft_was_argument("-add_name")) filename_add = TRIM(judft_string_for_argument("-add_name"))//"_"//""
     247             :         call fleur_init(fmpi,fi,sphhar,stars,nococonv,forcetheo,enpara,xcpot,results,wann, hybdat, mpdata, filename_add)
     248         160 :         CALL timestop("Initialization")
     249             : 
     250             :         CALL fleur_execute(fmpi,fi,sphhar,stars,nococonv,forcetheo,enpara,results,&
     251         160 :                            xcpot, wann, hybdat, mpdata)
     252             : 
     253           0 :     END SUBROUTINE
     254             : 
     255         160 :     SUBROUTINE fleur_job_distribute(jobs)
     256             :         use m_types_mpi
     257             :         TYPE(t_job),INTENT(INOUT)::jobs(:)
     258             : #ifdef CPP_MPI
     259             :         INTEGER:: i,free_pe,isize,irank,min_pe,new_comm,ierr
     260             : 
     261         160 :         CALL MPI_COMM_RANK(MPI_COMM_WORLD,irank,ierr)
     262         160 :         CALL MPI_COMM_SIZE(MPI_COMM_WORLD,isize,ierr)
     263             : 
     264             :         !if (irank==0) print *,"Running on ",isize," PE"
     265             :         !First determine if there are PE that should be distributed automatically
     266         160 :         IF (any(jobs%pe_requested==0)) THEN
     267         320 :             i=count(jobs%pe_requested==0)
     268         320 :             free_pe=isize-sum(jobs%pe_requested)
     269         160 :             if (irank==0.and.i>1) print *,i," jobs are distributed on ",free_pe," unassigned PE"
     270         160 :             i=free_pe/i
     271             : 
     272         160 :             IF (i<1) THEN
     273           0 :                 if (irank==0) PRINT *,"Not enough PE after automatic assignment of jobs"
     274           0 :                 STOP "NOT enough PE"
     275             :             ELSE
     276         320 :                 WHERE (jobs%pe_requested==0) jobs%pe_requested=i
     277             :             ENDIF
     278             :         ENDIF
     279         320 :         free_pe=isize-sum(jobs%pe_requested)
     280         160 :         IF (free_pe<0) THEN
     281           0 :             if (irank==0) PRINT *,"Not enough PE for assignment of jobs"
     282           0 :             STOP "NOT enough PE"
     283             :         ENDIF
     284         160 :         IF (free_pe>0.and.irank==0)    PRINT *,"WARNING, there are unused PE"
     285             : 
     286             :         !Now create the groups
     287         160 :         DO i=1,size(jobs)
     288         160 :             min_pe=sum(jobs(:i-1)%PE_requested)
     289         160 :             IF ((irank.GE.min_pe).AND.(irank<min_pe+jobs(i)%PE_requested)) EXIT
     290             :         ENDDO
     291         320 :         jobs%mpi_comm=MPI_UNDEFINED
     292         160 :         CALL judft_comm_split(MPI_COMM_WORLD,i,irank,new_comm)
     293         160 :         IF (i.LE.size(jobs)) THEN
     294         160 :             if(size(jobs) > 1) PRINT* ,"PE:",irank," works on job ",i," in ",jobs(i)%directory
     295         160 :             jobs(i)%mpi_comm=new_comm
     296             :         ENDIF
     297             : 
     298             : #else
     299             :         IF (size(jobs)>1) THEN
     300             :             PRINT*, "Cannot run multiple jobs without MPI"
     301             :             STOP "NO MPI"
     302             :         ENDIF
     303             :         IF (sum(jobs%pe_requested)>1) THEN
     304             :             PRINT*, "You cannot request a multiple PE job without MPI"
     305             :             STOP "NO MPI"
     306             :         ENDIF
     307             :         jobs(1)%mpi_comm=1
     308             : #endif
     309         160 :     END SUBROUTINE
     310           0 : END MODULE
     311             : 
     312         160 : PROGRAM fleurjob
     313         160 :     USE m_fleur_jobs
     314             :     USE m_juDFT
     315             :     IMPLICIT NONE
     316         160 :     TYPE(t_job),ALLOCATABLE::jobs(:)
     317             :     logical :: l_mpi_multithreaded
     318         160 :     CALL fleur_job_init(l_mpi_multithreaded)
     319             :     CALL fleur_job_arguments(jobs)
     320         160 :     CALL fleur_job_distribute(jobs)
     321         160 :     CALL fleur_job_execute(jobs, l_mpi_multithreaded)
     322           0 : END PROGRAM fleurjob

Generated by: LCOV version 1.14