mergerefined.F90 Source File


Source Code

!-----------------------------------------------------------------------------------------!
! 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 mergerefined

  use mod_read,       only: read_kpointsfile_vis, read_kpointsfile_int
  use mod_ioformat,   only: filename_cubesinfo, filename_fsdata, filename_vtktest,&
                          & fmt_fn_ext, fmt_fn_sub_ext,                           &
                          & filemode_ref, filemode_vis, filemode_int,             &
                          & ext_formatted, ext_vtkxml, ext_new, ext_refined, ext_orig
  use mod_mympi,      only: mympi_init, myrank, nranks, master
  use mod_pointgrp, only: pointgrp
  use mod_fermisurf_basic,  only: find_kpoints_irredset, save_kpointsfile_vis, save_kpointsfile_int
  use mod_vtkxml,     only: write_pointdata_rot
#ifdef CPP_MPI
  use mpi
#endif

  implicit none

  integer :: nBZdim, nCub3(3)
  double precision :: bounds(3,2), areatot

  integer :: nkpts_refined, nkpts_irr_refined, nsym_refined, &
           & nkpts_orig,    nkpts_irr_orig,    nsym_orig,    &
           & nkpts_new,     nkpts_irr_new,     nkpts_orig_filtered

  integer, allocatable :: isym_refined(:), kpt2irr_refined(:), irr2kpt_refined(:), cubeids_refined(:), &
                        & isym_orig(:),    kpt2irr_orig(:),    irr2kpt_orig(:),    cubeids_orig(:),    &
                        & isym_new(:),     kpt2irr_new(:),     irr2kpt_new(:),     cubeids_new(:),     &
                        & cubeids_orig_save(:)

  double precision, allocatable :: kpoints_irr_refined(:,:), kpoints_refined(:,:), areas_refined(:), &
                                 & kpoints_irr_orig(:,:),    kpoints_orig(:,:),    areas_orig(:),    &
                                 & kpoints_irr_new(:,:),     kpoints_new(:,:),     areas_new(:)


  integer :: ierr, ikp, itri, itmparr(1)
  character(len=256) :: filename
  integer, parameter :: ifile=1656

  double precision   :: rotmat(64,3,3)
  character(len=10)  :: rotname(64)
  character(len=256) :: scalarstring(3), vectorstring(1)
  double precision, allocatable :: vectordata(:,:,:), &
                                 & scalardata(:,:)


  integer :: iarg, narg
  character(len=20) :: arg_name

  !initialize MPI
#ifdef CPP_MPI
  call MPI_Init ( ierr )
#endif
  call mympi_init()

  !initializations
  call pointgrp(rotmat,rotname)
  areatot = 0d0

  nBZdim = -1

  narg=command_argument_count()
  if (narg>0) then
    do iarg=1,narg
      call get_command_argument(iarg,arg_name)
      if (arg_name=='--2' .or. arg_name=='-2') nBZdim=2
      if (arg_name=='--3' .or. arg_name=='-3') nBZdim=3
    end do
  end if
  

  write(*,*) '****************************************************'
  write(*,*) '* What is the dimensionality of your BZ            *'
  write(*,*) '* - - - - - - - - - - - - - - - - - - - - - - - - -*'
  write(*,*) '* possible choices implemented: 2 or 3             *'

  if (nBZdim==-1) read(*,*) nBZdim

  write(*,'(A,I3,A)') 'mode ', nBZdim, ' chosen'
  if (.not.(nBZdim==2 .or. nBZdim==3)) stop 'illegal mode'

  !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
  close(ifile)

  !read the bounds
  open(unit=1359,file='bounds',form='formatted',action='read')
  read(1359,'(3ES25.16)') bounds
  close(1359)




  !#################################
  !# work on the visualization set #
  !#################################

  !read in the k-points data
  write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_vis, ext_orig
  call read_kpointsfile_vis(nkpts_orig, nkpts_irr_orig, kpoints_irr_orig, nsym_orig, isym_orig, kpt2irr_orig, irr2kpt_orig, filenamein=filename)
  write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_vis, ext_refined
  call read_kpointsfile_vis(nkpts_refined, nkpts_irr_refined, kpoints_irr_refined, nsym_refined, isym_refined, kpt2irr_refined, irr2kpt_refined, filenamein=filename)

  if(nsym_refined/=nsym_orig)then
    stop 'number of symmetries not consistent for vis'
  else
   if(any(isym_refined/=isym_orig)) stop 'symmetries not consistent for vis'
  end if

  !unfold the compressed data to a big array
  allocate(kpoints_refined(3,nkpts_refined), kpoints_orig(3,nkpts_orig), STAT=ierr)
  if(ierr/=0) stop 'Problem allocating big kpoint-arrays'
  do ikp=1,nkpts_orig
    kpoints_orig(:,ikp) = kpoints_irr_orig(:,kpt2irr_orig(ikp))
  end do!ikp
  do ikp=1,nkpts_refined
    kpoints_refined(:,ikp) = kpoints_irr_refined(:,kpt2irr_refined(ikp))
  end do!ikp

  !compute the cube-ids for each triangle
  call find_cubeids_vis(nBZdim, nkpts_orig,    kpoints_orig,    bounds, nCub3, cubeids_orig,    areas_orig   )
  call find_cubeids_vis(nBZdim, nkpts_refined, kpoints_refined, bounds, nCub3, cubeids_refined, areas_refined)

  !go through the old set and delete triangles that are in the new set
