!-----------------------------------------------------------------------------------------! ! 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_symmetries ! This module provides routines regardinf the symmetry of the lattice and the irreducible brillouin zone. use mod_mympi, only: nranks, myrank, master use mod_pointgrp, only: pointgrp use mod_findgroup, only: findgroup implicit none private public :: symmetries_type, set_symmetries, get_IBZwedge_faces, points_in_wedge, singlepoint_in_wedge, rotate_kpoints, expand_visarrays, expand_areas, expand_spinvalues, expand_torqvalues, unfold_visarrays, get_2DIBZwedge_lines type :: symmetries_TYPE integer :: N = 5 integer :: nsym_used integer :: nsym_found double precision :: rotmat(64,3,3) character(len=10) :: rotname(64) integer, allocatable :: isym_used(:) integer, allocatable :: isym_found(:) integer, allocatable :: isym_notused(:) end type symmetries_TYPE contains subroutine unfold_visarrays(nkpts_all, nkpts_irr, kpt2irr_in, kpoints_in, kpt2irr_out, irr2kpt_out, kpoints_out) implicit none integer, intent(in) :: nkpts_irr, nkpts_all integer, intent(in) :: kpt2irr_in(nkpts_all) double precision, intent(in) :: kpoints_in(3,nkpts_irr) integer, allocatable, intent(out) :: irr2kpt_out(:), kpt2irr_out(:) double precision, allocatable, intent(out) :: kpoints_out(:,:) integer :: ierr, ikp allocate(kpoints_out(3,nkpts_all), irr2kpt_out(nkpts_all), kpt2irr_out(nkpts_all), STAT=ierr) if(ierr/=0) stop 'problem allocating kpoints, irr2kpt etc.' do ikp=1,nkpts_all kpoints_out(:,ikp) = kpoints_in(:,kpt2irr_in(ikp)) end do do ikp=1,nkpts_all irr2kpt_out(ikp) = ikp kpt2irr_out(ikp) = ikp end do end subroutine unfold_visarrays subroutine expand_visarrays(nsym, nkpts1, nkpts_irr1, kpt2irr1, irr2kpt1, kpt2irr, irr2kpt) implicit none integer, intent(in) :: nsym, nkpts1, nkpts_irr1 integer, intent(in) :: kpt2irr1(nkpts1), irr2kpt1(nkpts_irr1) integer, allocatable, intent(out) :: kpt2irr(:), irr2kpt(:) integer :: ierr, isy, ub, lb allocate(kpt2irr(nsym*nkpts1), irr2kpt(nsym*nkpts_irr1), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpt2irr in expand_visarrays' do isy=1,nsym lb = (isy-1)*nkpts1+1 ub = isy*nkpts1 kpt2irr(lb:ub) = kpt2irr1 + (isy-1)*nkpts_irr1 end do!isy do isy=1,nsym lb = (isy-1)*nkpts_irr1+1 ub = isy*nkpts_irr1 irr2kpt(lb:ub) = irr2kpt1 + (isy-1)*nkpts1 end do!isy end subroutine expand_visarrays subroutine expand_areas(nsym,nkpts_in,areas_in,areas_out) implicit none integer, intent(in) :: nsym, nkpts_in double precision, intent(in) :: areas_in(nkpts_in) double precision, allocatable, intent(out) :: areas_out(:) integer :: ierr, isy, ub, lb allocate(areas_out(nsym*nkpts_in), STAT=ierr) if(ierr/=0) stop 'Problem allocating areas_out' do isy=1,nsym lb = (isy-1)*nkpts_in+1 ub = isy*nkpts_in areas_out(lb:ub) = areas_in end do!isy end subroutine expand_areas subroutine expand_spinvalues(nsym,ndegen,nsqa,nkpts_in,spinval_in,spinval_out) implicit none integer, intent(in) :: nsym, ndegen, nsqa, nkpts_in double precision, intent(in) :: spinval_in(ndegen,nsqa,nkpts_in) double precision, allocatable, intent(out) :: spinval_out(:,:,:) integer :: ierr, isy, ub, lb allocate(spinval_out(ndegen,nsqa,nsym*nkpts_in), STAT=ierr) if(ierr/=0) stop 'Problem allocating spinval_out' do isy=1,nsym lb = (isy-1)*nkpts_in+1 ub = isy*nkpts_in spinval_out(:,:,lb:ub) = spinval_in end do!isy end subroutine expand_spinvalues subroutine expand_torqvalues(nsym,ndegen,nkpts_in,torqval_in,torqval_out) implicit none integer, intent(in) :: nsym, ndegen, nkpts_in double precision, intent(in) :: torqval_in(3,ndegen,nkpts_in) double precision, allocatable, intent(out) :: torqval_out(:,:,:) integer :: ierr, isy, ub, lb allocate(torqval_out(3,ndegen,nsym*nkpts_in), STAT=ierr) if(ierr/=0) stop 'Problem allocating torqval_out' do isy=1,nsym lb = (isy-1)*nkpts_in+1 ub = isy*nkpts_in torqval_out(:,:,lb:ub) = torqval_in end do!isy end subroutine expand_torqvalues subroutine rotate_kpoints(rotmat, nkpts_in, kpoints_in, nsym, isym, nkpts_out, kpoints_out) implicit none integer, intent(in) :: nkpts_in, nsym, isym(nsym) double precision, intent(in) :: kpoints_in(3,nkpts_in), rotmat(64,3,3) integer, intent(out) :: nkpts_out double precision, allocatable, intent(out) :: kpoints_out(:,:) integer :: ierr, ipoint, isy, iout allocate(kpoints_out(3,nkpts_in*nsym), STAT=ierr) if(ierr/=0) stop 'Problem allocating kpoints_out' do isy=1,nsym do ipoint=1,nkpts_in iout = (isy-1)*nkpts_in+ipoint kpoints_out(:,iout) = rotmat(isym(isy),1,:)*kpoints_in(1,ipoint) & & + rotmat(isym(isy),2,:)*kpoints_in(2,ipoint) & & + rotmat(isym(isy),3,:)*kpoints_in(3,ipoint) end do!ipoint end do!isy nkpts_out = nkpts_in*nsym end subroutine rotate_kpoints function points_in_wedge(nfaces, nvec, dscal, npts, points, mode) logical :: points_in_wedge integer, intent(in) :: nfaces, npts double precision, intent(in) :: nvec(3,nfaces), dscal(nfaces), points(3,npts) character(len=*), intent(in) :: mode integer :: ipt logical :: lpoints(npts) do ipt=1,npts lpoints(ipt) = singlepoint_in_wedge(nfaces, nvec, dscal, points(:,ipt)) end do!ipt select case( mode ) case( 'any' ) ; points_in_wedge = any(lpoints) case( 'all' ) ; points_in_wedge = all(lpoints) case default ; stop "Mode for 'points_in_wedge' not known." end select!icase end function points_in_wedge function singlepoint_in_wedge(nfaces, nvec, dscal, point) logical :: singlepoint_in_wedge integer, intent(in) :: nfaces double precision, intent(in) :: nvec(3,nfaces), dscal(nfaces), point(3) integer :: iface double precision :: dtmp double precision, parameter :: eps=1d-16 singlepoint_in_wedge=.true. do iface=1,nfaces dtmp = sum(nvec(:,iface)*point)-dscal(iface)+eps if(dtmp<0d0)then singlepoint_in_wedge=.false. return end if!eps end do!iface end function singlepoint_in_wedge subroutine get_2DIBZwedge_lines(recbv, nsym, rotmat, isym, nBZlines, nvec, dscal, bounds ) ! Generates the equations for the faces of the IBZ-wedge (2D-Version), ! such that for all points in the IBZ the inequality ! nvec(:,i) * k(:) >= dvec(i) ! holds. ! ! NOTE: nvec, dvec etc. are 3D-vectors due to compatibility with the bulk-version of the program ! ! In the end, the IBZ and its equvalents by symmetry ! are plotted as matplotlib-file. ! ! B.Zimmermann, Mai 2014 use mod_ioinput, only: IoInput use mod_mathtools, only: crossprod #ifdef CPP_MPI use mpi #endif implicit none integer, intent(in) :: nsym, isym(nsym) double precision, intent(in) :: rotmat(64,3,3), recbv(3,3) integer, intent(out) :: nBZlines double precision, allocatable, intent(out) :: nvec(:,:), dscal(:) double precision, intent(out) :: bounds(3,2) integer :: npoints!, isymtmp(1) double precision :: dtest, diff(3), vecinp(3), testpoint(3), diffvec(3,2) integer, allocatable :: verts2d(:) double precision, allocatable :: points(:,:) logical :: cartesian=.false. integer :: ipoint, iline, ierr,isy character(len=80) :: uio !===== ! Read in high symmetry points and number of BZ face lines !===== if(myrank==master)then call IoInput('NSYMPTS ',uio,1,7,ierr) read (unit=uio,fmt=*) npoints call IoInput('CARTESIAN ',uio,1,7,ierr) read (unit=uio,fmt=*) cartesian ! write(*,*) 'cartesian=', cartesian allocate(points(3,npoints), STAT=ierr ) if(ierr/=0) stop 'Problem allocating high symmetry points etc.' do ipoint=1,npoints call IoInput('SYMCOORD ',uio,ipoint,7,ierr) read (unit=uio,fmt=*) vecinp(:) if(cartesian)then points(:,ipoint) = vecinp(:) else!cartesian points(:,ipoint) = recbv(:,1)*vecinp(1) + recbv(:,2)*vecinp(2) + recbv(:,3)*vecinp(3) end if!cartesian if(abs(points(3,ipoint))>1d-16) stop 'z-coordinate of SYMCOORD not 0 for 2D system' end do!ipoint call IoInput('NIBZ2D ',uio,1,7,ierr) read (unit=uio,fmt=*) nBZlines allocate(verts2D(nBZlines+1), STAT=ierr) if(ierr/=0) stop 'Problem allocating nfaceverts' call IoInput('VERTS2D ',uio,1,7,ierr) read (unit=uio,fmt=*) verts2D call IoInput('POINTIBZ ',uio,1,7,ierr) read (unit=uio,fmt=*) vecinp(:) if(cartesian)then testpoint(:) = vecinp(:) else!cartesian testpoint(:) = recbv(:,1)*vecinp(1) + recbv(:,2)*vecinp(2) + recbv(:,3)*vecinp(3) end if!cartesian ! write(*,*) testpoint bounds(:,1) = minval(points, dim=2) bounds(:,2) = maxval(points, dim=2) end if!myrank==master !===== ! Allocate result arrays !===== #ifdef CPP_MPI call MPI_Bcast(nBZlines,1,MPI_INTEGER,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nfaces' #endif allocate(nvec(3,nBZlines), dscal(nBZlines), STAT=ierr) if(ierr/=0) stop 'Problem allocating nvec etc.' !===== ! Compute the equations for the BZ lines !===== if(myrank==master)then do iline=1,nBZlines !get difference vectors between three points of a face diffvec(:,1) = points(:,verts2D(iline+1)) - points(:,verts2D(iline)) diffvec(:,2) = (/ 0d0, 0d0, 1d0 /) !calculate the normal of the face call crossprod(diffvec(:,1),diffvec(:,2),nvec(:,iline)) !calculate the distance of plane to origin dscal(iline) = sum( nvec(:,iline)*points(:,verts2D(iline)) ) !calculate the distance of the testpoint dtest = sum( nvec(:,iline)*testpoint ) if(dtest<dscal(iline))then nvec(:,iline) = -nvec(:,iline) dscal(iline) = -dscal(iline) end if end do!iface end if!myrank==master #ifdef CPP_MPI call MPI_Bcast(nvec,3*nBZlines,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' call MPI_Bcast(dscal,nBZlines,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' call MPI_Bcast(bounds,6,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' #endif !===== ! Write info to the screen !===== if(myrank==master)then write(*,*) write(*,'("Reciprocal lattice:")') write(*,'(3ES25.16)') recbv write(*,*) write(*,'("Coordinates of the corner points of the IBZ:")') do ipoint=1,npoints write(*,'(2X,"Point ",I0,": (",3F10.6,")")') ipoint, points(:,ipoint) end do!ipoint write(*,*) write(*,'("Equations for the lines of the IBZ:")') do iline=1,nBZlines write(*,'(2X,"n=(",3F10.6,"), d=",F10.6)') nvec(:,iline), dscal(iline) end do!iface write(*,*) write(*,'("Bounds for the IBZ:")') write(*,'(" min:",3F12.6)') bounds(:,1) write(*,'(" max:",3F12.6)') bounds(:,2) open(unit=1359,file='bounds',form='formatted',action='write') write(1359,'(3ES25.16)') bounds close(1359) diff = bounds(:,2)-bounds(:,1) diff = diff/minval(diff(1:2)) write(*,'(" fac:",3F12.1)') diff write(*,*) end if!myrank==master !===== ! Create TXT-File containing the IBZ !===== if(myrank==master)then open(unit=19535, file='ibz_wedge.txt', form='formatted', action='write') write(19535,'(A)') '# 2D IBZ. Each line represents one IBZ point' do ipoint=1,nBZlines+1 write(19535,'(3ES25.16)') points(:,verts2D(ipoint)) end do ! write(19535,'(A)') '# 2D IBZ. Each line represents one IBZ straigt line, containing the start and end point' ! do iline=1,nBZlines ! write(19535,'(6ES25.16)') points(:,verts2D(iline)), points(:,verts2D(iline+1)) ! end do close(19535) open(unit=19536, file='ibz_fullbz.txt', form='formatted', action='write') write(19536,'(A)') '# 2D IBZ. Each line represents one BZ point, first number is number of symmetry operation' write(19536,'(2I8)') nsym, nBZlines+1 do isy=1,nsym do ipoint=1,nBZlines+1 write(19536,'(I8,3ES25.16)') isy, rotmat(isym(isy),1,:)*points(1,verts2D(ipoint)) & & + rotmat(isym(isy),2,:)*points(2,verts2D(ipoint)) & & + rotmat(isym(isy),3,:)*points(3,verts2D(ipoint)) end do!ipoint end do!isy close(19536) end if!myrank==master end subroutine get_2DIBZwedge_lines subroutine get_IBZwedge_faces(recbv, nsym, rotmat, isym, nfaces, nvec, dscal, bounds) ! Generates the equations for the faces of the IBZ-wedge, ! such that for all points in the IBZ the inequality ! nvec(:,i) * k(:) >= dvec(i) ! holds. ! In the end, the IBZ and its equvalents by symmetry ! are plotted as vtk-file. ! ! B.Zimmermann, Mar.2013 use mod_ioinput, only: IoInput use mod_mathtools, only: crossprod use mod_vtkxml, only: write_IBZ_rot #ifdef CPP_MPI use mpi #endif implicit none integer, intent(in) :: nsym, isym(nsym) double precision, intent(in) :: rotmat(64,3,3), recbv(3,3) integer, intent(out) :: nfaces double precision, allocatable, intent(out) :: nvec(:,:), dscal(:) double precision, intent(out) :: bounds(3,2) integer :: npoints, isymtmp(1) double precision :: dtest, diff(3), vecinp(3), testpoint(3), diffvec(3,2) integer, allocatable :: nfaceverts(:), ifaceverts(:,:) double precision, allocatable :: points(:,:) logical :: cartesian=.false. integer :: ipoint, iface, ierr character(len=80) :: uio !===== ! Read in high symmetry points and number of faces !===== if(myrank==master)then call IoInput('NSYMPTS ',uio,1,7,ierr) read (unit=uio,fmt=*) npoints call IoInput('CARTESIAN ',uio,1,7,ierr) read (unit=uio,fmt=*) cartesian ! write(*,*) 'cartesian=', cartesian allocate(points(3,npoints), STAT=ierr ) if(ierr/=0) stop 'Problem allocating high symmetry points etc.' do ipoint=1,npoints call IoInput('SYMCOORD ',uio,ipoint,7,ierr) read (unit=uio,fmt=*) vecinp(:) if(cartesian)then points(:,ipoint) = vecinp(:) else!cartesian points(:,ipoint) = recbv(:,1)*vecinp(1) + recbv(:,2)*vecinp(2) + recbv(:,3)*vecinp(3) end if!cartesian ! write(*,*) points(:,ipoint) end do!ipoint call IoInput('NIBZFAC ',uio,1,7,ierr) read (unit=uio,fmt=*) nfaces allocate(nfaceverts(nfaces), STAT=ierr) if(ierr/=0) stop 'Problem allocating nfaceverts' do iface=1,nfaces call IoInput('NVERT ',uio,iface,7,ierr) read (unit=uio,fmt=*) nfaceverts(iface) ! write(*,*) nfaceverts(iface) end do!iface allocate(ifaceverts(maxval(nfaceverts),nfaces), STAT=ierr) if(ierr/=0) stop 'Problem allocating ifaceverts' ifaceverts = 0 do iface=1,nfaces call IoInput('VERTIDS ',uio,iface,7,ierr) read (unit=uio,fmt=*) ifaceverts(1:nfaceverts(iface),iface) ! write(*,'(10I3)') ifaceverts(:,iface) end do!iface call IoInput('POINTIBZ ',uio,1,7,ierr) read (unit=uio,fmt=*) vecinp(:) if(cartesian)then testpoint(:) = vecinp(:) else!cartesian testpoint(:) = recbv(:,1)*vecinp(1) + recbv(:,2)*vecinp(2) + recbv(:,3)*vecinp(3) end if!cartesian ! write(*,*) testpoint bounds(:,1) = minval(points, dim=2) bounds(:,2) = maxval(points, dim=2) end if!myrank==master !===== ! Allocate result arrays !===== #ifdef CPP_MPI call MPI_Bcast(nfaces,1,MPI_INTEGER,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nfaces' #endif allocate(nvec(3,nfaces), dscal(nfaces), STAT=ierr) if(ierr/=0) stop 'Problem allocating nvec etc.' !===== ! Compute the equations for the planes of the BZ faces !===== if(myrank==master)then do iface=1,nfaces !get difference vectors between three points of a face diffvec(:,1) = points(:,ifaceverts(2,iface)) - points(:,ifaceverts(1,iface)) diffvec(:,2) = points(:,ifaceverts(3,iface)) - points(:,ifaceverts(1,iface)) !calculate the normal of the face call crossprod(diffvec(:,1),diffvec(:,2),nvec(:,iface)) !calculate the distance of plane to origin dscal(iface) = sum( nvec(:,iface)*points(:,ifaceverts(1,iface)) ) !calculate the distance of the testpoint dtest = sum( nvec(:,iface)*testpoint ) if(dtest<dscal(iface))then nvec(:,iface) = -nvec(:,iface) dscal(iface) = -dscal(iface) end if end do!iface end if!myrank==master #ifdef CPP_MPI call MPI_Bcast(nvec,3*nfaces,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' call MPI_Bcast(dscal,nfaces,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' call MPI_Bcast(bounds,6,MPI_DOUBLE_PRECISION,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nvec' #endif !===== ! Write info to the screen !===== if(myrank==master)then write(*,'("Coordinates of the corner points of the IBZ:")') do ipoint=1,npoints write(*,'(2X,"Point ",I0,": (",3F10.6,")")') ipoint, points(:,ipoint) end do!ipoint write(*,*) write(*,'("Equations for the faces of the IBZ:")') do iface=1,nfaces write(*,'(2X,"n=(",3F10.6,"), d=",F10.6)') nvec(:,iface), dscal(iface) end do!iface write(*,*) write(*,'("Bounds for the IBZ:")') write(*,'(" min:",3F12.6)') bounds(:,1) write(*,'(" max:",3F12.6)') bounds(:,2) open(unit=1359,file='bounds',form='formatted',action='write') write(1359,'(3ES25.16)') bounds close(1359) diff = bounds(:,2)-bounds(:,1) diff = diff/minval(diff) write(*,'(" fac:",3F12.1)') diff write(*,*) end if!myrank==master !===== ! Create VTK-File containing the IBZ !===== if(myrank==master) call write_IBZ_rot('ibz_fullbz.vtp',npoints,points,nfaces,nfaceverts,ifaceverts,nsym,rotmat,isym) isymtmp = 1 if(myrank==master) call write_IBZ_rot('ibz_wedge.vtp',npoints,points,nfaces,nfaceverts,ifaceverts,1,rotmat,isymtmp) end subroutine get_IBZwedge_faces subroutine set_symmetries(inc, lattice, symmetries) ! This subroutine sets the symmetry infortmation ! and stores them in the derived datatype symmetries. ! The symmetry information as found from 'findgroup', ! as well as the user-defined symmetries from the ! input-file are concerned. use type_inc, only: inc_type use type_data, only: lattice_type #ifdef CPP_MPI use mpi #endif implicit none type(inc_type), intent(in) :: inc type(lattice_type), intent(in) :: lattice type(symmetries_type), intent(out) :: symmetries integer :: ierr, isy1, isy2, icount !===== ! Find symmetry information from the lattice !===== call findgroup( inc%naez,inc%naezd,inc%nembd,lattice%bravais, & & lattice%rbasis,lattice%alat,lattice%recbv,inc%nBZdim, & & symmetries%rotmat,symmetries%rotname, & & symmetries%nsym_found,symmetries%isym_found ) !===== ! Find symmetry information from the input-file !===== if(myrank==master) then call read_sym_inp( symmetries%rotname,symmetries%nsym_used,symmetries%isym_used ) end if!myrank==master #ifdef CPP_MPI call MPI_Bcast(symmetries%nsym_used,1,MPI_INTEGER,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting nsym' if(myrank/=master)then allocate( symmetries%isym_used(symmetries%nsym_used), STAT=ierr ) if(ierr/=0) stop 'Problem allocating symmetries%isym_used on slaves' end if call MPI_Bcast(symmetries%isym_used,symmetries%nsym_used,MPI_INTEGER,master,MPI_COMM_WORLD,ierr) if(ierr/=MPI_SUCCESS) stop 'Problem broadcasting symmetries%isym_used' #endif !===== ! Find symmetries that are exluded (i.e. valid ones for the lattice but not specified by the user) !===== allocate(symmetries%isym_notused(symmetries%nsym_found - symmetries%nsym_used), STAT=ierr) if(ierr/=0) stop 'Problem allocating symmetries%isym_notused' icount=0 outer: do isy1=1,symmetries%nsym_found inner: do isy2=1,symmetries%nsym_used if(symmetries%isym_found(isy1) == symmetries%isym_used(isy2)) cycle outer end do inner!isy2 icount = icount+1 symmetries%isym_notused(icount) = symmetries%isym_found(isy1) end do outer!isy1 if(myrank==master)then write(6,*) write(6,'(" Symmetries NOT used: ",I0)') icount write(6,1050) (symmetries%rotname(symmetries%isym_notused(isy1)), isy1=1,icount ) write(6,*) end if!myrank==master 1050 FORMAT(5(A10,2X)) end subroutine set_symmetries subroutine read_sym_inp(rotname, nsym, isymindex) !This subroutine reads symmetry information from the inputfile. ! In the inputfile the names of symmetry transformations ! according to the subroutine 'pointgrp' must be given. ! INPUT: the array 'rotname' containing the names of ! all possible symmetry operations. ! OUTPUT: nsym contains the number of symmetry operations used ! isymindex contains the id's of the used symmetries use mod_ioinput, only: IoInput implicit none character(len=10), intent(in) :: rotname(64) integer, intent(out) :: nsym integer, allocatable, intent(out) :: isymindex(:) integer :: irow, icol, isym, istore, rest, ierr integer, allocatable :: linespercol(:) character(len=10) :: colname character(len=80) :: uio character(len=10) :: charstr(64) integer, parameter :: ncols = 5 !read in number of symmetries to use call IoInput('NSYM ',uio,1,7,ierr) read (unit=uio,fmt=*) nsym !create storage array allocate( isymindex(nsym), STAT=ierr ) if(ierr/=0) stop 'Problem allocating isymindex' !create temporary variables to read in symmetries allocate(linespercol(ncols)) linespercol = nsym/ncols rest = nsym - linespercol(1)*ncols linespercol(1:rest) = linespercol(1:rest)+1 do icol=1,ncols write(colname,'("SYMFIELD",I0)') icol do irow = 1,linespercol(icol) call IoInput(colname,uio,1+irow,7,ierr) symloop: do isym=1,64 if(trim(uio(1:10))==trim(rotname(isym)))then istore = (irow-1)*ncols+icol isymindex(istore) = isym exit symloop end if end do symloop!isym end do!irow end do!icol !write info to the screen write(6,1040) nsym do isym=1,nsym istore = isymindex(isym) charstr(isym) = rotname(istore) end do write(6,1030) (charstr(isym),isym=1,nsym) write(6,*) 1030 FORMAT(5(A10,2X)) 1040 FORMAT(' Symmetries set by hand: ',I5) end subroutine read_sym_inp end module mod_symmetries