https://github.com/patrickfuchs/buildH/
Tip revision: f1302d534d35b1f517462b6498566229d95481ea authored by patrickfuchs on 27 May 2019, 13:46:15 UTC
Remove old files
Remove old files
Tip revision: f1302d5
subroutine_add_hydrogen.f
function normalize(vec) result(nvec)!{{{
real(kind=rk),intent(in) :: vec(:)
real(kind=rk) :: nvec(1:3)
nvec=vec/sqrt(sum(vec**2))
end function normalize!}}}
function v2q(v,theta) result(q)
!Create a quaternion from the vector v and angle theta
real(kind=rk),intent(in) :: v(:),theta ! Rad
real(kind=rk) :: q(4)
q=[cos(theta/2),sin(theta/2)*normalize(v)]
end function v2q
function RV(q) result(m)
!Rotational matrix: B.Stevensson et. al. 2011
real(kind=rk),intent(in) :: q(:) !quat
real(kind=rk) :: m(3,3) !quat
!First col
m(1,1)=q(1)**2+q(2)**2-q(3)**2-q(4)**2
m(2,1)=2*(q(2)*q(3)+q(1)*q(4))
m(3,1)=2*(q(2)*q(4)-q(1)*q(3))
!Second col
m(1,2)=2*(q(2)*q(3)-q(1)*q(4))
m(2,2)=q(1)**2-q(2)**2+q(3)**2-q(4)**2
m(3,2)=2*(q(3)*q(4)+q(1)*q(2))
!Third col
m(1,3)=2*(q(2)*q(4)+q(1)*q(3))
m(2,3)=2*(q(3)*q(4)-q(1)*q(2))
m(3,3)=q(1)**2-q(2)**2-q(3)**2+q(4)**2
end function RV
subroutine add_hydrogen(helpers,hcoor,imol,func,bondlength,theta)
integer(kind=ik),intent(in) :: helpers(:),func,imol
integer(kind=ik) :: i
real(kind=rk) ::&
v1(3),v2(3),v3(3),v4(3),v5(3),u(3),bondlength,thetal
real(kind=rk),intent(inout) :: hcoor(:)
real(kind=rk),optional :: theta
if(.not.present(theta) .and. func==3)stop 'CH2x needs rotation angle'
select case(func)
case(1) ! CH
v1=atom(helpers(1))%coor(:,imol)
v2=0._rk
do i=2,size(helpers)
! Center of the nomalized vectors
v2=v2+normalize(atom(helpers(i))%coor(:,imol)-v1)
end do
! Normalize by number and shift it back to v1
v2=v2/(size(helpers)-1)+v1
hcoor=bondlength*normalize(v1-v2)+v1
case(2) !CH double bond
v1=atom(helpers(1))%coor(:,imol)
v2=normalize(atom(helpers(2))%coor(:,imol)-v1)
v3=normalize(atom(helpers(3))%coor(:,imol)-v1)
! thetal is the angle 2pi - C-C-C devided by 2
! to ensure equal (C-C-H) angles from both directions
thetal=pi*(2-valenceangle(helpers(1),&
helpers(2),&
helpers(3),imol)/180._rk)/2
u=normalize(cross_product(v2,v3))
! RV returns a rotational 3x3 matrix from a quaternion
! v2q turns a vector into a quaternion with angle theta
! Rotate by matrix multiplication RV*V3 where V3 is rotated
hcoor=bondlength*normalize(matmul(RV(v2q(u,thetal)),v3))+v1
case(3) !CH2
thetal=theta*pi/180._rk
v1=atom(helpers(1))%coor(:,imol)
v2=normalize(atom(helpers(2))%coor(:,imol)-v1)
v3=normalize(atom(helpers(3))%coor(:,imol)-v1)
! Perpendicular to the C-C-C plane
v4=normalize(cross_product(v3,v2))
! Vector to rotate around. In the plane.
u=normalize(v2-v3)
! The vector to be rotated theta/2, perpendicular to u and v4
v4=normalize(cross_product(v4,u))
! Rotate the new v4 around u by thetal
hcoor=bondlength*normalize(matmul(RV(v2q(u,thetal)),v4))+v1
case(4) !CH3e
thetal=acos(-1._rk/3) ! 109.47 deg in radians
v1=atom(helpers(1))%coor(:,imol)
v2=normalize(atom(helpers(2))%coor(:,imol)-v1)
v3=normalize(atom(helpers(3))%coor(:,imol)-v1)
u=normalize(cross_product(v3,v2))
hcoor=bondlength*normalize(matmul(RV(v2q(u,thetal)),v2))+v1
case(5) !CH3r
thetal=120._rk*pi/180._rk
v1=atom(helpers(1))%coor(:,imol)
v2=atom(helpers(2))%coor(:,imol)
v3=atom(helpers(3))%coor(:,imol) !First hydrogen added by CH3e
u=normalize(v2-v1) ! C-C bond to rotate around
v4=normalize(v3-v1)
hcoor=bondlength*normalize(matmul(RV(v2q(u,thetal)),v4))+v1
case(6) !CH3s
thetal=-120._rk*pi/180._rk
v1=atom(helpers(1))%coor(:,imol)
v2=atom(helpers(2))%coor(:,imol)
v3=atom(helpers(3))%coor(:,imol) !First hydrogen added by CH3e
u=normalize(v2-v1) ! C-C bond to rotate around
v4=normalize(v3-v1)
hcoor=bondlength*normalize(matmul(RV(v2q(u,thetal)),v4))+v1
end select
end subroutine add_hydrogen