! allocate(cubeids_orig_save(nkpts_orig/3))
! cubeids_orig_save = cubeids_orig
  do itri=1,nkpts_orig/nBZdim
    if(any(cubeids_refined==cubeids_orig(itri))) cubeids_orig(itri) = -1
  end do!itri

! if(myrank==master)then
!   write(*,*) 'deleted triangles:'
!   do itri=1,nkpts_orig/3
!     if(cubeids_orig(itri)==-1) then 
!       write(*,*) cubeids_orig_save(itri)
!     end if!cubeids_orig(itri)==-1
!   end do!itri
!   write(1002,*) cubeids_refined
! end if!myrank==master

  !allocate the new arrays
  nkpts_orig_filtered = nBZdim*count(cubeids_orig/=-1)
  nkpts_new = nkpts_orig_filtered + nkpts_refined
  if(myrank==master) write(*,'("#original= ", I0, " #additional= ",I0, " #deleted= ",I0, " #new= ",I0)') &
                     &          nkpts_orig/nBZdim,   nkpts_refined/nBZdim, count(cubeids_orig==-1),   nkpts_new/nBZdim
  allocate(kpoints_new(3,nkpts_new), cubeids_new(nkpts_new/nBZdim), STAT=ierr)
  if(ierr/=0) stop 'Problem allocating kpoints_new etc.'

  !merge the two arrays
  call merge_arrays_vis()

  !save the visualization set
  call find_kpoints_irredset( bounds, nkpts_new, kpoints_new, nkpts_irr_new, kpt2irr_new, irr2kpt_new )
  if(myrank==master)then
    
    write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_vis, ext_new
    call save_kpointsfile_vis(nkpts_new, nkpts_irr_new, kpoints_new, nsym_orig, isym_orig, kpt2irr_new, irr2kpt_new, filenamein=filename )

    itmparr(1) = 1
    write(filename,fmt_fn_sub_ext) filename_vtktest, filemode_ref, ext_vtkxml
    call write_pointdata_rot( trim(filename),nkpts_new,kpoints_new, &
                            & 0,scalardata,scalarstring,            &
                            & 0,vectordata,vectorstring,            &
                            & 1,rotmat, itmparr                     )
    write(*,*) 'Visualization data written!'
    write(*,'(A,ES18.9)') 'Total area is ', areatot
  end if!myrank==master


  deallocate( isym_refined, kpt2irr_refined, irr2kpt_refined, cubeids_refined, &
            & isym_orig,    kpt2irr_orig,    irr2kpt_orig,    cubeids_orig,    &
            &               kpt2irr_new,     irr2kpt_new,     cubeids_new,     &
            & kpoints_irr_refined, kpoints_refined, areas_refined,             &
            & kpoints_irr_orig,    kpoints_orig,    areas_orig,                &
            &                      kpoints_new                                 )





  !###############################
  !# work on the integration set #
  !###############################

  !read in the k-points data
  write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_int, ext_orig
  call read_kpointsfile_int(nkpts_orig, kpoints_orig, areas_orig, nsym_orig, isym_orig, filename)
  write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_int, ext_refined
  call read_kpointsfile_int(nkpts_refined, kpoints_refined, areas_refined, nsym_refined, isym_refined, filename)

  if(nsym_refined/=nsym_orig)then
    stop 'number of symmetries not consistent for int'
  else
   if(any(isym_refined/=isym_orig)) stop 'symmetries not consistent for int'
  end if

  !compute the cubeids for each kpoint 
  call find_cubeids_int(nkpts_orig,    kpoints_orig,    bounds, nCub3, cubeids_orig   )
  call find_cubeids_int(nkpts_refined, kpoints_refined, bounds, nCub3, cubeids_refined)

  !go through the old set and delete points that are in the new set
