diff --git a/Numbered_element.png b/Numbered_element.png new file mode 100644 index 0000000..9930917 Binary files /dev/null and b/Numbered_element.png differ diff --git a/README.md b/README.md index e56e857..d387a8d 100644 --- a/README.md +++ b/README.md @@ -214,10 +214,10 @@ This command wraps atoms back into the simulation cell as though periodic bounda **Remesh** ``` -remesh esize +remesh esize lattice_parameter lattice_type ``` -This command remeshes the atoms/elements within the group to the new element size `esize`. Currently only accepts an `esize` of 2 which refines it to full atomistics. When remeshing to atomistics the group can contain any orientations of elements but when remeshing to different finite elements, the group must contain all atoms/elements with the same orientation. +This command remeshes the atoms/elements within the group to the new element size `esize`. Currently only accepts an `esize` of 2 which refines it to full atomistics. When remeshing to atomistics the group can contain any orientations of elements but when remeshing to different finite elements, the group must contain all atoms/elements with the same orientation. `lattice_parameter` is the lattice parameter for the elements within the group and `lattice_type` is the lattice type (integer) that these new elements will be assigned to. **Max** @@ -291,3 +291,20 @@ Specifying positions in cacmb can be done through a variety of ways. Examples of `rand[val1:val2]` - returns a random position that lies within the range +`rande[facenum]` - Returns a random position in an interelement boundary which is offset of the element face `facenum`. Face numbers are based on the which vertices comprise the face. Vertex numbers are shown in the figure below for the primitive fcc unit cell which is what the fcc rhombohedral element is based from. The face numbers are: + +Face 1: [1,2,3,4] + +Face 2: [1,2,6,5] + +Face 3: [2,3,7,6] + +Face 4: [3,4,8,7] + +Face 5: [1,4,8,5] + +Face 6: [5,6,7,8] + +Image for vertex numbers is: + +![](/home/alexselimov/Documents/CACmb/Numbered_element.png) \ No newline at end of file diff --git a/src/elements.f90 b/src/elements.f90 index b4b8814..fed369f 100644 --- a/src/elements.f90 +++ b/src/elements.f90 @@ -64,11 +64,11 @@ module elements shape(fcc_cell)) !Now we create a list containing the list of vertices needed to describe the 6 cube faces - cubic_faces(:,1) = (/ 1, 4, 8, 5 /) - cubic_faces(:,2) = (/ 2, 3, 7, 6 /) - cubic_faces(:,3) = (/ 1, 2, 6, 5 /) + cubic_faces(:,1) = (/ 1, 2, 3, 4 /) + cubic_faces(:,2) = (/ 1, 2, 6, 5 /) + cubic_faces(:,3) = (/ 2, 3, 7, 6 /) cubic_faces(:,4) = (/ 3, 4, 8, 7 /) - cubic_faces(:,5) = (/ 1, 2, 3, 4 /) + cubic_faces(:,5) = (/ 1, 4, 8, 5 /) cubic_faces(:,6) = (/ 5, 6, 7, 8 /) !!Now initialize the fcc primitive cell @@ -491,4 +491,132 @@ module elements end do end subroutine + recursive subroutine parse_pos(i, pos_string, pos) + !This subroutine parses the pos command allowing for command which include inf + integer, intent(in) :: i !The dimension of the position + character(len=100), intent(in) :: pos_string !The position string + real(kind=dp), intent(out) :: pos !The output parsed position value + + integer :: iospara, face, ele + real(kind=dp) :: rand, rone, rtwo, rand_ele_pos(3) + character(len=100) :: cone, ctwo + + iospara = 0 + + if(trim(adjustl(pos_string)) == 'inf') then + pos=box_bd(2*i) + + else if(trim(adjustl(pos_string)) == '-inf') then + pos=box_bd(2*i-1) + + else if (trim(adjustl(pos_string)) == 'rand') then + call random_number(rand) + pos = (box_bd(2*i)-box_bd(2*i-1))*rand + box_bd(2*i-1) + + else if (index(pos_string,'rande')>0) then + !First select a random element + call random_number(rand) + ele= 1 + floor(ele_num*rand) + !Now read the rest of the command which specifies the face we need and check + !to make sure it's an accepted face number + cone = pos_string(index(pos_string, '[')+1:index(pos_string, '[')+1) + read(cone, *) face + if ((face < 1).or.(face > 6)) stop "Current face number must be 1,2,3,4,5,6. Please check documentation" + !Now get the position + call offset_pos(ele, face, rand_ele_pos) + pos = rand_ele_pos(i) + + else if (index(pos_string,'rand')>0) then + call random_number(rand) + cone = pos_string(index(pos_string, '[')+1:index(pos_string,':')-1) + call parse_pos(i, cone, rone) + ctwo = pos_string(index(pos_string, ':')+1:index(pos_string,']')-1) + call parse_pos(i, ctwo, rtwo) + pos = (rtwo - rone)*rand + rone + + else if ((index(pos_string,'-') > 0).and.(index(pos_string,'inf')>0)) then + !Now extract the number we are reducing from infinity + if(index(pos_string,'inf') < index(pos_string,'-')) then + read(pos_string(index(pos_string,'-')+1:), *, iostat=iospara) pos + else + read(pos_string(1:index(pos_string,'-')-1), *, iostat=iospara) pos + end if + pos = box_bd(2*i) - pos + + else if ((index(pos_string,'+') > 0).and.(index(pos_string,'inf')>0)) then + !Now extract the number we are reducing from infinity + if(index(pos_string,'inf') < index(pos_string,'+')) then + read(pos_string(index(pos_string,'+')+1:), *, iostat=iospara) pos + else + read(pos_string(1:index(pos_string,'+')-1), *, iostat=iospara) pos + end if + pos = box_bd(2*i-1) + pos + + else if ((index(pos_string,'*') > 0).and.(index(pos_string,'inf')>0)) then + !Now extract the number we are reducing from infinity + if(index(pos_string,'inf') < index(pos_string,'*')) then + read(pos_string(index(pos_string,'*')+1:), *, iostat=iospara) pos + else + read(pos_string(1:index(pos_string,'*')-1), *, iostat=iospara) pos + end if + pos = (box_bd(2*i)-box_bd(2*i-1))*pos + box_bd(2*i-1) + + else + read(pos_string, *, iostat=iospara) pos + + end if + + if (iospara > 0) then + print *, "Error reading position argument ", trim(adjustl(pos_string)), ". Please reformat and try again." + end if + end subroutine parse_pos + + subroutine offset_pos(ie, iface, pos) + !This returns a position slightly offset from the center of an element face + !This is used to return a random position within an element discontinuity + + integer, intent(in) :: ie !Element index + integer, intent(in) :: iface !Face number between 1 and 6 + real(kind=dp), dimension(3), intent(out) :: pos !Position vector + + !Other variables we need + integer :: esize + real(kind=dp) :: orient(3,3), ori_inv(3,3), lp, r_cubic_node(3,8) + + !First find the offset vector for the face in the untransformed cubic cell + esize = size_ele(ie) + select case(iface) + case(1) + pos = (/ real(esize-1,dp)/2.0_dp, real(esize-1,dp)/2.0_dp, -10.0_dp**-2.0_dp /) + case(2) + pos = (/ real(esize-1,dp)/2.0_dp, -10.0_dp**-2.0_dp, real(esize-1,dp)/2.0_dp /) + case(3) + pos = (/ (esize-1)+10.0_dp**-2.0_dp, real(esize-1,dp)/2.0_dp, real(esize-1,dp)/2.0_dp /) + case(4) + pos = (/ real(esize-1,dp)/2.0_dp, (esize-1)+10.0_dp**-2.0_dp, real(esize-1,dp)/2.0_dp /) + case(5) + pos = (/ -10.0_dp**-2.0_dp, real(esize-1,dp)/2.0_dp, real(esize-1,dp)/2.0_dp /) + case(6) + pos = (/ real(esize-1,dp)/2.0_dp, real(esize-1,dp)/2.0_dp, (esize-1)+10.0_dp**-2.0_dp /) + end select + + !Now transform it to real space and adjust it to the position of the element in the first node. + select case (trim(adjustl(type_ele(ie)))) + + case('fcc') + !First we have to extract the element lattice parameter + call matrix_inverse(sub_box_ori(:,:,sbox_ele(ie)),3,ori_inv) + r_cubic_node = r_node(:,1,:,ie) + r_cubic_node = matmul(fcc_inv,matmul(ori_inv,r_cubic_node)) + lp = (maxval(r_cubic_node(1,:))-minval(r_cubic_node(1,:)))/(esize-1) + pos = matmul(sub_box_ori(:,:,sbox_ele(ie)),matmul(fcc_mat,pos))*lp + pos = pos + r_node(:,1, 1, ie) + + case default + print *, trim(adjustl(type_ele(ie))), " is not a currently accepted element type for random element positions" + stop 3 + + end select + end subroutine + end module elements \ No newline at end of file diff --git a/src/io.f90 b/src/io.f90 index b1bc084..f4928e4 100644 --- a/src/io.f90 +++ b/src/io.f90 @@ -730,7 +730,7 @@ module io do i = 1, in_atoms read(11,*) j, type, sbox, r(:) r = r+newdisplace - call add_atom(new_type_to_type(type), sbox, r) + call add_atom(new_type_to_type(type), sbox+sub_box_num, r) end do !Read the elements @@ -742,7 +742,7 @@ module io r_innode(:,ibasis,inod) = r_innode(:, ibasis, inod) + newdisplace end do end do - call add_element(etype, size, new_lattice_map(type), sbox+n, r_innode) + call add_element(etype, size, new_lattice_map(type), sbox+sub_box_num, r_innode) end do !Close the file being read diff --git a/src/subroutines.f90 b/src/subroutines.f90 index 4e3d9a9..0be8d0e 100644 --- a/src/subroutines.f90 +++ b/src/subroutines.f90 @@ -171,67 +171,7 @@ module subroutines return end subroutine parse_ori_vec - - recursive subroutine parse_pos(i, pos_string, pos) - !This subroutine parses the pos command allowing for command which include inf - integer, intent(in) :: i !The dimension of the position - character(len=100), intent(in) :: pos_string !The position string - real(kind=dp), intent(out) :: pos !The output parsed position value - - integer :: iospara - real(kind=dp) :: rand, rone, rtwo - character(len=100) :: cone, ctwo - - iospara = 0 - if(trim(adjustl(pos_string)) == 'inf') then - pos=box_bd(2*i) - else if(trim(adjustl(pos_string)) == '-inf') then - pos=box_bd(2*i-1) - - else if (trim(adjustl(pos_string)) == 'rand') then - call random_number(rand) - pos = (box_bd(2*i)-box_bd(2*i-1))*rand + box_bd(2*i-1) - - else if (index(pos_string,'rand')>0) then - call random_number(rand) - cone = pos_string(index(pos_string, '[')+1:index(pos_string,':')-1) - call parse_pos(i, cone, rone) - ctwo = pos_string(index(pos_string, ':')+1:index(pos_string,']')-1) - call parse_pos(i, ctwo, rtwo) - pos = (rtwo - rone)*rand + rone - else if ((index(pos_string,'-') > 0).and.(index(pos_string,'inf')>0)) then - !Now extract the number we are reducing from infinity - if(index(pos_string,'inf') < index(pos_string,'-')) then - read(pos_string(index(pos_string,'-')+1:), *, iostat=iospara) pos - else - read(pos_string(1:index(pos_string,'-')-1), *, iostat=iospara) pos - end if - pos = box_bd(2*i) - pos - else if ((index(pos_string,'+') > 0).and.(index(pos_string,'inf')>0)) then - !Now extract the number we are reducing from infinity - if(index(pos_string,'inf') < index(pos_string,'+')) then - read(pos_string(index(pos_string,'+')+1:), *, iostat=iospara) pos - else - read(pos_string(1:index(pos_string,'+')-1), *, iostat=iospara) pos - end if - pos = box_bd(2*i-1) + pos - else if ((index(pos_string,'*') > 0).and.(index(pos_string,'inf')>0)) then - !Now extract the number we are reducing from infinity - if(index(pos_string,'inf') < index(pos_string,'*')) then - read(pos_string(index(pos_string,'*')+1:), *, iostat=iospara) pos - else - read(pos_string(1:index(pos_string,'*')-1), *, iostat=iospara) pos - end if - pos = (box_bd(2*i)-box_bd(2*i-1))*pos + box_bd(2*i-1) - - else - read(pos_string, *, iostat=iospara) pos - end if - - if (iospara > 0) then - print *, "Error reading position argument ", trim(adjustl(pos_string)), ". Please reformat and try again." - end if - end subroutine parse_pos + subroutine heapsort(a)