!-----------------------------------------------------------------------------------------! ! 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. ! !-----------------------------------------------------------------------------------------! module mod_fermisurf_3D implicit none private public :: find_fermisurface_3D integer, save :: tetcorners(4,6)=-1, tetdiags(2,4)=-1, cubedges(2,19)=-1, tetedges(6,6)=-1 integer, parameter :: nkpmax = 512 ! shall be >> 32 to contain enough triangles per cube and band contains subroutine find_fermisurface_3D( inc, lattice, cluster, tgmatrx, symmetries, nCub3, nFSiter, nROOTiter, nstepsconnect, & & nCut_iter, roottype, rooteps, lrefine, nrefinenew, nkpts_int, kpoints_int, areas_int ) use type_inc, only: inc_type use type_data, only: lattice_type, cluster_type, tgmatrx_type use mod_symmetries, only: symmetries_type, get_IBZwedge_faces use mod_mympi, only: myrank, nranks, master use mod_ioformat, only: filename_cubesinfo, ext_formatted, fmt_fn_ext use mod_iohelp, only: file_present use mod_fermisurf_basic, only: get_cubesinfo_filename, read_cubesfile, save_cubesfile, mark_cubes_FScross, find_kpoints_irredset, save_kpointsfile_vis #ifdef CPP_TIMING use mod_timing, only: timing_start, timing_stop #endif implicit none type(inc_type), intent(in) :: inc type(lattice_type), intent(in) :: lattice type(cluster_type), intent(in) :: cluster type(tgmatrx_type), intent(inout) :: tgmatrx type(symmetries_type), intent(in) :: symmetries integer, intent(inout) :: nCub3(3) integer, intent(in) :: nFSiter, nROOTiter, lrefine, nrefinenew, nCut_iter(:), roottype(:), nstepsconnect(:) double precision, intent(in) :: rooteps(:) integer, intent(out) :: nkpts_int double precision, allocatable, intent(out) :: kpoints_int(:,:), areas_int(:) integer :: nfaces double precision :: bounds(3,2) double precision, allocatable :: nvec(:,:), dscal(:) integer :: nmarked, ntotal integer, allocatable :: imarked(:) integer :: nkpts_vis, nkpts_irr integer, allocatable :: kpt2irr(:), irr2kpt(:), vis2int(:) double precision, allocatable :: kpoints_vis(:,:) integer :: icube, iter, iter2, ierr, ii, nCub3test(3), iterstart double precision :: dtmp character(len=256) :: filename, filetest logical :: l_cubesfile, l_exist #ifdef CPP_TIMING call timing_start(' FS 3D - get cubes') #endif call get_IBZwedge_faces(lattice%recbv, symmetries%nsym_used, symmetries%rotmat, symmetries%isym_used, nfaces, nvec, dscal, bounds) !initialize tetraeder indices arrays call init_cube2tetralines() !=====================================! !=== generate or read a cubesfile ====! !=====================================! write(filename,fmt_fn_ext) filename_cubesinfo, ext_formatted if(.not.file_present(trim(filename)).and.lrefine==1) stop 'cannot refine dataset: no cubesinfo present' if(file_present(trim(filename)))then call read_cubesfile(nCub3test, nmarked, imarked) if(any(nCub3 /= nCub3test).and.(myrank==master)) write(*,*) 'Warning!!! nCub3 inconsistent with cubesfile. Taking the values from cubesfile' nCub3 = nCub3test if(lrefine==1)then deallocate(imarked) call read_cubesrefine(nCub3test, nmarked, imarked) if(any(nCub3/=nCub3test)) stop 'nCub3 not consistent between cubesinfo and cubesrefine' if(myrank==master)then write(filename,'("cubes_refine_step=",I0,"_",A".vtp")') 0, 'read' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) end if!myrank==master end if!lrefine==1 ! write(*,*) 'readin of cubesfile done on rank', myrank else!cubesfile_present !search for existing cubesfiles that match the grid of an iteration within the iterative refinements iterstart=1 !try to take the densest file, therefore count from top to bottom: iter_loop: do iter=nFSiter,1,-1 !find the density of the cubes of iteration #iter nCub3test = nCub3 do iter2=2,iter nCub3test = nCub3test*nCut_iter(iter2-1) end do!iter2 !search for the existing cubesfile filetest = get_cubesinfo_filename(nCub3test,.true.) l_exist = file_present(trim(filetest)) if(l_exist)then iterstart=iter+1 call read_cubesfile(nCub3, nmarked, imarked, nCub3test) call cut_and_update_cubes(nCut_iter(iter), nCub3, nmarked, imarked) ntotal = nmarked if(myrank==master) then write(filename,'("cubes_iter=",I0,"_step=",I0,"_",(A),".vtp")') iter, 3, 'cut' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) end if!myrank==master !cubesfile found, so exit loop exit iter_loop end if!l_exist end do iter_loop if(iterstart==1)then !initialize cubes indices nmarked = product(nCub3) ntotal = product(nCub3) allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in fermisurface' do icube=1,nmarked imarked(icube) = icube end do!icube end if!iterstart==1 #ifdef CPP_TIMING call timing_stop(' FS 3D - get cubes') #endif !====== != scan the cubes for intersections !====== do iter=iterstart,nFSiter #ifdef CPP_TIMING call timing_start(' FS 3D - FS iter - mark cubes in IBZ') #endif !=== mark the cubes that lie (at least with one corner) within the first BZ ===! call mark_cubes_in_IBZ(nCub3, nfaces, nvec, dscal, bounds, nmarked, imarked) if(myrank==master) then write(filename,'("cubes_iter=",I0,"_step=",I0,"_",(A),".vtp")') iter, 1, 'IBZ' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) write(*,'("***** Iteration ",I0," *****")') iter write(*,'(2X,2(A,I0),(A,F5.1,A))') 'Cubes found within the IBZ: ', nmarked, ' of ', ntotal, ' (= ', real(nmarked*100)/ntotal,' %)' end if!myrank==master #ifdef CPP_TIMING call timing_stop(' FS 3D - FS iter - mark cubes in IBZ') #endif #ifdef CPP_TIMING call timing_start(' FS 3D - FS iter - find FS crossings') #endif !========= mark the cubes that cross the Fermi surface =========! !=== (only searching across the four diagonals of the cubes) ===! ntotal = nmarked call mark_cubes_FScross( inc, lattice, cluster, tgmatrx, nCub3, & & nstepsconnect(iter), 8, 4, tetdiags, bounds, & & roottype(iter), rooteps(iter), nmarked, imarked ) if(myrank==master) then write(filename,'("cubes_iter=",I0,"_step=",I0,"_",(A),".vtp")') iter, 2, 'mark' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) write(*,'(2X,2(A,I0),(A,F5.1,A))') 'Cubes found intersecting with FS: ', nmarked, ' of ', ntotal, ' (= ', real(nmarked*100)/ntotal,' %)' call save_cubesfile(nCub3, nmarked, imarked, lintermediate=.true.) end if!myrank==master #ifdef CPP_TIMING call timing_stop(' FS 3D - FS iter - find FS crossings') #endif #ifdef CPP_TIMING call timing_start(' FS 3D - FS iter - divide cubes') #endif !=== cut the remaining cubes into smaller pieces and update the indices ===! ! write(1000+myrank,*) iter, nCut_iter(iter) call cut_and_update_cubes(nCut_iter(iter), nCub3, nmarked, imarked) ntotal = nmarked if(myrank==master) then write(filename,'("cubes_iter=",I0,"_step=",I0,"_",(A),".vtp")') iter, 3, 'cut' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) end if!myrank==master #ifdef CPP_TIMING call timing_stop(' FS 3D - FS iter - divide cubes') #endif end do!iter !=== mark the cubes that lie (maybe only partly) within the first BZ ===! iter = nFSiter+1 call mark_cubes_in_IBZ(nCub3, nfaces, nvec, dscal, bounds, nmarked, imarked) if(myrank==master) then write(filename,'("cubes_iter=",I0,"_step=",I0,"_",(A),".vtp")') iter, 1, 'IBZ' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) call save_cubesfile(nCub3, nmarked, imarked) end if!myrank==master end if!cubesfile_present !=====================================! !=== generate or read a cubesfile ====! !=====================================! iter = nFSiter+1 !=======================================! !=== refine the grid on a cubesfile ====! !=======================================! if(lrefine==1)then if(myrank==master) write(*,*) 'In REFINE mode...' ! write(*,'("-->NREFINE= ",I0)') nrefinenew call cut_and_update_cubes(nrefinenew, nCub3, nmarked, imarked) if(myrank==master)then write(filename,'("cubes_refine_step=",I0,"_",A".vtp")') 1, 'cut' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) end if!myrank==master ntotal = nmarked call mark_cubes_in_IBZ(nCub3, nfaces, nvec, dscal, bounds, nmarked, imarked) if(myrank==master)then write(filename,'("cubes_refine_step=",I0,"_",A,".vtp")') 2, 'IBZ' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) write(*,'(2X,2(A,I0),(A,F5.1,A))') 'Cubes found within the IBZ: ', nmarked, ' of ', ntotal, ' (= ', real(nmarked*100)/ntotal,' %)' end if!myrank==master ntotal = nmarked call mark_cubes_FScross( inc, lattice, cluster, tgmatrx, nCub3, & & nstepsconnect(nFSiter), 8, 4, tetdiags, bounds, & & roottype(nFSiter), rooteps(nFSiter), nmarked, imarked ) if(myrank==master) then write(filename,'("cubes_refine_step=",I0,"_",A,".vtp")') 3, 'mark' call cubes2VTK(filename, nCub3, nmarked, imarked, bounds) write(*,'(2X,2(A,I0),(A,F5.1,A))') 'Cubes found intersecting with FS: ', nmarked, ' of ', ntotal, ' (= ', real(nmarked*100)/ntotal,' %)' end if!myrank==master end if!lrefine==1 !=======================================! !=== refine the grid on a cubesfile ====! !=======================================! ! write(3360+myrank,*) iter, nstepsconnect(iter), nROOTiter ! write(3360+myrank,*) roottype(iter), rooteps(iter) ! write(3360+myrank,*) nfaces ! write(3360+myrank,*) nvec ! write(3360+myrank,*) dscal ! dtmp=0d0 ! do ii=1,10000000 ! dtmp=dtmp+datan(ii*0.1d0)/ii ! end do!ii #ifdef CPP_TIMING call timing_start(' FS 3D - find FS intersections') #endif ! write(*,*) 'before sub find_intesection_triangles, myrank=',myrank call find_intesection_triangles( inc, lattice, cluster, tgmatrx, symmetries, & & nCub3, bounds, nmarked, imarked, & & nstepsconnect(iter), nROOTiter, & & roottype(iter), rooteps(iter), nfaces, & & nvec, dscal, nkpts_vis, nkpts_int, & & kpoints_vis, kpoints_int, areas_int, vis2int ) call find_kpoints_irredset( bounds, nkpts_vis, kpoints_vis, nkpts_irr, kpt2irr, irr2kpt) #ifdef CPP_TIMING call timing_stop(' FS 3D - find FS intersections') #endif !save the visualization k-points to a file if(myrank==master) call save_kpointsfile_vis(nkpts_vis, nkpts_irr, kpoints_vis, symmetries%nsym_used, symmetries%isym_used, kpt2irr, irr2kpt, vis2int) end subroutine find_fermisurface_3D subroutine find_intesection_triangles( inc, lattice, cluster, tgmatrx, symmetries, & & nCub3, bounds, nmarked, imarked, & & nsteps, niter, roottype, rooteps, & & nfaces, nvec, dscal, npoints_vis_tot, & & npoints_int_tot, kpoints_vis_all, & & kpoints_int_all, areas_int_all, vis2int_all ) use type_inc, only: inc_type use type_data, only: lattice_type, cluster_type, tgmatrx_type use mod_symmetries, only: symmetries_type use mod_parutils, only: distribute_linear_on_tasks use mod_mympi, only: myrank, nranks, master use mod_mathtools, only: bubblesort, findminindex use mod_vtkxml, only: write_pointdata_rot use mod_ioformat, only: fmt_fn_ext, fmt_fn_sub_ext, ext_vtkxml, filemode_rot, filename_vtktest, fmt_fn_rank_ext, filename_outinfo, ext_formatted use mod_fermisurf_basic, only: roots_along_edge, compare_two_eigv_in_substeps, ROOT_IMAG, ROOT_REAL, generate_cubevertices #ifdef CPP_MPI use mpi #endif #ifdef CPP_TIMING use mod_timing, only: timing_start, timing_stop #endif implicit none type(inc_type), intent(in) :: inc type(lattice_type), intent(in) :: lattice type(cluster_type), intent(in) :: cluster type(tgmatrx_type), intent(in) :: tgmatrx type(symmetries_type), intent(in) :: symmetries integer, intent(in) :: nCub3(3), nmarked, imarked(nmarked),& & nsteps, roottype, niter, nfaces double precision, intent(in) :: bounds(3,2), rooteps, nvec(3,nfaces), dscal(nfaces) integer, intent(out) :: npoints_vis_tot, npoints_int_tot integer, allocatable, intent(out) :: vis2int_all(:) double precision, allocatable, intent(out) :: kpoints_vis_all(:,:),& & kpoints_int_all(:,:),& & areas_int_all(:) integer :: irank, npoints_vis,& & npoints_vis_tmpa(0:nranks-1),& & npoints_int_tmpa(0:nranks-1),& & ioffs_tmpa(0:nranks-1),& & ioffs_save(0:nranks-1),& & isendarr(0:nranks-1),& & ioffsarr(0:nranks-1) double precision, allocatable :: kpoints_vis(:,:),& & kpoints_int(:,:),& & areas_int(:), & & scalardata(:,:), & & vectordata(:,:,:) character(len=256) :: scalarstring(3), vectorstring(1) integer, allocatable :: vis2int(:) double complex, allocatable :: eigw_vis(:), eigw_vis_all(:) integer :: curid, nbands, nroots(19), lmid(inc%nrootmax,19), lmroot(inc%nrootmax,19) double precision :: kverts(3,8),& & kends(3,2),& & kmidcube(3),& & kroot_in_cube(3,inc%nrootmax,19),& & ktriangle(3,3),& & kroot_lm_tet(3,nkpmax) ! nkpmax >> (3 intersections per triangle) * (2 triangles per tetrahedron) * (6 tetrahedra) x ! (multiplication-factor for splitting the triangle if BZ-face is crossed) double complex :: eigw_lm_tet(nkpmax),& & eigw_triangle(3) double complex, allocatable :: LVroot(:,:,:,:), & & RVroot(:,:,:,:), & & eigwroot(:,:,:) double precision :: ksub(3,nsteps+1) double complex :: eigwends(2,inc%nrootmax,19) integer :: iproblems, icubeproblems(2,10*nmarked/nranks), iproblems_tmpa(0:nranks-1), iproblems_tot integer, allocatable :: icubeproblems_all(:,:) integer :: ioff, nkpt, ntot_pT(0:nranks-1), ioff_pT(0:nranks-1), lb, ub integer :: ierr, ii, ivc, icub, itmp, itet, iedge, itetedge, itetroot,& & icount, iedge1, iedge2, iroot1, iroot2, lm0, lm1, lm2, & & nfound_band, nfound_tet, lookup_tet(2,4), iverts_picked(4),& & sorted(4), sorted_tmp(4), i4edge(4), i4tet(4), isave, & & kcounter_lm, kcounter_cub, printstep, itmparr(1) double precision :: dtmp_ri(4), dist(nkpmax), weight_lm double complex :: eigw_picked(4) logical :: match character(len=256) :: filename integer, parameter :: iofile=69821 ! write(*,*) 'in sub find_intesection_triangles, myrank=',myrank !Parallelize call distribute_linear_on_tasks(nranks,myrank,master,nmarked,ntot_pT,ioff_pT,.true.) nkpt = ntot_pT(myrank) ioff = ioff_pT(myrank) !initialize icubeproblems = 0 iproblems = 0 npoints_vis = 0 !allocate arrays allocate( LVroot(inc%almso,inc%almso,inc%nrootmax,19),& & RVroot(inc%almso,inc%almso,inc%nrootmax,19),& & eigwroot(inc%almso,inc%nrootmax,19), & & STAT=ierr ) if(ierr/=0) stop 'Problem allocating LVroot etc. in find_intesection_triangles' allocate(kpoints_vis(3,200*nkpt), eigw_vis(200*nkpt), kpoints_int(3,20*nkpt), areas_int(20*nkpt), vis2int(200*nkpt), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_vis etc.' !print header of statusbar if(myrank==master) write(*,'("Loop over cubes: |",5(1X,I2,"%",5X,"|"),1X,I3,"%")') 0, 20, 40, 60, 80, 100 printstep = nkpt/50 if(printstep==0) printstep=1 #ifdef CPP_DEBUG write(filename,fmt_fn_rank_ext) filename_outinfo, myrank, ext_formatted open(unit=iofile, file=trim(filename), action='write', form='formatted') #endif #ifdef CPP_DEBUG if(myrank==master) call cubes2VTK('testcubes.vtp',nCub3,nmarked,imarked,bounds) write(iofile,'(A,4I8)') 'nCub3, nmarked=', nCub3, nmarked write(iofile,'(A,3ES18.9)') 'bounds(:,1)=', bounds(:,1) write(iofile,'(A,3ES18.9)') 'bounds(:,2)=', bounds(:,2) write(iofile,'(A,16I8)') 'ntot_pT', ntot_pT write(iofile,'(A,16I8)') 'ioff_pT', ioff_pT write(iofile,'(A,2I8)') 'nkpt, ioff=', nkpt, ioff write(iofile,'(A)') 'imarked:' write(iofile,'(20I8)') imarked #endif !**************************************! !************* B E G I N **************! !**************************************! !*** (parallelized) loop over cubes ***! !**************************************! if(myrank==master) write(*,FMT=190) !beginning of statusbar kcounter_cub=0 areas_int = 0d0 do icub=1,nkpt !update statusbar if(mod(icub,printstep)==0 .and. myrank==master) write(*,FMT=200) #ifdef CPP_TIMING if (icub==1) call timing_start(' FS 3D - find FS intersections - time1') if (icub==1) call timing_start(' FS 3D - find FS intersections - time10') #endif ! write(iofile,'(A,I0)') 'starting cube ', imarked(icub+ioff) call generate_cubevertices(nCub3,imarked(icub+ioff), bounds, kverts) !find middle point of the cube kmidcube = (kverts(:,1)+kverts(:,8))/2 #ifdef CPP_DEBUG write(iofile,'(2X,"kverts(:,i)= ",3ES18.9)') kverts #endif !==================================! !=== find roots along the edges ===! !==================================! do iedge=1,19 !pick k-points kends(:,1) = kverts(:,cubedges(1,iedge)) kends(:,2) = kverts(:,cubedges(2,iedge)) call roots_along_edge( inc, lattice, cluster, tgmatrx, nsteps, kends, niter,& & roottype, rooteps, nroots(iedge), lmroot(:,iedge), & & kroot_in_cube(:,:,iedge), LVroot(:,:,:,iedge), & ! & RVroot(:,:,:,iedge), eigwroot(:,:,iedge), 500+iedge, & & RVroot(:,:,:,iedge), eigwroot(:,:,iedge), -1, & & eigwends(:,:,iedge) ) end do!iedge #ifdef CPP_TIMING if (icub==1) call timing_stop(' FS 3D - find FS intersections - time1') if (icub==10) call timing_stop(' FS 3D - find FS intersections - time10') #endif #ifdef CPP_DEBUG write(iofile,'(2X,"#roots found on the edges:")') do iedge=1,19 write(iofile,'(4X,"iedge= ",I0,", # = ",I0)') iedge, nroots(iedge) end do #endif !======================================================! !=== determine which kroots belong to the same band ===! !======================================================! lmid=0 ! the array lmid(iroot,iedge) will contain a unique id to which band a k-point belongs. curid=0 do iedge1=1,19 do iroot1=1,nroots(iedge1) !pick a first root lm1 = lmroot(iroot1,iedge1) if(lmid(iroot1,iedge1)>0) cycle !this root has already an ID curid = curid+1 lmid(iroot1,iedge1)=curid #ifdef CPP_DEBUG write(iofile,'(4X,"Set (iedge,iroot)=( ",I0,",",I0,") to curid= ",I0)') iedge1, iroot1, curid #endif ! write(*,'("Next cur-id= ",I0)'), curid !compare to all other roots on different edges which are not yet treated loop3: do iedge2=iedge1+1,19 loop4: do iroot2=1,nroots(iedge2) if(lmid(iroot2,iedge2)>0) cycle lm2 = lmroot(iroot2,iedge2) kends(:,1) = kroot_in_cube(:,iroot1,iedge1) kends(:,2) = kroot_in_cube(:,iroot2,iedge2) call compare_two_eigv_in_substeps( inc, lattice, cluster, tgmatrx, nsteps,& & kends, lm1, LVroot(:,:,iroot1,iedge1), & & RVroot(:,lm2,iroot2,iedge2), & & eigwroot(lm2,iroot2,iedge2), match ) #ifdef CPP_DEBUG write(iofile,'(6X,"Compare (iedge,iroot)=( ",I0,",",I0,") with (iedge,iroot)=( ",I0,",",I0,"), matching=",L1)') iedge1, iroot1, iedge2, iroot2, match #endif if(match) then lmid(iroot2,iedge2)=curid cycle loop3 end if!match end do loop4!iroot2 end do loop3!iedge2 end do!iroot1 end do!iedge1 nbands = curid #ifdef CPP_DEBUG write(iofile,'(2X,A)') 'LM-check' do iedge=1,19 write(iofile,'(4X,"iedge= ",I0," - ",20I8)') iedge, lmid(1:nroots(iedge),iedge) end do!iedge write(iofile,'(2X,A,I0)') 'nbands= ', nbands #endif ! !delete multiple bands on the same edge ! do lm0=1,nbands ! do iedge1=1,19 ! itmp=0 ! do iroot1=1,nroots(iedge1) ! if(lmid(iroot1,iedge1)==lm0) itmp=itmp+1 ! if(lmid(iroot1,iedge1)==lm0 .and. itmp>1) lmid(iroot1,iedge1)=0 ! end do ! end do ! end do!lm0 ! write(*,*) 'LM-check 2' ! do iedge=1,19 ! write(*,'(4X,"iedge= ",I0," - ",20I8)') iedge, lmid(1:nroots(iedge),iedge) ! end do!iedge !==========================================! !=== scan the tetrahedra for each band ===! !=== and find the triangles and areas ===! !==========================================! #ifdef CPP_DEBUG write(iofile,'(2X,A)') 'Scan all bands ands tetraheda' #endif !loop over all bands do lm0=1,nbands kcounter_lm=0 !scan all tetrahedra do itet=1,6 #ifdef CPP_DEBUG write(iofile,'(4X,2(A,I0))') 'lm0= ', lm0, ', itet= ', itet #endif nfound_tet = 0 !find all roots belonging to this this tetrahedron and this band edgeloop: do iedge1=1,6 itetedge = tetedges(iedge1,itet) ! write(*,'(20(A,I0))') 'itetedge= ', itetedge, ', #roots=', nroots(itetedge) do iroot1=1,nroots(itetedge) if(lmid(iroot1,itetedge)==lm0)then nfound_tet = nfound_tet+1 if(nfound_tet>4)then #ifdef CPP_DEBUG write(iofile,'(I0,A)') imarked(icub+ioff), ' =imarked: more than 4 intersections of band with tetrahedron --> skip' #endif iproblems = iproblems+1 icubeproblems(1,iproblems) = imarked(icub+ioff) icubeproblems(2,iproblems) = 1 nfound_tet=0 exit edgeloop end if lookup_tet(:,nfound_tet) = (/ iroot1, itetedge /) end if end do!iroot1 end do edgeloop!iedge1 #ifdef CPP_DEBUG write(iofile,'(6X,A,I0)') 'nfound_tet= ', nfound_tet #endif select case ( nfound_tet ) case( 0 ); cycle case( 3 ) !store the triangle k-points ktriangle(:,1) = kroot_in_cube(:,lookup_tet(1,1),lookup_tet(2,1)) ktriangle(:,2) = kroot_in_cube(:,lookup_tet(1,2),lookup_tet(2,2)) ktriangle(:,3) = kroot_in_cube(:,lookup_tet(1,3),lookup_tet(2,3)) eigw_triangle(1) = eigwroot(lmroot(lookup_tet(1,1),lookup_tet(2,1)),lookup_tet(1,1),lookup_tet(2,1)) eigw_triangle(2) = eigwroot(lmroot(lookup_tet(1,2),lookup_tet(2,2)),lookup_tet(1,2),lookup_tet(2,2)) eigw_triangle(3) = eigwroot(lmroot(lookup_tet(1,3),lookup_tet(2,3)),lookup_tet(1,3),lookup_tet(2,3)) !split triangle if BZ-face is crossed call split_triangle(ktriangle, eigw_triangle, kroot_lm_tet(:,:), eigw_lm_tet(:), kcounter_lm, nfaces, nvec, dscal) !cccccccc kroot_lm_tet(:,kcounter_lm+1:kcounter_lm+3) = ktriangle !cccccccc kcounter_lm = kcounter_lm+3 case( 4 ) !pick the eigenvalues at the four vertices of the tetrahedron icount = 0 iverts_picked = 0 eigw_picked = (0d0, 0d0) do iedge=1,4 itetroot = lookup_tet(1,iedge) itetedge = lookup_tet(2,iedge) do ii=1,2 ivc = cubedges(ii,itetedge) if(any(iverts_picked==ivc)) cycle icount = icount+1 iverts_picked(icount) = ivc eigw_picked(icount) = eigwends(ii,itetroot,itetedge) end do!ii end do if(icount>4) stop 'icount>4 sould not happen' #ifdef CPP_DEBUG write(iofile,'(6X,"iverts_picked= ",4I8)') iverts_picked write(iofile,'(8X,"eigws_picked= ",2ES18.9)') eigw_picked write(iofile,'(6X,A)') 'Test-eigws:' do iedge=1,4 itetroot = lookup_tet(1,iedge) itetedge = lookup_tet(2,iedge) do ii=1,2 write(iofile,'(8X,A,I0,A,I0,A,2ES18.9)') 'itetedge=',itetedge,', icorner=', cubedges(ii,itetedge),& & ', eigw= ', eigwends(ii,itetroot,itetedge) end do!ii end do!iedge #endif select case (roottype) case(ROOT_REAL); dtmp_ri = dble(eigw_picked) case(ROOT_IMAG); dtmp_ri = aimag(eigw_picked) case default; stop 'option not known: only real/imag' end select!roottype !sort the values call bubblesort(4, dtmp_ri, sorted_tmp) do ii=1,4 sorted(ii) = iverts_picked(sorted_tmp(ii)) end do i4edge(1) = get_edgeindex(sorted(1),sorted(3)) i4edge(2) = get_edgeindex(sorted(1),sorted(4)) i4edge(3) = get_edgeindex(sorted(2),sorted(3)) i4edge(4) = get_edgeindex(sorted(2),sorted(4)) !reorder the indices icount=0 i4tet =0 do ii=1,4 do iedge=1,4 if(i4edge(ii)==lookup_tet(2,iedge))then icount = icount+1 i4tet(icount) = iedge end if end do!iedge end do!ii if(any(i4tet==0) .or. any(i4tet>4))then #ifdef CPP_DEBUG write(iofile,'(I0,A)') imarked(icub+ioff), ' =imarked: it does not hold (1 <= i4tet(ii) <= 4) --> skip' #endif iproblems = iproblems+1 icubeproblems(1,iproblems) = imarked(icub+ioff) icubeproblems(2,iproblems) = 2 cycle end if !store the first triangle k-points ktriangle(:,1) = kroot_in_cube(:,lookup_tet(1,i4tet(1)),lookup_tet(2,i4tet(1))) ktriangle(:,2) = kroot_in_cube(:,lookup_tet(1,i4tet(2)),lookup_tet(2,i4tet(2))) ktriangle(:,3) = kroot_in_cube(:,lookup_tet(1,i4tet(3)),lookup_tet(2,i4tet(3))) eigw_triangle(1) = eigwroot(lmroot(lookup_tet(1,1),lookup_tet(2,1)),lookup_tet(1,1),lookup_tet(2,1)) eigw_triangle(2) = eigwroot(lmroot(lookup_tet(1,2),lookup_tet(2,2)),lookup_tet(1,2),lookup_tet(2,2)) eigw_triangle(3) = eigwroot(lmroot(lookup_tet(1,3),lookup_tet(2,3)),lookup_tet(1,3),lookup_tet(2,3)) !split triangle if BZ-face is crossed call split_triangle(ktriangle, eigw_triangle, kroot_lm_tet(:,:), eigw_lm_tet(:), kcounter_lm, nfaces, nvec, dscal) !cccccccc kroot_lm_tet(:,kcounter_lm+1:kcounter_lm+3) = ktriangle !cccccccc kcounter_lm = kcounter_lm+3 !store the second triangle k-points ktriangle(:,1) = kroot_in_cube(:,lookup_tet(1,i4tet(2)),lookup_tet(2,i4tet(2))) ktriangle(:,2) = kroot_in_cube(:,lookup_tet(1,i4tet(3)),lookup_tet(2,i4tet(3))) ktriangle(:,3) = kroot_in_cube(:,lookup_tet(1,i4tet(4)),lookup_tet(2,i4tet(4))) eigw_triangle(1) = eigwroot(lmroot(lookup_tet(1,2),lookup_tet(2,2)),lookup_tet(1,2),lookup_tet(2,2)) eigw_triangle(2) = eigwroot(lmroot(lookup_tet(1,3),lookup_tet(2,3)),lookup_tet(1,3),lookup_tet(2,3)) eigw_triangle(3) = eigwroot(lmroot(lookup_tet(1,4),lookup_tet(2,4)),lookup_tet(1,4),lookup_tet(2,4)) !split triangle if BZ-face is crossed call split_triangle(ktriangle, eigw_triangle, kroot_lm_tet(:,:), eigw_lm_tet(:), kcounter_lm, nfaces, nvec, dscal) !cccccccc kroot_lm_tet(:,kcounter_lm+1:kcounter_lm+3) = ktriangle !cccccccc kcounter_lm = kcounter_lm+3 case default #ifdef CPP_DEBUG write(iofile,'(I0,A)') imarked(icub+ioff), ' =imarked: neither 3 nor 4 intesections found for --> skip' #endif iproblems = iproblems+1 icubeproblems(1,iproblems) = imarked(icub+ioff) icubeproblems(2,iproblems) = 3 end select end do!itet !if cube is empty, proceed to next cube if(kcounter_lm==0) cycle !==============================! !=== Find the k-point and ===! !=== weight for integration ===! !==============================! !update the counter for integration k-points kcounter_cub = kcounter_cub+1 !find kpoint-index representing this cube do ii=1,kcounter_lm dist(ii) = sum((kroot_lm_tet(:,ii) - kmidcube)**2) end do call findminindex(kcounter_lm, dist(1:kcounter_lm), isave) !save the k-point kpoints_int(:,kcounter_cub) = kroot_lm_tet(:,isave) !find the weight of the representing cube (=area of all triangles) weight_lm = 0d0 do ii=1,kcounter_lm/3 weight_lm = weight_lm + area_triangle(kroot_lm_tet(:,ii*3-2:ii*3)) end do!ii areas_int(kcounter_cub) = weight_lm !if weight for this triangle is negligible, forget this k-point if(abs(weight_lm)<1d-16) kcounter_cub = kcounter_cub - 1 !=================================! !=== Store the visualization ===! !=== information in temp array ===! !=================================! !add the visualization-triangles to the temporary storage array kpoints_vis(:,npoints_vis+1:npoints_vis+kcounter_lm) = kroot_lm_tet(:,1:kcounter_lm) eigw_vis(npoints_vis+1:npoints_vis+kcounter_lm) = eigw_lm_tet(1:kcounter_lm) vis2int(npoints_vis+1:npoints_vis+kcounter_lm) = kcounter_cub npoints_vis = npoints_vis + kcounter_lm end do!lm0 end do!icub if(myrank==master) write(*,*) '' !**************************************! !*** (parallelized) loop over cubes ***! !**************************************! !*************** E N D ****************! !**************************************! !*************************************! !************* B E G I N *************! !*************************************! !*** collect the problematic cubes ***! !*************************************! #ifdef CPP_MPI !collect the numbers of problematic arrays call MPI_Allgather( iproblems, 1, MPI_INTEGER, & & iproblems_tmpa, 1, MPI_INTEGER, & & MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgather npoints_vis_glob' iproblems_tot = sum(iproblems_tmpa) allocate(icubeproblems_all(2,iproblems_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating icubeproblems_all' !calculate offsets ioffs_tmpa=0 do irank=1,nranks-1 ioffs_tmpa(irank) = ioffs_tmpa(irank-1)+iproblems_tmpa(irank-1) end do!irank ioffs_save = ioffs_tmpa !collect the problematic cubes isendarr = 2*iproblems_tmpa ioffsarr = 2*ioffs_tmpa call MPI_Allgatherv( icubeproblems, isendarr(myrank), MPI_INTEGER, & & icubeproblems_all, isendarr, ioffsarr, & & MPI_INTEGER, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv icubeproblems' #else iproblems_tot = iproblems allocate(icubeproblems_all(2,iproblems_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating icubeproblems_all' icubeproblems_all = icubeproblems(:,1:iproblems_tot) #endif #ifndef CPP_DEBUG if(myrank==master)then write(filename,fmt_fn_rank_ext) filename_outinfo, myrank, ext_formatted open(unit=13512, file=trim(filename), action='write', form='formatted') do ii=1,iproblems_tot select case (icubeproblems_all(2,ii)) case(1); write(13512,'(I0,A)') icubeproblems_all(1,ii), ' =imarked: more than 4 intersections of band with tetrahedron --> skip' case(2); write(13512,'(I0,A)') icubeproblems_all(1,ii), ' =imarked: it does not hold (1 <= i4tet(ii) <= 4) --> skip' case(3); write(13512,'(I0,A)') icubeproblems_all(1,ii), ' =imarked: neither 3 nor 4 intesections found for --> skip' case default; write(13512,'(I0,A,I0,A)') icubeproblems_all(1,ii), ' =imarked: identifier ', icubeproblems_all(2,ii), ' not known' end select end do!ii close(13512) end if!myrank==master #endif !*************************************! !*** collect the problematic cubes ***! !*************************************! !************** E N D ****************! !*************************************! !************************************! !************ B E G I N *************! !************************************! !*** output of visualization data ***! !************************************! #ifdef CPP_MPI !collect the number of points call MPI_Allgather( npoints_vis, 1, MPI_INTEGER, & & npoints_vis_tmpa, 1, MPI_INTEGER, & & MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgather npoints_vis_glob' npoints_vis_tot = sum(npoints_vis_tmpa) ioffs_tmpa=0 do irank=1,nranks-1 ioffs_tmpa(irank) = ioffs_tmpa(irank-1)+npoints_vis_tmpa(irank-1) end do!irank ioffs_save = ioffs_tmpa !allocate result arrays allocate(kpoints_vis_all(3,npoints_vis_tot), eigw_vis_all(npoints_vis_tot), vis2int_all(npoints_vis_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_vis_all etc.' !collect the k-points isendarr = 3*npoints_vis_tmpa ioffsarr = 3*ioffs_tmpa call MPI_Allgatherv( kpoints_vis, isendarr(myrank), MPI_DOUBLE_PRECISION,& & kpoints_vis_all, isendarr, ioffsarr, & & MPI_DOUBLE_PRECISION, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv kpoints_vis_glob' !collect the eigenvalues isendarr = npoints_vis_tmpa ioffsarr = ioffs_tmpa call MPI_Allgatherv( eigw_vis, isendarr(myrank), MPI_DOUBLE_COMPLEX,& & eigw_vis_all, isendarr, ioffsarr, & & MPI_DOUBLE_COMPLEX, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv eigv_vis_glob' !collect the translation array isendarr = npoints_vis_tmpa ioffsarr = ioffs_tmpa call MPI_Allgatherv( vis2int, isendarr(myrank), MPI_INTEGER, & & vis2int_all, isendarr, ioffsarr, & & MPI_INTEGER, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv vis2int_glob' !adapt the offsets for the translation array --> done below (!!!!!) #else npoints_vis_tot = npoints_vis allocate(kpoints_vis_all(3,npoints_vis_tot), eigw_vis_all(npoints_vis_tot), vis2int_all(npoints_vis_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_vis_all etc.' kpoints_vis_all = kpoints_vis(:,1:npoints_vis_tot) eigw_vis_all = eigw_vis(1:npoints_vis_tot) vis2int_all = vis2int(1:npoints_vis_tot) #endif deallocate( kpoints_vis, eigw_vis, STAT=ierr ) if(ierr/=0) stop 'Problem deallocating kpoints_vis etc.' if(myrank==master)then allocate(scalardata(npoints_vis_tot,3)) scalardata(:,1) = abs(eigw_vis_all) scalardata(:,2) = dble(eigw_vis_all) scalardata(:,3) = aimag(eigw_vis_all) scalarstring(1) = 'eigw_abs' scalarstring(2) = 'eigw_real' scalarstring(3) = 'eigw_imag' write(filename,fmt_fn_ext) filename_vtktest, ext_vtkxml itmparr(1) = 1 ! write(*,*) 'prepare fstest with nsym=1.. done' call write_pointdata_rot( trim(filename),npoints_vis_tot,kpoints_vis_all, & & 3,scalardata,scalarstring, & & 0,vectordata,vectorstring, & & 1,symmetries%rotmat, itmparr ) ! write(*,*) 'write fstest with nsym=1.. done' write(filename,fmt_fn_sub_ext) filename_vtktest, filemode_rot, ext_vtkxml call write_pointdata_rot( trim(filename),npoints_vis_tot,kpoints_vis_all, & & 3,scalardata,scalarstring,& & 0,vectordata,vectorstring,& & symmetries%nsym_used,symmetries%rotmat, & & symmetries%isym_used) ! write(*,*) 'write fstest with nsym=48.. done' end if!myrank==master !************************************! !*** output of visualization data ***! !************************************! !************** E N D ***************! !************************************! !*************************************! !************ B E G I N **************! !*************************************! !*** gathering of integration data ***! !*************************************! #ifdef CPP_MPI !collect the number of points call MPI_Allgather( kcounter_cub, 1, MPI_INTEGER, & & npoints_int_tmpa, 1, MPI_INTEGER, & & MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgather npoints_int_tmpa' npoints_int_tot = sum(npoints_int_tmpa) ioffs_tmpa=0 do irank=1,nranks-1 ioffs_tmpa(irank) = ioffs_tmpa(irank-1)+npoints_int_tmpa(irank-1) end do!irank !allocate result arrays allocate(kpoints_int_all(3,npoints_int_tot), areas_int_all(npoints_int_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_int_all etc.' !collect the k-points isendarr = 3*npoints_int_tmpa ioffsarr = 3*ioffs_tmpa call MPI_Allgatherv( kpoints_int, isendarr(myrank), MPI_DOUBLE_PRECISION,& & kpoints_int_all, isendarr, ioffsarr, & & MPI_DOUBLE_PRECISION, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv kpoints_int_all' !collect the areas isendarr = npoints_int_tmpa ioffsarr = ioffs_tmpa call MPI_Allgatherv( areas_int, isendarr(myrank), MPI_DOUBLE_PRECISION,& & areas_int_all, isendarr, ioffsarr, & & MPI_DOUBLE_PRECISION, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in allgatherv kpoints_int_all' !adapt the offsets for the translation array --> from above (!!!!!) do irank=1,nranks-1 lb = ioffs_save(irank)+1 ub = ioffs_save(irank)+npoints_vis_tmpa(irank) vis2int_all(lb:ub) = vis2int_all(lb:ub) + ioffs_tmpa(irank) end do!irank #else npoints_int_tot = kcounter_cub allocate(kpoints_int_all(3,npoints_int_tot), areas_int_all(npoints_int_tot), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_int_all etc.' kpoints_int_all = kpoints_int(:,1:npoints_int_tot) areas_int_all = areas_int(1:npoints_int_tot) #endif ! write(iofile,'(2(A,ES18.9))') 'Test: sum of areas on all tasks=', sum(areas_int_all) ! write(iofile,'(2(A,ES18.9))') 'Test: sum of areas on this task=', sum(areas_int) close(iofile) 190 FORMAT(' |'$) 200 FORMAT('|'$) end subroutine find_intesection_triangles subroutine cut_and_update_cubes(ncut, nCub3, nmarked, imarked) use mod_fermisurf_basic, only: unroll_ixyz implicit none integer, intent(in) :: ncut integer, intent(inout) :: nCub3(3) integer, intent(inout) :: nmarked integer, allocatable, intent(inout) :: imarked(:) integer :: nCub3in(3), nmarked_tmp, imarked_tmp(nmarked) integer :: ii3(3), ix, iy, iz, icub, icount, ierr !save input to temporary arrays nCub3in = nCub3 nmarked_tmp = nmarked imarked_tmp = imarked deallocate(imarked) !determine size of output-array nmarked = nmarked_tmp * ncut**3 allocate( imarked(nmarked), STAT=ierr ) if(ierr/=0) stop 'Problem allocating imarked in "cut_and_update_cubes"' nCub3 = nCub3in*ncut icount = 0 do icub=1,nmarked_tmp call unroll_ixyz(imarked_tmp(icub), nCub3in, ii3) do iz=0,ncut-1 do iy=0,ncut-1 do ix=0,ncut-1 icount = icount+1 imarked(icount) = (ii3(1)*ncut+ix+1) + (ii3(2)*ncut+iy)*nCub3(1) + (ii3(3)*ncut+iz)*product(nCub3(1:2)) end do!ix end do!iy end do!iz end do!icub end subroutine cut_and_update_cubes subroutine mark_cubes_FScrossold(inc, lattice, cluster, tgmatrx, nCub3, nsteps, bounds, roottype, rooteps, nmarked, imarked) use type_inc, only: inc_type use type_data, only: lattice_type, cluster_type, tgmatrx_type use mod_parutils, only: distribute_linear_on_tasks use mod_mympi, only: myrank, nranks, master use mod_fermisurf_basic, only: connect_eigw_in_substeps, find_roots_any_eigw, generate_cubevertices #ifdef CPP_MPI use mpi #endif implicit none type(inc_type), intent(in) :: inc type(lattice_type), intent(in) :: lattice type(cluster_type), intent(in) :: cluster type(tgmatrx_type), intent(in) :: tgmatrx integer, intent(in) :: nCub3(3), nsteps double precision, intent(in) :: bounds(3,2) integer, intent(in) :: roottype double precision, intent(in) :: rooteps integer, intent(inout) :: nmarked integer, allocatable, intent(inout) :: imarked(:) integer :: ncubmarked_tmp, ioff, nkpt, ntot_pT(0:nranks-1), ioff_pT(0:nranks-1) integer :: ncubmarked_pT(0:nranks-1), iioff(0:nranks-1) double precision :: kverts(3,8) integer, allocatable :: icubmarked_tmp(:) integer :: connection(inc%almso,nsteps+1) double precision :: ksub(3,nsteps+1), kends(3,2) double complex :: LVeig(inc%almso,inc%almso,nsteps+1),& & RVeig(inc%almso,inc%almso,nsteps+1),& & eigw(inc%almso,nsteps+1) integer :: iedge, irank, icub, ierr logical :: edgeroot(19) !Parallelize call distribute_linear_on_tasks(nranks,myrank,master, nmarked, ntot_pT, ioff_pT, .false.) nkpt = ntot_pT(myrank) ioff = ioff_pT(myrank) !Create temp arrays allocate(icubmarked_tmp(nkpt), STAT=ierr) if(ierr/=0) stop 'Problem allocating icubmarked_tmp in mark_cubes_FScross' ncubmarked_tmp = 0 icubmarked_tmp = -1 !Test whether cubes cross FS do icub=1,nkpt if(mod(icub,10)==0 .and. myrank==master) write(*,"(2X,F8.3,A)") dble(icub)/nkpt*100, ' percent done' call generate_cubevertices(nCub3,imarked(icub+ioff), bounds, kverts) do iedge=1,4 kends(:,1) = kverts(:,tetdiags(1,iedge)) kends(:,2) = kverts(:,tetdiags(2,iedge)) call connect_eigw_in_substeps( inc, lattice, cluster, tgmatrx, nsteps, kends, & & connection, ksub, eigw, LVeig, RVeig ) call find_roots_any_eigw( inc%almso, nsteps, connection, eigw, & & roottype, rooteps, edgeroot(iedge) ) end do!iedge if(any(edgeroot))then ncubmarked_tmp = ncubmarked_tmp + 1 icubmarked_tmp(ncubmarked_tmp) = imarked(icub+ioff) end if!l_cut end do!icub deallocate(imarked) #ifdef CPP_MPI !Combine results call MPI_Allgather(ncubmarked_tmp, 1, MPI_INTEGER, ncubmarked_pT, 1, MPI_INTEGER, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in Allgather(ncubmarked_tmp) in mark_cubes_FScross' nmarked = sum(ncubmarked_pT) allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in mark_cubes_FScross' iioff = 0 do irank=1,nranks-1 iioff(irank) = sum(ncubmarked_pT(0:irank-1)) end do call MPI_Allgatherv( icubmarked_tmp, ncubmarked_tmp, MPI_INTEGER, & & imarked, ncubmarked_pT, iioff, MPI_INTEGER, & & MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in Allgatherv(icubmarked_tmp) in mark_cubes_FScross' #else nmarked=ncubmarked_tmp allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in mark_cubes_FScross' imarked = icubmarked_tmp(1:ncubmarked_tmp) #endif end subroutine mark_cubes_FScrossold subroutine mark_cubes_in_IBZ(nCub3, nfaces, nvec, dscal, bounds, nmarked, imarked) use mod_parutils, only: distribute_linear_on_tasks use mod_mympi, only: myrank, nranks, master use mod_symmetries, only: points_in_wedge use mod_fermisurf_basic, only: generate_cubevertices #ifdef CPP_MPI use mpi #endif implicit none integer, intent(in) :: nCub3(3), nfaces double precision, intent(in) :: nvec(3,nfaces), dscal(nfaces), bounds(3,2) integer, intent(inout) :: nmarked integer, allocatable, intent(inout) :: imarked(:) integer :: ncubmarked_tmp, ioff, nkpt, ntot_pT(0:nranks-1), ioff_pT(0:nranks-1) integer :: ncubmarked_pT(0:nranks-1), iioff(0:nranks-1) double precision :: kverts(3,8) integer, allocatable :: icubmarked_tmp(:) integer :: irank, icub, ierr logical :: cubeinwedge !Parallelize call distribute_linear_on_tasks(nranks,myrank,master, nmarked, ntot_pT, ioff_pT, .false.) nkpt = ntot_pT(myrank) ioff = ioff_pT(myrank) !Create temp arrays allocate(icubmarked_tmp(nkpt), STAT=ierr) if(ierr/=0) stop 'Problem allocating icubmarked_tmp in mark_cubes_in_IBZ' ncubmarked_tmp = 0 icubmarked_tmp = -1 !Test whether cubes lie in wedge do icub=1,nkpt call generate_cubevertices(nCub3,imarked(icub+ioff),bounds,kverts) cubeinwedge = points_in_wedge(nfaces, nvec, dscal, 8, kverts, 'any') if(cubeinwedge)then ncubmarked_tmp = ncubmarked_tmp + 1 icubmarked_tmp(ncubmarked_tmp) = imarked(icub+ioff) end if!cubeinwedge end do!icub deallocate(imarked) #ifdef CPP_MPI !Combine results call MPI_Allgather(ncubmarked_tmp, 1, MPI_INTEGER, ncubmarked_pT, 1, MPI_INTEGER, MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in Allgather(ncubmarked_tmp) in mark_cubes_in_IBZ' nmarked = sum(ncubmarked_pT) allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in mark_cubes_in_IBZ' iioff = 0 do irank=1,nranks-1 iioff(irank) = sum(ncubmarked_pT(0:irank-1)) end do call MPI_Allgatherv( icubmarked_tmp, ncubmarked_tmp, MPI_INTEGER, & & imarked, ncubmarked_pT, iioff, MPI_INTEGER, & & MPI_COMM_WORLD, ierr ) if(ierr/=MPI_SUCCESS) stop 'Problem in Allgatherv(icubmarked_tmp) in mark_cubes_in_IBZ' #else nmarked=ncubmarked_tmp allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in mark_cubes_in_IBZ' imarked = icubmarked_tmp(1:ncubmarked_tmp) #endif end subroutine mark_cubes_in_IBZ subroutine cubes2VTK(filename,nCub3,nmarked,imarked,bounds) use mod_fermisurf_basic, only: generate_cubevertices 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 init_cube2tetralines() ! A cube is cut into 6 tetrahedra. ! - itetcorner(j,i) is the corner-index of the cube of the jth corner of the ith tetrahedron. ! - lines(1,l) and lines(2,l) contains the cube-index of the ! start- and end-points of the l-th edge of the tetrahedron in this triangle. ! - itetlines(l,i) is the lth edge of the ith tetrahedron integer :: itet tetdiags = reshape( (/ 1, 8, 2, 7, 3, 6, 4, 5 /), (/ 2,4 /)) ! do ii=1,4 ! write(*,*) 't', tetdiags(:,ii) ! end do!ii !define the endpoints of the edges of the tetraeda. cubedge(1,j) = k means: !the startpoint of the j-th edge is the k-th corner-point of the cube cubedges(:,1) = (/ 1, 2 /) !\ cubedges(:,2) = (/ 1, 3 /) ! \ = the 4 cube-edges in the base cubedges(:,3) = (/ 2, 4 /) ! / cubedges(:,4) = (/ 3, 4 /) !/ cubedges(:,5) = (/ 1, 5 /) !\ cubedges(:,6) = (/ 2, 6 /) ! \ = the 4 cube-edges from the base to the top cubedges(:,7) = (/ 3, 7 /) ! / cubedges(:,8) = (/ 4, 8 /) !/ cubedges(:,9) = (/ 5, 6 /) !\ cubedges(:,10) = (/ 5, 7 /) ! \ = the 4 cube-edges in the top cubedges(:,11) = (/ 6, 8 /) ! / cubedges(:,12) = (/ 7, 8 /) !/ cubedges(:,13) = (/ 1, 4 /) !\ cubedges(:,14) = (/ 1, 6 /) ! \ cubedges(:,15) = (/ 1, 7 /) ! \ = the diagonals along the 6 faces cubedges(:,16) = (/ 2, 8 /) ! / cubedges(:,17) = (/ 3, 8 /) ! / cubedges(:,18) = (/ 5, 8 /) !/ cubedges(:,19) = (/ 1, 8 /) ! = diagonal across the cube tetcorners(:,1) = (/ 1, 2, 4, 8 /) tetcorners(:,2) = (/ 1, 3, 4, 8 /) tetcorners(:,3) = (/ 1, 2, 6, 8 /) tetcorners(:,4) = (/ 1, 5, 6, 8 /) tetcorners(:,5) = (/ 1, 3, 7, 8 /) tetcorners(:,6) = (/ 1, 5, 7, 8 /) do itet=1,6 tetedges(:,itet) = get_tedges(tetcorners(:,itet)) end do end subroutine init_cube2tetralines function get_tedges(tcorners) result(tedges) integer, intent(in) :: tcorners(4) integer :: tedges(6) integer :: ii, jj, icount, iedge, pair(2) !loop over pairs icount=0 iloop: do ii=1,3 jloop: do jj=ii+1,4 icount = icount+1 !order the pair if(tcorners(ii)<tcorners(jj))then pair = (/ tcorners(ii), tcorners(jj) /) else pair = (/ tcorners(jj), tcorners(ii) /) end if do iedge=1,19 if(all( pair == cubedges(:,iedge) ))then tedges(icount) = iedge cycle jloop end if end do stop 'edge not found' end do jloop end do iloop end function get_tedges integer function get_edgeindex(icorner1, icorner2) integer, intent(in) :: icorner1, icorner2 integer :: ivc(2), iout, iedge if(icorner1<icorner2)then ivc(1)=icorner1 ivc(2)=icorner2 else ivc(1)=icorner2 ivc(2)=icorner1 end if iout=0 do iedge=1,19 if(all(ivc==cubedges(:,iedge)))then iout=iedge exit end if end do #ifdef DEBUG if(iout==0) stop 'get_edgeindex: no matching case found!' #endif get_edgeindex = iout return end function get_edgeindex 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 subroutine read_cubesrefine(nCub3, nmarked, imarked) use mod_mympi, only: myrank, nranks, master use mod_ioformat, only: filename_cubesrefine, ext_formatted, fmt_fn_ext use mod_iohelp, only: get_nLines use mod_mathtools, only: bubblesort_int #ifdef CPP_MPI use mpi #endif implicit none integer, intent(out) :: nCub3(3), nmarked integer, allocatable, intent(out) :: imarked(:) integer :: ierr, ii, ipointer, iline, istart, istop, nlines, ncubsplit, nCub3in(3), icubtmp, nrefine, nmarkedtmp integer, allocatable :: imarkedtmp(:), srtidx(:), imarked2(:), imarked3(:) character(len=256) :: filename integer, parameter :: iounit=15369 if(myrank==master)then write(filename,fmt_fn_ext) filename_cubesrefine, ext_formatted open(unit=iounit, file=filename, form='formatted', action='read') ncubsplit = 0 nlines = get_nLines( iounit ) !check the input data and get total number of split cubes rewind(iounit) do iline = 1,nlines read(iounit,*) nCub3in, nrefine, icubtmp ! write(*,'(5I8)') nCub3in, nrefine, icubtmp if(iline==1) nCub3 = nCub3in*nrefine if(any(nCub3in*nrefine/=nCub3)) stop 'nCub3 not consistent in refine' ncubsplit = ncubsplit + nrefine**3 end do!iline allocate(imarked2(ncubsplit), imarked3(ncubsplit), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in readin on master' rewind(iounit) istart=1 istop =0 do iline = 1,nlines allocate(imarkedtmp(1)) nmarkedtmp = 1 read(iounit,'(5I8)') nCub3in, nrefine, imarkedtmp call cut_and_update_cubes(nrefine, nCub3in, nmarkedtmp, imarkedtmp) if(nmarkedtmp/=nrefine**3)then write(*,'(A,I0,A,I0)') 'Something went wrong. nmarkedtmp= ', nmarkedtmp, ', nrefine=', nrefine stop 'Error in read_cubesrefine' end if istop =istart-1+nrefine**3 imarked2(istart:istop) = imarkedtmp deallocate(imarkedtmp) istart=istop+1 end do!iline nmarkedtmp = istart-1 close(iounit) if(nmarkedtmp/=ncubsplit) then write(*,'(A,I0,A,I0)') 'Something went wrong. nmarkedtmp= ', nmarkedtmp, ', ncubsplit=', ncubsplit stop 'Error in read_cubesrefine' end if !sort the index and filter out double indices allocate(srtidx(ncubsplit), STAT=ierr) if(ierr/=0) stop 'Problem allocating srtidx in readin on master' call bubblesort_int(nmarkedtmp, imarked2, srtidx) imarked3 = -1 imarked3(1) = imarked2(srtidx(1)) ipointer = 1 do iline=2,nmarkedtmp if(imarked2(srtidx(iline))>imarked3(ipointer))then imarked3(ipointer+1) = imarked2(srtidx(iline)) ipointer = ipointer+1 end if end do nmarked = ipointer allocate(imarked(nmarked), STAT=ierr) imarked = imarked3(1:nmarked) ! write(666,'(I8)') nmarked, imarked end if!myrank==master #ifdef CPP_MPI call MPI_Bcast(nCub3, 3, MPI_INTEGER, master, MPI_COMM_WORLD, ierr) if(ierr/=MPI_SUCCESS) stop 'Problem in Bcast(nCub3)' call MPI_Bcast(nmarked, 1, MPI_INTEGER, master, MPI_COMM_WORLD, ierr) if(ierr/=MPI_SUCCESS) stop 'Problem in Bcast(nmarked)' if(myrank/=master)then allocate(imarked(nmarked), STAT=ierr) if(ierr/=0) stop 'Problem allocating imarked in readin on slaves' end if!myrank/=master call MPI_Bcast(imarked, nmarked, MPI_INTEGER, master, MPI_COMM_WORLD, ierr) if(ierr/=MPI_SUCCESS) stop 'Problem in Bcast(imarked)' #endif ! write(*,'("myrank=",I0," imarked=",10I8)') myrank, imarked ! write(2000+myrank,'(I8)') nmarked ! write(2000+myrank,'(10I8)') imarked end subroutine read_cubesrefine subroutine split_triangle(ktriangle, eigw_triangle, kstore, eigw_store, kcounter, nfaces, nvec, dscal) use mod_symmetries, only: singlepoint_in_wedge implicit none integer, intent(in) :: nfaces double precision, intent(in) :: ktriangle(3,3), nvec(3,nfaces), dscal(nfaces) double complex, intent(in) :: eigw_triangle(3) integer, intent(inout) :: kcounter double precision, intent(inout) :: kstore(3,nkpmax) double complex, intent(inout) :: eigw_store(nkpmax) integer :: ntri, ii, iface, itri, cutcase, its(0:2), ikp(3), nLines, nLinesINP double precision :: dtmp, ktmp1(3,nkpmax), ktmp2(3,nkpmax), denom, rscal, ki0new(3,2) double complex :: etmp1(nkpmax), etmp2(nkpmax), ei0new(2) logical :: linIBZ(3), lplane(3) double precision, parameter :: eps=1d-10 !test whether the points lie inside the IBZ do ii=1,3 linIBZ(ii) = singlepoint_in_wedge(nfaces, nvec, dscal, ktriangle(:,ii)) end do!ii !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if(all(linIBZ))then ! DISTINGUISH THE DIFFERENT CASES ! !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !the triangle lies completely inside the IBZ --> just copy do ii=1,3 kstore(:,ii+kcounter) = ktriangle(:,ii) eigw_store(ii+kcounter) = eigw_triangle(ii) end do kcounter = kcounter+3 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ elseif(any(linIBZ))then ! DISTINGUISG THE DIFFERENT CASES ! !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !the triangle lies partly in the IBZ --> cut it nLinesINP=3 ktmp1(:,1:3) = ktriangle etmp1(1:3) = eigw_triangle !===== BEGIN =====! ! loop over faces ! do iface=1,nfaces nLines=0!init counter for all triangles found ntri=nLinesINP/3 !(updated) loop over triangles do itri=1,ntri ikp(1) = 3*(itri-1)+1 ikp(2) = 3*(itri-1)+2 ikp(3) = 3*itri !check if points are inside or outside the plane lplane(:) = .true. do ii=1,3 dtmp = sum(nvec(:,iface)*ktmp1(:,ikp(ii)))-dscal(iface)+eps if(dtmp<0d0)then lplane(ii) = .false. end if!eps end do!ii !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! if(all(lplane))then ! distinguish the different cases --- part 2 ! !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! !the whole triangles lies on the corect side of the plane ktmp2(:,nLines+1:nLines+3) = ktmp1(:,ikp) etmp2(nLines+1:nLines+3) = etmp1(ikp) nLines = nLines+3 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! elseif(any(lplane))then ! distinguish the different cases --- part 2 ! !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! !the triangles crosses the plane --> cut it !=== BEGIN ===! !get the single point and the cutcase its(:) = -1 cutcase = 0 if(count(lplane)==1)then cutcase=1 do ii=1,3 if(lplane(ii)) its(0)=ii end do!ii elseif(count(lplane)==2)then cutcase=2 do ii=1,3 if(.not.lplane(ii)) its(0)=ii end do!ii else stop 'this case should not happen' end if!count !get the single point and the cutcase !=== END ===! !get the indices of the other points its(1)=mod(its(0), 3)+1 its(2)=mod(its(0)+1,3)+1 !=== BEGIN ===! ! cut the triangle according to the case do ii=1,2 denom = sum(ktmp1(:,ikp(its(ii)))*nvec(:,iface)) - sum(ktmp1(:,ikp(its(0)))*nvec(:,iface)) rscal = ( dscal(iface) - sum(ktmp1(:,ikp(its(0)))*nvec(:,iface)) )/denom ! if(abs(rscal-1d0)<eps)then ! ki0new(:,ii) = ktmp1(:,ikp(its(ii))) ! else!abs(rscal) ki0new(:,ii) = ktmp1(:,ikp(its(0))) + rscal*( ktmp1(:,ikp(its(ii))) - ktmp1(:,ikp(its(0))) ) ei0new(ii) = etmp1(ikp(its(0))) + rscal*( etmp1(ikp(its(ii))) - etmp1(ikp(its(0))) ) ! end if!abs(rscal) end do!ii if(cutcase==1)then ktmp2(:,nLines+1) = ktmp1(:,ikp(its(0))) ktmp2(:,nLines+2) = ki0new(:,1) ktmp2(:,nLines+3) = ki0new(:,2) etmp2(nLines+1) = etmp1(ikp(its(0))) etmp2(nLines+2) = ei0new(1) etmp2(nLines+3) = ei0new(2) nLines = nLines+3 elseif(cutcase==2)then ktmp2(:,nLines+1) = ktmp1(:,ikp(its(1))) ktmp2(:,nLines+2) = ktmp1(:,ikp(its(2))) ktmp2(:,nLines+3) = ki0new(:,1) ktmp2(:,nLines+4) = ktmp1(:,ikp(its(2))) ktmp2(:,nLines+5) = ki0new(:,2) ktmp2(:,nLines+6) = ki0new(:,1) etmp2(nLines+1) = etmp1(ikp(its(1))) etmp2(nLines+2) = etmp1(ikp(its(2))) etmp2(nLines+3) = ei0new(1) etmp2(nLines+4) = etmp1(ikp(its(2))) etmp2(nLines+5) = ei0new(2) etmp2(nLines+6) = ei0new(1) nLines = nLines+6 else!cutcase stop 'this case may not happen = 3' end if!cutcase ! cut the triangle according to the case !=== END ===! !++++++++++++++++++++++++++++++++++++++++++++++++! else! distinguish the different cases --- part 2 ! !++++++++++++++++++++++++++++++++++++++++++++++++! !the triangle lies on the wrong side of the plane --> throw away !++++++++++++++++++++++++++++++++++++++++++++++++++! end if! distinguish the different cases --- part 2 ! !++++++++++++++++++++++++++++++++++++++++++++++++++! ktmp1(:,1:nLines) = ktmp2(:,1:nLines) etmp1(1:nLines) = etmp2(1:nLines) nLinesINP = nLines end do!itri end do!iface ! loop over faces ! !===== END =====! !copy here to big array do ii=1,nLinesINP kstore(:,ii+kcounter) = ktmp1(:,ii) eigw_store(ii+kcounter) = etmp1(ii) end do kcounter = kcounter+nLinesINP !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ else ! DISTINGUISG THE DIFFERENT CASES ! !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !the triangle lies completely outside of the IBZ --> throw it away !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end if!DISTINGUISG THE DIFFERENT CASES ! !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end subroutine split_triangle end module mod_fermisurf_3D