! allocate(cubeids_orig_save(nkpts_orig))
! cubeids_orig_save = cubeids_orig
  do ikp=1,nkpts_orig
    if(any(cubeids_refined==cubeids_orig(ikp))) cubeids_orig(ikp) = -1
  end do!itri

! if(myrank==master)then
!   write(*,*) 'deleted points:'
!   do itri=1,nkpts_orig
!     if(cubeids_orig(itri)==-1) then 
!       write(*,*) cubeids_orig_save(itri)
!       write(*,'(8X,4ES25.16)') kpoints_orig(:,itri), areas_orig(itri)
!     end if!cubeids_orig(itri)==-1
!   end do!itri
!   write(1002,*) cubeids_refined
! end if!myrank==master

  !allocate the new arrays
  nkpts_orig_filtered = count(cubeids_orig/=-1)
  nkpts_new = nkpts_orig_filtered + nkpts_refined
  if(myrank==master) write(*,'("#original= ", I0, " #additional= ",I0, " #deleted= ",I0, " #new= ",I0)') &
                     &          nkpts_orig,     nkpts_refined,   count(cubeids_orig==-1),   nkpts_new
  allocate(kpoints_new(3,nkpts_new), cubeids_new(nkpts_new), areas_new(nkpts_new), STAT=ierr)
  if(ierr/=0) stop 'Problem allocating kpoints_new etc.'

  !merge the two arrays
  call merge_arrays_int()

  if(myrank==master)then
    
    write(filename,fmt_fn_sub_ext) filename_fsdata, filemode_int, ext_new
    call save_kpointsfile_int(nkpts_new, kpoints_new, areas_new, nsym_orig, isym_orig, filename)

    write(*,*) 'Integration data written!'
    write(*,'(A,ES18.9)') 'Total area is ', sum(areas_new)
  end if!myrank==master

#ifdef CPP_MPI
  call MPI_Finalize(ierr)
#endif


