|
|
|
@ -15,7 +15,7 @@ module mode_create
|
|
|
|
|
orient_inv(3,3), box_vert(3,8), maxbd(3), lattice_space(3), duplicate(3)
|
|
|
|
|
integer :: esize, ix, iy, iz, box_lat_vert(3,8), lat_ele_num, lat_atom_num, bd_in_lat(6), &
|
|
|
|
|
basis_pos(3,10), esize_nums, esize_index(10)
|
|
|
|
|
logical :: dup_flag, dim_flag, efill
|
|
|
|
|
logical :: dup_flag, dim_flag, efill, crossb(3)
|
|
|
|
|
|
|
|
|
|
real(kind=dp), allocatable :: r_lat(:,:,:), r_atom_lat(:,:)
|
|
|
|
|
integer, allocatable :: elat(:)
|
|
|
|
@ -79,10 +79,10 @@ module mode_create
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
box_bd(2*i) = maxval(box_vert(i,:)) - 0.25_dp*lattice_space(i)
|
|
|
|
|
box_bd(2*i-1) = origin(i)-0.25_dp*lattice_space(i)
|
|
|
|
|
box_len(i) = box_bd(2*i) - box_bd(2*i-1)
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else if(dim_flag) then
|
|
|
|
|
!As a note everything is defined so that the lattice parameter is multiplied in at the end
|
|
|
|
|
!so we have to divide all the real Angstroms units by the lattice parameter
|
|
|
|
@ -131,11 +131,11 @@ module mode_create
|
|
|
|
|
!Call the build function with the correct transformation matrix
|
|
|
|
|
select case(trim(adjustl(element_type)))
|
|
|
|
|
case('fcc')
|
|
|
|
|
call build_with_rhomb(box_lat_vert, fcc_mat, 8)
|
|
|
|
|
call build_with_rhomb(box_lat_vert, fcc_mat, 8, fcc_inv)
|
|
|
|
|
case('bcc')
|
|
|
|
|
call build_with_rhomb(box_lat_vert, bcc_mat, 8)
|
|
|
|
|
call build_with_rhomb(box_lat_vert, bcc_mat, 8, bcc_inv)
|
|
|
|
|
case('20fcc')
|
|
|
|
|
call build_with_rhomb(box_lat_vert, fcc_mat, 20)
|
|
|
|
|
call build_with_rhomb(box_lat_vert, fcc_mat, 20, fcc_inv)
|
|
|
|
|
case default
|
|
|
|
|
print *, "Element type ", trim(adjustl(element_type)), " not accepted in mode create, please specify a supported ",&
|
|
|
|
|
"element type"
|
|
|
|
@ -176,6 +176,11 @@ module mode_create
|
|
|
|
|
sub_box_num = 1
|
|
|
|
|
sub_box_ori(:,:,1) = orient
|
|
|
|
|
sub_box_bd(:,1) = box_bd
|
|
|
|
|
|
|
|
|
|
!If any elements are fully outside the box then wrap them back in
|
|
|
|
|
if (any(crossb)) then
|
|
|
|
|
call wrap_elements
|
|
|
|
|
end if
|
|
|
|
|
end subroutine create
|
|
|
|
|
!This subroutine parses the command and pulls out information needed for mode_create
|
|
|
|
|
subroutine parse_command(arg_pos)
|
|
|
|
@ -183,9 +188,9 @@ module mode_create
|
|
|
|
|
integer, intent(out) :: arg_pos
|
|
|
|
|
integer :: ori_pos, i, j, arglen, stat
|
|
|
|
|
character(len=100) :: textholder
|
|
|
|
|
character(len=20) :: orient_string
|
|
|
|
|
character(len=100) :: orient_string
|
|
|
|
|
character(len=2) :: btype
|
|
|
|
|
logical :: isortho, isrighthanded
|
|
|
|
|
logical :: isortho, isrighthanded, bool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!Pull out all required positional arguments
|
|
|
|
@ -203,6 +208,7 @@ module mode_create
|
|
|
|
|
call get_command_argument(5, textholder, arglen)
|
|
|
|
|
if(arglen==0) STOP "Esize missing in mode create"
|
|
|
|
|
read(textholder, *, iostat=stat) esize
|
|
|
|
|
max_esize = esize
|
|
|
|
|
if(stat > 0) STOP "Error reading esize"
|
|
|
|
|
|
|
|
|
|
arg_pos = 6
|
|
|
|
@ -250,6 +256,12 @@ module mode_create
|
|
|
|
|
read(textholder, *) origin(i)
|
|
|
|
|
arg_pos = arg_pos + 1
|
|
|
|
|
end do
|
|
|
|
|
case('crossb')
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
call get_command_argument(arg_pos, textholder)
|
|
|
|
|
read(textholder, *) crossb(i)
|
|
|
|
|
arg_pos = arg_pos + 1
|
|
|
|
|
end do
|
|
|
|
|
case('basis')
|
|
|
|
|
call get_command_argument(arg_pos, textholder)
|
|
|
|
|
read(textholder, *) basisnum(1)
|
|
|
|
@ -275,11 +287,13 @@ module mode_create
|
|
|
|
|
end select
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!Calculate the lattice periodicity length in lattice units
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
lattice_space(i) = norm2(orient(i,:))
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
|
!Now normalize the orientation matrix
|
|
|
|
|
orient = matrix_normal(orient,3)
|
|
|
|
|
!Check special periodicity relations
|
|
|
|
|
select case(trim(adjustl(element_type)))
|
|
|
|
|
case('fcc', '20fcc')
|
|
|
|
@ -309,8 +323,6 @@ module mode_create
|
|
|
|
|
end if
|
|
|
|
|
end do
|
|
|
|
|
end select
|
|
|
|
|
!Now normalize the orientation matrix
|
|
|
|
|
orient = matrix_normal(orient,3)
|
|
|
|
|
!Now check these to make sure they are right handed and orthogonal
|
|
|
|
|
call check_right_ortho(orient, isortho, isrighthanded)
|
|
|
|
|
if (.not.isortho) then
|
|
|
|
@ -330,21 +342,22 @@ module mode_create
|
|
|
|
|
call add_atom_type(name, basis_type(1,1)) !If basis command not defined then we use name as the atom_name
|
|
|
|
|
basis_pos(:,1) = 0.0_dp
|
|
|
|
|
end if
|
|
|
|
|
!
|
|
|
|
|
|
|
|
|
|
end subroutine
|
|
|
|
|
|
|
|
|
|
subroutine build_with_rhomb(box_in_lat, transform_matrix, nn)
|
|
|
|
|
subroutine build_with_rhomb(box_in_lat, transform_matrix, nn, transform_inverse)
|
|
|
|
|
!This subroutine returns all the lattice points in the box in r_lat
|
|
|
|
|
|
|
|
|
|
!Inputs
|
|
|
|
|
integer, dimension(3,8), intent(in) :: box_in_lat !The box vertices transformed to lattice space
|
|
|
|
|
real(kind=dp), dimension(3,3), intent(in) :: transform_matrix !The transformation matrix from lattice_space to real space
|
|
|
|
|
real(kind=dp), dimension(3,3), intent(in) :: transform_inverse !The inverse transform
|
|
|
|
|
integer, intent(in) :: nn
|
|
|
|
|
!Internal variables
|
|
|
|
|
integer :: i, inod, bd_in_lat(6), bd_in_array(6), ix, iy, iz, numlatpoints, ele(3,nn), rzero(3), efill_size, &
|
|
|
|
|
integer :: i, inod, bd_in_lat(6), bd_in_array(6), ix, iy, iz, numlatpoints, ele(3,nn), rzero(3), efill_size, &
|
|
|
|
|
vlat(3), temp_lat(3,nn), m, n, o, j, k, nump_ele, efill_temp_lat(3,nn), filzero(3), &
|
|
|
|
|
bd_ele_lat(6), efill_ele(3,nn), ebd(6)
|
|
|
|
|
real(kind=dp) :: v(3), temp_nodes(3,1,nn), r(3), centroid_bd(6)
|
|
|
|
|
bd_ele_lat(6), efill_ele(3,nn), ebd(6), shift_vec(3), type_interp(max_basisnum*max_esize**3)
|
|
|
|
|
real(kind=dp) :: v(3), temp_nodes(3,1,nn), r(3), centroid_bd(6), vreal(3), r_interp(3, max_basisnum*max_esize**3)
|
|
|
|
|
logical, allocatable :: lat_points(:,:,:)
|
|
|
|
|
logical :: node_in_bd(nn), add, lat_points_ele(esize,esize,esize), intersect_bd(3)
|
|
|
|
|
|
|
|
|
@ -422,6 +435,7 @@ module mode_create
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!Now we redefine bd_in_lat The first 3 indices contains limits for the lat_points array
|
|
|
|
|
bd_in_array(1) = bd_in_lat(2) - bd_in_lat(1) + 10
|
|
|
|
|
bd_in_array(2) = bd_in_lat(4) - bd_in_lat(3) + 10
|
|
|
|
@ -493,6 +507,31 @@ module mode_create
|
|
|
|
|
!If within array boundaries check to see if it is a lattice point
|
|
|
|
|
else if(lat_points(vlat(1),vlat(2),vlat(3))) then
|
|
|
|
|
node_in_bd(inod) = .true.
|
|
|
|
|
else if(any(crossb)) then
|
|
|
|
|
vreal=0
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
if(crossb(i)) then
|
|
|
|
|
if(temp_nodes(i,1,inod) < box_bd(2*i-1)) then
|
|
|
|
|
vreal(i) = temp_nodes(i,1,inod)+box_len(i)
|
|
|
|
|
else if(temp_nodes(i,1,inod) > box_bd(2*i)) then
|
|
|
|
|
vreal(i) = temp_nodes(i,1,inod)-box_len(i)
|
|
|
|
|
else
|
|
|
|
|
vreal(i) = temp_nodes(i,1,inod)
|
|
|
|
|
end if
|
|
|
|
|
else
|
|
|
|
|
vreal(i) = temp_nodes(i,1,inod)
|
|
|
|
|
end if
|
|
|
|
|
end do
|
|
|
|
|
v = matmul(transform_inverse, matmul(orient_inv, vreal))
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
vlat(i) = nint(v(i) - bd_in_lat(2*i-1)+5)
|
|
|
|
|
end do
|
|
|
|
|
if(any(vlat > shape(lat_points)).or.any(vlat < 1)) then
|
|
|
|
|
continue
|
|
|
|
|
!If within array boundaries check to see if it is a lattice point
|
|
|
|
|
else if(lat_points(vlat(1),vlat(2),vlat(3))) then
|
|
|
|
|
node_in_bd(inod) = .true.
|
|
|
|
|
end if
|
|
|
|
|
end if
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
@ -502,14 +541,50 @@ module mode_create
|
|
|
|
|
lat_ele_num = lat_ele_num+1
|
|
|
|
|
r_lat(:,:,lat_ele_num) = temp_nodes(:,1,:)
|
|
|
|
|
elat(lat_ele_num) = esize
|
|
|
|
|
!Now set all the lattice points contained within an element to false
|
|
|
|
|
do o = minval(temp_lat(3,:)), maxval(temp_lat(3,:))
|
|
|
|
|
do n = minval(temp_lat(2,:)), maxval(temp_lat(2,:))
|
|
|
|
|
do m = minval(temp_lat(1,:)), maxval(temp_lat(1,:))
|
|
|
|
|
lat_points(m,n,o) = .false.
|
|
|
|
|
if(any(crossb)) then
|
|
|
|
|
call interpolate_atoms('fcc', esize, 0, temp_nodes, type_interp, r_interp)
|
|
|
|
|
j= 0
|
|
|
|
|
do o = minval(temp_lat(3,:)), maxval(temp_lat(3,:))
|
|
|
|
|
do n = minval(temp_lat(2,:)), maxval(temp_lat(2,:))
|
|
|
|
|
do m = minval(temp_lat(1,:)), maxval(temp_lat(1,:))
|
|
|
|
|
j=j+1
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
if(crossb(i)) then
|
|
|
|
|
if(r_interp(i,j) < box_bd(2*i-1)) then
|
|
|
|
|
vreal(i) = r_interp(i,j)+box_len(i)
|
|
|
|
|
else if(r_interp(i,j) > box_bd(2*i)) then
|
|
|
|
|
vreal(i) = r_interp(i,j)-box_len(i)
|
|
|
|
|
else
|
|
|
|
|
vreal(i) = r_interp(i,j)
|
|
|
|
|
end if
|
|
|
|
|
else
|
|
|
|
|
vreal(i) = r_interp(i,j)
|
|
|
|
|
end if
|
|
|
|
|
end do
|
|
|
|
|
v = matmul(transform_inverse, matmul(orient_inv, vreal))
|
|
|
|
|
do i = 1, 3
|
|
|
|
|
vlat(i) = nint(v(i) - bd_in_lat(2*i-1)+5)
|
|
|
|
|
end do
|
|
|
|
|
|
|
|
|
|
if(lat_points(vlat(1), vlat(2), vlat(3))) then
|
|
|
|
|
lat_points(vlat(1), vlat(2), vlat(3)) = .false.
|
|
|
|
|
else
|
|
|
|
|
print *, "Lat points should be true not false"
|
|
|
|
|
stop 2
|
|
|
|
|
end if
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
else
|
|
|
|
|
!Now set all the lattice points contained within an element to false
|
|
|
|
|
do o = minval(temp_lat(3,:)), maxval(temp_lat(3,:))
|
|
|
|
|
do n = minval(temp_lat(2,:)), maxval(temp_lat(2,:))
|
|
|
|
|
do m = minval(temp_lat(1,:)), maxval(temp_lat(1,:))
|
|
|
|
|
lat_points(m,n,o) = .false.
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
end do
|
|
|
|
|
end if
|
|
|
|
|
|
|
|
|
|
!If any nodes are in the boundary and we want to efill then run the efill code
|
|
|
|
|
else if(any(node_in_bd).and.efill) then
|
|
|
|
|