module opt_delete use parameters use subroutines use elements use neighbors implicit none real(kind=dp) :: rc_off logical :: first public contains subroutine run_delete(arg_pos) integer, intent(inout) :: arg_pos rc_off = -lim_zero !Main calling function for delete option. print *, '-----------------------Option Delete------------------------' call parse_delete(arg_pos) if (rc_off > 0.0_dp) call delete_overlap end subroutine run_delete subroutine parse_delete(arg_pos) !Parse the delete command integer, intent(inout) :: arg_pos integer :: arg_len character(len=100) :: textholder arg_pos = arg_pos + 1 first = .true. call get_command_argument(arg_pos, textholder, arg_len) if(arg_len==0) stop "Missing argument to delete command" select case(textholder) case('overlap') arg_pos=arg_pos + 1 call get_command_argument(arg_pos, textholder, arg_len) if(arg_len==0) stop "Missing argument to delete overlap command" read(textholder, *) rc_off case default print *, "Command ", trim(adjustl(textholder)), " is not accepted for option delete" stop 3 end select arg_pos = arg_pos + 1 do while(.true.) if(arg_pos > command_argument_count()) exit !Pull out the next argument which should either be a keyword or an option arg_pos=arg_pos+1 call get_command_argument(arg_pos, textholder) textholder=adjustl(textholder) select case(trim(textholder)) case('first') first=.true. case('last') first=.false. case default !if it isn't an available option to opt_group then we just exit exit end select end do end subroutine parse_delete subroutine delete_overlap !This subroutine deletes all overlapping atoms, which is defined as atoms which are separated by a distance of !less then rc_off integer :: i, c(3), ci, cj, ck, num_nei, nei, delete_num integer, dimension(atom_num) :: for_delete !These are the variables containing the cell list information integer, dimension(3) :: cell_num integer, allocatable :: num_in_cell(:,:,:), which_cell(:,:) integer, allocatable :: cell_list(:,:,:,:) logical :: deleted_atom(atom_num) allocate(which_cell(3,atom_num)) !First pass the atom list and atom num to the algorithm which builds the cell list call build_cell_list(atom_num, r_atom, 5*rc_off, cell_num, num_in_cell, cell_list, which_cell) !Now loop over every atom and figure out if it has neighbors within the rc_off delete_num = 0 deleted_atom=.false. atom_loop: do i = 1, atom_num !c is the position of the cell that the atom belongs to c = which_cell(:,i) !Check to make sure it hasn't already been deleted if(all(c /= 0)) then !Now loop over all neighboring cells do ci = -1, 1, 1 do cj = -1, 1, 1 do ck = -1, 1, 1 if (any((c + (/ ck, cj, ci /)) == 0)) cycle if( (c(1) + ck > cell_num(1)).or.(c(2) + cj > cell_num(2)).or. & (c(3) + ci > cell_num(3))) cycle do num_nei = 1, num_in_cell(c(1) + ck, c(2) + cj, c(3) + ci) nei = cell_list(num_nei,c(1) + ck, c(2) + cj, c(3) + ci) !Check to make sure the atom isn't the same index as the atom we are checking !and that the neighbor hasn't already been deleted if((nei /= i).and.(.not.deleted_atom(nei))) then !Now check to see if it is in the cutoff radius, if it is add it to the delete code if (norm2(r_atom(:,nei)-r_atom(:,i)) < rc_off) then delete_num = delete_num + 1 if(first) then for_delete(delete_num) = min(i,nei) deleted_atom(min(i,nei)) = .true. else for_delete(delete_num) = max(i,nei) deleted_atom(max(i,nei)) = .true. end if !Now zero out the larger index if(first) then if(i < nei) then which_cell(:,i) = 0 cycle atom_loop else which_cell(:,nei) = 0 cell_list(num_nei,c(1) + ck, c(2) + cj, c(3) + ci) = 0 end if else if(i > nei) then which_cell(:,i) = 0 cycle atom_loop else which_cell(:,nei) = 0 cell_list(num_nei,c(1) + ck, c(2) + cj, c(3) + ci) = 0 end if end if end if end if end do end do end do end do end if end do atom_loop print *, "Overlap command deletes ", delete_num, " atoms" !Now delete all the atoms call delete_atoms(delete_num, for_delete(1:delete_num)) end subroutine delete_overlap end module opt_delete