contains


  subroutine merge_arrays_int()
    implicit none

    integer :: ikp, ipointer

    ipointer = 0
    do ikp=1,nkpts_orig
      if(cubeids_orig(ikp)==-1)then
        write(*,'(A,3ES16.9)') 'skipping cube: k=', kpoints_orig(:,ikp)
        cycle
      end if
      ipointer = ipointer+1
      kpoints_new(:,ipointer) = kpoints_orig(:,ikp)
      cubeids_new(ipointer)   = cubeids_orig(ikp)
      areas_new(ipointer)     = areas_orig(ikp)
    end do!itri

    if(ipointer/=nkpts_orig_filtered) stop 'inconsistency in number of kpoints when filtering old array, int'

    kpoints_new(:,ipointer+1:nkpts_new) = kpoints_refined
    cubeids_new(ipointer+1:nkpts_new)   = cubeids_refined
    areas_new(ipointer+1:nkpts_new)     = areas_refined

  end subroutine merge_arrays_int


  subroutine merge_arrays_vis()
    implicit none

    integer :: itri, ipointer, istart1, istart2, istop1, istop2

    areatot = 0d0

    ipointer = 0
    do itri=1,nkpts_orig/nBZdim
      if(cubeids_orig(itri)==-1) cycle
      ipointer = ipointer+1
      istart1 = (ipointer-1)*nBZdim+1
      istop1  = ipointer*nBZdim
      istart2 = (itri-1)*nBZdim+1
      istop2  = itri*nBZdim
      kpoints_new(:,istart1:istop1) = kpoints_orig(:,istart2:istop2)
      cubeids_new(ipointer) = cubeids_orig(itri)
      areatot = areatot + areas_orig(itri)
    end do!itri

    if(ipointer/=nkpts_orig_filtered/nBZdim) stop 'inconsistency in number of triangles when filtering old array, vis'

    kpoints_new(:,nBZdim*ipointer+1:nkpts_new) = kpoints_refined
    cubeids_new(ipointer+1:nkpts_new/nBZdim)   = cubeids_refined
    areatot = areatot + sum(areas_refined)

  end subroutine merge_arrays_vis


  subroutine find_cubeids_int(nkpts_in, kpoints_in, bounds, nCub3, cubeids)
    implicit none
    integer,                       intent(in)  :: nkpts_in, nCub3(3)
    double precision,              intent(in)  :: kpoints_in(3,nkpts_in), bounds(3,2)
    integer,          allocatable, intent(out) :: cubeids(:)

    integer :: ierr, ikp, ii3(3)

    allocate(cubeids(nkpts_in), STAT=ierr)
    if(ierr/=0) stop 'Problem allocating cubeids in int'

    do ikp=1,nkpts_in
      call kpoint_to_indices(nCub3,bounds,kpoints_in(:,ikp),ii3,cubeids(ikp))
    end do!itri

  end subroutine find_cubeids_int


  subroutine find_cubeids_vis(nBZdim, nkpts_in, kpoints_in, bounds, nCub3, cubeids, areas)
    implicit none
    integer,                       intent(in)  :: nBZdim, nkpts_in, nCub3(3)
    double precision,              intent(in)  :: kpoints_in(3,nkpts_in), bounds(3,2)
    integer,          allocatable, intent(out) :: cubeids(:)
    double precision, allocatable, intent(out) :: areas(:)

    integer :: ierr, itri, ik1, ik2, ikp, ii3(3)
    double precision :: ktriangle(3,nBZdim), kmedium(3)

    allocate(cubeids(nkpts_in/nBZdim), areas(nkpts_in/nBZdim), STAT=ierr)
    if(ierr/=0) stop 'Problem allocating cubeids in vis'

    do itri=1,nkpts_in/nBZdim
      ik1=(itri-1)*nBZdim+1
      ik2=itri*nBZdim
      ktriangle = kpoints_in(:,ik1:ik2)

      if(nBZdim==3)then
        areas(itri) = area_triangle(ktriangle)
      elseif(nBZdim==2)then
        areas(itri) = sqrt( sum((ktriangle(:,2)-ktriangle(:,1))**2) )
      else
        stop 'nBZdim shall be 2 or 3'
      endif

      kmedium = 0
      do ikp=1,nBZdim
        kmedium = kmedium + ktriangle(:,ikp)
      end do!ikp
      kmedium = kmedium/nBZdim

      call kpoint_to_indices(nCub3,bounds,kmedium,ii3,cubeids(itri))

    end do!itri

  end subroutine find_cubeids_vis



  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+1d-14)

    ixyz = 1 + ii3(1) + nCub3(1)*ii3(2) + nCub3(1)*nCub3(2)*ii3(3)

  end subroutine kpoint_to_indices



  double precision function area_triangle(kpoints)

    use mod_mathtools, only: crossprod

    double precision, intent(in) :: kpoints(3,3)
    double precision :: k21(3), k31(3), kcross(3)

    k21 = kpoints(:,3) - kpoints(:,1)
    k31 = kpoints(:,3) - kpoints(:,2)
    call crossprod(k21, k31, kcross)

    area_triangle = 0.5d0*sqrt(sum(kcross**2))

  end function area_triangle

end program mergerefined