!-----------------------------------------------------------------------------------------! ! Copyright (c) 2016 Peter Grünberg Institut, Forschungszentrum Jülich, Germany ! ! This file is part of kk-prime@juKKR and available as free software under the conditions ! ! of the MIT license as expressed in the LICENSE file in more detail. ! !-----------------------------------------------------------------------------------------! program refineBZparts use mod_mathtools, only: bubblesort_int use mod_ioinput, only: IoInput use mod_ioformat, only: filename_cubesinfo, filename_cubesrefine, ext_formatted, fmt_fn_ext implicit none integer :: nCub3(3), nCub3_inp(3), nCub3_file(3), nFSiter, ii3(3), imarked(1), nmarked, nverts, nBZdimen=3 integer, allocatable :: nCut_iter(:), nCub3_steps(:,:) double precision :: bounds(3,2) integer :: idomain, ierr, istep, iselect character(len=80) :: uio character(len=256) :: filename integer, parameter :: ifile=14, iofile=16 write(*,*) '****************************************************' write(*,*) '* What is the dimensionality of your BZ *' write(*,*) '* - - - - - - - - - - - - - - - - - - - - - - - - -*' write(*,*) '* possible choices implemented: 2 or 3 *' read(*,*) nBZdimen select case (nBZdimen) case (3); nverts=8 case (2); nverts=4 case default; stop 'nBZdimen =/= 2 or 3' end select write(filename,fmt_fn_ext) filename_cubesrefine, ext_formatted open(unit=iofile,file=filename,form='formatted',action='write',access='append') !read in the cubes header write(filename,fmt_fn_ext) filename_cubesinfo, ext_formatted open(unit=ifile,file=trim(filename),form='formatted',action='read') read(ifile,'(3I8)') nCub3_file close(ifile) write(*,'(A)') 'BZdivisions from cubesinfo.txt:' write(*,'(3I8)') nCub3_file nCub3 = nCub3_file !read the bounds open(unit=1359,file='bounds',form='formatted',action='read') read(1359,'(3ES25.16)') bounds close(1359) !************************************* !*** get infos from the input card *** !************************************* call IoInput('NKPTCUBES ',uio,1,7,ierr) read(unit=uio,fmt=*) nCub3_inp(:) call IoInput('NFSITER ',uio,1,7,ierr) read(unit=uio,fmt=*) nFSiter allocate(nCut_iter(nFSiter), STAT=ierr) if(ierr/=0) stop 'Problem allocating nCut_iter etc.' call IoInput('NREFINE ',uio,1,7,ierr) read(unit=uio,fmt=*) nCut_iter !*********************************** !*** compute the divisions of BZ *** !*********************************** allocate(nCub3_steps(3,nFSiter+1),STAT=ierr) if(ierr/=0) stop 'Problem allocating nCub3_steps' nCub3_steps(:,1) = nCub3_inp do istep=1,nFSiter nCub3_steps(:,istep+1) = nCub3_steps(:,istep)*nCut_iter(istep) if(nBZdimen==2) nCub3_steps(3,istep+1)=1 end do !loop to input multiple choices idomain=0 do while(idomain==0) write(*,*) '****************************************************' write(*,*) '* What do you want to do? *' write(*,*) '* - - - - - - - - - - - - - - - - - - - - - - - - -*' write(*,*) '* 0) exit program *' write(*,*) '* 1) change the cube size *' write(*,*) '* 2) add a single cube containing a single point *' write(*,*) '* 3) add multiple cubes in a sphere around a point *' write(*,*) '* 4) include the incomplete cubes from outfiles *' read(*,*) iselect select case(iselect) case(0); idomain=1 case(1) nCub3 = select_cubesize(nFSiter, nCub3_steps, bounds) case(2); call add_point ( nCub3, nCub3_file, nFSiter, nCub3_steps, bounds ) case(3); call add_sphere( nverts, nCub3, nCub3_file, nFSiter, nCub3_steps, bounds ) case(4); call add_from_outfile(nCub3_file, bounds) case default; write(*,*) '--> illegal input option. Try again.' end select end do!while close(iofile) contains subroutine add_from_outfile(nCub3,bounds) use mod_ioformat, only: fmt_fn_rank_ext, filename_outinfo, ext_formatted implicit none integer, intent(in) :: nCub3(3) double precision, intent(in) :: bounds(3,2) integer :: nFiles, nmarked, iselect, ipt, ii, ifile, iline, icube integer, allocatable :: nLines(:), imarked(:) character(len=256) :: filename integer, parameter :: iounit=6592 nFiles = get_nFiles() allocate(nLines(nFiles)) do ifile=1,nFiles write(filename,fmt_fn_rank_ext) filename_outinfo, ifile-1, ext_formatted open(iounit, file=trim(filename), form='formatted', action='read') nLines(ifile) = get_nLines( iounit ) write(*,'(A,A,I0)') trim(filename), ' --- ', nLines(ifile) close(iounit) end do nmarked=sum(nLines) allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked' ipt=0 do ifile=1,nFiles write(filename,fmt_fn_rank_ext) filename_outinfo, ifile-1, ext_formatted open(iounit, file=trim(filename), form='formatted', action='read') do iline=1,nLines(ifile) ipt=ipt+1 read(iounit,*) imarked(ipt) end do!iline close(iounit) end do!ifile if(ipt/=nmarked) then write(*,'(I0,A,I0)') ipt, ' = ipt does not equal nmarked = ', nmarked stop 'Data inconsitency with outfiles' end if select case (nBZdimen) case (3); call cubes2VTK('test_cube.vtp', nCub3, nmarked, imarked, bounds) case (2); call squares2TXT('test_square.txt', nCub3, nmarked, imarked, bounds) case default; stop 'nBZdimen =/= 2 or 3' end select write(*,'(A,I0,A,I0)') ' .. number of cubes found in the ', nFiles, ' files =', nmarked write(*,*) '***************************' write(*,*) '* Add these points ? *' write(*,*) '* 0: no *' write(*,*) '* 1: yes *' read(*,*) iselect select case(iselect) case(0) write(*,*) ' ... Cubes ignored!' case(1) do ii=1,nmarked write(iofile,'(5I8)') nCub3, 1, imarked(ii) end do!ii write(*,'(A,I0,A)') ' ... ', ii-1, ' cubes added to refinement-file' case default write(*,*) ' ... This is was illegal input option.' end select end subroutine add_from_outfile subroutine add_point(nCub3, nCub3_file, nFSiter, nCub3_steps, bounds ) implicit none integer, intent(in) :: nCub3(3), nCub3_file(3), nFSiter, nCub3_steps(3,nFSiter+1) double precision, intent(in) :: bounds(3,2) integer :: ido, nmarked, imarked(1), ii3(3), nCub3tmp(3), iselect double precision :: kpoint(3) nCub3tmp = nCub3 !************************** !*** enter the k-point ***! !************************** write(*,*) '***************************' write(*,*) '* Enter the k-point: *' read(*,*) kpoint nmarked = 1 ido=0 do while(ido==0) call kpoint_to_indices(nCub3tmp,bounds,kpoint,ii3,imarked(1)) !************************** !*** visualize the cube *** !************************** select case (nBZdimen) case (3); call cubes2VTK('test_cube.vtp', nCub3tmp, nmarked, imarked, bounds) case (2); call squares2TXT('test_square.txt', nCub3tmp, nmarked, imarked, bounds) case default; stop 'nBZdimen =/= 2 or 3' end select !********************************* !*** Ask user about what to do *** !********************************* write(*,*) '.. number of this cube: imarked=', imarked write(*,*) '.. cube written to file test_cube.vtp' write(*,*) '' write(*,*) '*************************************************' write(*,*) '* Shall I add this cube to the refinement-file? *' write(*,*) '* 0: no *' write(*,*) '* 1: yes *' write(*,*) '* 2: change cubesize and try again *' read(*,*) iselect select case(iselect) case(0) write(*,*) ' ... Cube ignored!' ido=1 case(1) write(iofile,'(5I8)') nCub3tmp, nCub3_file(1)/nCub3tmp(1), imarked(1) write(*,*) ' ... Cube added to refinement-file' ido=1 case(2) !change size of cubes nCub3tmp = select_cubesize(nFSiter, nCub3_steps, bounds) ido=0 case default write(*,*) ' ... This is an illegal input option.' write(*,*) ' ..... Your input was: ', iselect write(*,*) ' ..... Try again!' ido=0 end select end do!while ido==0 end subroutine add_point subroutine add_sphere(nverts,nCub3,nCub3_file,nFSiter,nCub3_steps,bounds) implicit none integer, intent(in) :: nverts, nCub3(3), nCub3_file(3), nFSiter, nCub3_steps(3,nFSiter+1) double precision, intent(in) :: bounds(3,2) integer :: nmarked, ii, ido, nCub3tmp(3) double precision :: kcenter(3), radius integer, allocatable :: imarked(:) nCub3tmp = nCub3 write(*,*) nCub3tmp !************************** !*** enter the sphere ***! !************************** write(*,*) '***************************************' write(*,*) '* Enter the center of the sphere *' read(*,*) kcenter write(*,*) '* Enter the radius of the sphere *' read(*,*) radius ido=0 do while(ido==0) call mark_cubes_in_sphere(nverts, nCub3tmp,bounds,kcenter,radius,nmarked,imarked) !************************** !*** visualize the cube *** !************************** select case (nBZdimen) case (3); call cubes2VTK('test_cube.vtp', nCub3tmp, nmarked, imarked, bounds) case (2); call squares2TXT('test_square.txt', nCub3tmp, nmarked, imarked, bounds) case default; stop 'nBZdimen =/= 2 or 3' end select !********************************* !*** Ask user about what to do *** !********************************* write(*,*) '.. number of cubes found = ', nmarked write(*,*) '.. cubes written to file test_cube.vtp' write(*,*) '' write(*,*) '***************************************************' write(*,*) '* Shall I add these cubes to the refinement-file? *' write(*,*) '* 0: no *' write(*,*) '* 1: yes *' write(*,*) '* 2: change cubesize and try again *' read(*,*) iselect select case(iselect) case(0) write(*,*) ' ... Cube ignored!' ido=1 case(1) do ii=1,nmarked write(iofile,'(5I8)') nCub3tmp, nCub3_file(1)/nCub3tmp(1), imarked(ii) end do!ii write(*,'(A,I0,A)') ' ... ', ii-1, ' cubes added to refinement-file' ido=1 case(2) !change size of cubes nCub3tmp = select_cubesize(nFSiter, nCub3_steps, bounds) ido=0 case default write(*,*) ' ... This is an illegal input option.' write(*,*) ' ..... Your input was: ', iselect write(*,*) ' ..... Try again!' ido=0 end select end do!while ido==0 end subroutine add_sphere function select_cubesize(nFSiter, nCub3_steps, bounds) result(nCub3) implicit none integer, intent(in) :: nFSiter, nCub3_steps(3,nFSiter+1) double precision, intent(in) :: bounds(3,2) integer :: nCub3(3) integer :: ido, iselect, istep write(*,*) '**********************************************' write(*,*) '* The BZ-Divisios for the steps are: *' write(*,*) '* *' do istep=1,nFSiter+1 write(*,'(" * step= ",I2," -> nCub= ",3I8," *")') istep, nCub3_steps(:,istep) end do write(*,*) '* - - - - - - - - - - - - - - - - - - - - - -*' write(*,*) '* Enter the cubesize you want to use. *' write(*,*) '* [Press 0 to exit program] *' ido=0 do while (ido==0) read(*,*) iselect if(iselect>nFSiter+1)then write(*,'(A,I0)') ' ... Only integers between 1 and ', nFSiter+1, ' are allowed! Try again:' elseif(iselect==0)then stop '!!! Aborted by user !!!' else nCub3 = nCub3_steps(:,iselect) write(*,'(A,3I8)') '... your selected cubesize: ', nCub3 write(*,'(A,3F8.4)') '... this corresponds to cubelengths of: ', (bounds(:,2)-bounds(:,1))/nCub3 ido=1 end if end do!while end function select_cubesize subroutine kpoint_to_indices(nCub3,bounds,kpoint,ii3,ixyz) implicit none integer, intent(in) :: nCub3(3) double precision, intent(in) :: bounds(3,2), kpoint(3) integer, intent(out) :: ii3(3), ixyz double precision :: ktemp(3) ktemp = (kpoint - bounds(:,1))/(bounds(:,2) - bounds(:,1)) ii3 = int(ktemp*nCub3) ixyz = 1 + ii3(1) + nCub3(1)*ii3(2) + nCub3(1)*nCub3(2)*ii3(3) end subroutine kpoint_to_indices subroutine cubes2VTK(filename,nCub3,nmarked,imarked,bounds) use mod_vtkxml implicit none character(len=*), intent(in) :: filename integer, intent(in) :: nCub3(3), nmarked, imarked(nmarked) double precision, intent(in) :: bounds(3,2) integer :: faces(4,6), offsets(6) double precision :: kverts(3,8) integer :: icub, ivert, iface character(len=80) :: fmtstr open(unit=123894, file=trim(filename), action='write', form='formatted') !write header write(123894, FMT=vtkfmt_ivtkfile) write(123894, FMT=vtkfmt_ipolydata) write(123894, FMT=vtkfmt_ipiece) 8*nmarked, 6*nmarked !write points write(123894, FMT=vtkfmt_ipoints) write(123894, FMT=vtkfmt_idata_points) write(fmtstr,'("(",I0,"X,3ES14.5)")') vtkfmxXdata do icub=1,nmarked call generate_cubevertices(nCub3,imarked(icub),bounds,kverts) do ivert=1,8 write(123894, FMT=fmtstr) kverts(:,ivert) end do!ivert end do!icub write(123894, FMT=vtkfmt_fdata) write(123894, FMT=vtkfmt_fpoints) faces(:,1) = (/ 0,1,3,2 /) faces(:,2) = (/ 0,1,5,4 /) faces(:,3) = (/ 0,2,6,4 /) faces(:,4) = (/ 1,3,7,5 /) faces(:,5) = (/ 2,3,7,6 /) faces(:,6) = (/ 4,5,7,6 /) offsets = (/ 4, 8, 12, 16, 20, 24 /) !write polys write(123894, FMT=vtkfmt_ipolys) write(123894, FMT=vtkfmt_idata_connectivity) do icub=1,nmarked do iface=1,6 write(123894, FMT='(10X,4I8)' ) faces(:,iface)+(icub-1)*8 end do!iface end do!icub write(123894, FMT=vtkfmt_fdata) write(123894, FMT=vtkfmt_idata_offsets) write(fmtstr, '("(",I0,"X,6(I0,X))")') vtkfmxXdata do icub=1,nmarked write(123894, FMT=fmtstr) offsets + (icub-1)*24 end do!icub write(123894, FMT=vtkfmt_fdata) write(123894, FMT=vtkfmt_fpolys) !write tail write(123894, FMT=vtkfmt_fpiece) write(123894, FMT=vtkfmt_fpolydata) write(123894, FMT=vtkfmt_fvtkfile) close(123894) end subroutine cubes2VTK subroutine squares2TXT(filename,nCub3,nmarked,imarked,bounds) ! use mod_fermisurf_basic, only: generate_squarevertices implicit none character(len=*), intent(in) :: filename integer, intent(in) :: nCub3(3), nmarked, imarked(nmarked) double precision, intent(in) :: bounds(3,2) double precision :: kverts(3,4) integer :: isqu, ivert character(len=80) :: fmtstr open(unit=123895, file=trim(filename), action='write', form='formatted') !write header write(123895,'(A)') '# four lines define one square' !write points do isqu=1,nmarked call generate_squarevertices(nCub3,imarked(isqu),bounds,kverts) do ivert=1,4 write(123895,'(3ES25.16)') kverts(:,ivert) end do!ivert end do!icub close(123895) end subroutine squares2TXT subroutine mark_cubes_in_sphere(nverts,nCub3,bounds,kcenter,radius,nmarked,imarked) implicit none integer, intent(in) :: nverts, nCub3(3) double precision, intent(in) :: bounds(3,2), kcenter(3), radius integer, intent(out) :: nmarked integer, allocatable, intent(out) :: imarked(:) integer :: ierr, icube, ntotmax double precision :: kverts(3,nverts) integer, allocatable :: imarkedtmp(:) ntotmax = product(nCub3) allocate(imarkedtmp(ntotmax), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarkedtmp(ntotmax) in mark_cubes_in_sphere' nmarked=0 do icube=1,ntotmax select case (nBZdimen) case (3); call generate_cubevertices(nCub3,icube,bounds,kverts) case (2); call generate_squarevertices(nCub3,icube,bounds,kverts) case default; stop 'nBZdimen =/= 2 or 3' end select if(cube_in_sphere(nverts,kverts,kcenter,radius)) then nmarked = nmarked+1 imarkedtmp(nmarked) = icube end if end do!icube if(nmarked==0) write(*,*) 'WARNING: no cubes in sphere found' allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked(nmarked) in mark_cubes_in_sphere' imarked = imarkedtmp(1:nmarked) deallocate(imarkedtmp) end subroutine mark_cubes_in_sphere logical function cube_in_sphere(nverts,kverts,kcenter,radius) implicit none integer, intent(in) :: nverts double precision, intent(in) :: kverts(3,nverts), kcenter(3), radius integer :: ipoint double precision :: dtmp, rsquare logical :: points_in_sphere(nverts) rsquare = radius**2 do ipoint=1,nverts dtmp = sum((kverts(:,ipoint) - kcenter(:))**2) points_in_sphere(ipoint) = (dtmp<rsquare) end do!ipoint cube_in_sphere = all(points_in_sphere) end function cube_in_sphere subroutine generate_cubevertices(nCub3,cubeid,bounds,kverts) !generates the vertices of a cube given by the cubeid implicit none integer, intent(in) :: nCub3(3), cubeid double precision, intent(in) :: bounds(3,2) double precision, intent(out) :: kverts(3,8) integer :: ii3(3), ivert call unroll_ixyz(cubeid, nCub3, ii3) !generate vertices, limits are from 0 to 1 kverts(:,1) = dble( (/ ii3(1) , ii3(2) , ii3(3) /) )/nCub3 kverts(:,2) = dble( (/ ii3(1)+1, ii3(2) , ii3(3) /) )/nCub3 kverts(:,3) = dble( (/ ii3(1) , ii3(2)+1, ii3(3) /) )/nCub3 kverts(:,4) = dble( (/ ii3(1)+1, ii3(2)+1, ii3(3) /) )/nCub3 kverts(:,5) = dble( (/ ii3(1) , ii3(2) , ii3(3)+1 /) )/nCub3 kverts(:,6) = dble( (/ ii3(1)+1, ii3(2) , ii3(3)+1 /) )/nCub3 kverts(:,7) = dble( (/ ii3(1) , ii3(2)+1, ii3(3)+1 /) )/nCub3 kverts(:,8) = dble( (/ ii3(1)+1, ii3(2)+1, ii3(3)+1 /) )/nCub3 !shift the vertices to the correct bounds do ivert=1,8 kverts(:,ivert) = kverts(:,ivert)*(bounds(:,2)-bounds(:,1))+bounds(:,1) end do!ivert end subroutine generate_cubevertices subroutine generate_squarevertices(nCub3,cubeid,bounds,kverts) !generates the vertices of a square given by the id implicit none integer, intent(in) :: nCub3(3), cubeid double precision, intent(in) :: bounds(3,2) double precision, intent(out) :: kverts(3,4) integer :: ii3(3), ivert call unroll_ixyz(cubeid, nCub3, ii3) !generate vertices, limits are from 0 to 1 kverts(:,1) = dble( (/ ii3(1) , ii3(2) , 0 /) )/nCub3 kverts(:,2) = dble( (/ ii3(1)+1, ii3(2) , 0 /) )/nCub3 kverts(:,3) = dble( (/ ii3(1) , ii3(2)+1, 0 /) )/nCub3 kverts(:,4) = dble( (/ ii3(1)+1, ii3(2)+1, 0 /) )/nCub3 !shift the vertices to the correct bounds do ivert=1,4 kverts(:,ivert) = kverts(:,ivert)*(bounds(:,2)-bounds(:,1))+bounds(:,1) end do!ivert end subroutine generate_squarevertices subroutine unroll_ixyz(ixyz, nCub3, ii3) !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ !+ helper function to divide the UID to an integer triple + !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ implicit none integer, intent(in) :: ixyz, nCub3(3) integer, intent(out) :: ii3(3) integer :: irest ii3(3) = int((ixyz-1)/(nCub3(1)*nCub3(2))) irest= ixyz-1-ii3(3)*(nCub3(1)*nCub3(2)) ii3(2) = int(irest/nCub3(1)) irest= ixyz-1-ii3(3)*(nCub3(1)*nCub3(2)) - ii3(2)*nCub3(1) ii3(1) = irest end subroutine unroll_ixyz integer function get_nFiles() use mod_ioformat, only: fmt_fn_rank_ext, filename_outinfo, ext_formatted implicit none integer :: nFiles logical :: fileexists character(len=80) :: filename nFiles=0 fileexists = .TRUE. do while (fileexists) write(filename,fmt_fn_rank_ext) filename_outinfo, nFiles, ext_formatted inquire(file=filename, exist=fileexists) nFiles = nFiles+1 end do get_nFiles = nFiles-1 write(*,'(A,I0)') 'Number of output-files found = ', get_nFiles end function get_nFiles function get_nLines( UIO ) result( nLines ) implicit none integer :: nLines, IOERR, UIO character(len=50) :: tmpstring nLines = 0 Read_Loop: DO READ( UIO, *, IOSTAT = IOERR ) tmpstring IF (IOERR < 0) THEN EXIT Read_Loop END IF nLines = nLines + 1 END DO Read_Loop end function get_nLines end program refineBZparts