Fitting-L-matrix/src/model/Maik_chngs/maik_ctrans.f90

674 lines
22 KiB
Fortran

!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! % SUBROUTINE CTRANS(...)
! %
! % M. Vossel 21.03.2023
! %
! % Routine to transform symmetryinput coordinates to symmetrized
! % coordinates. Distances Are discribet by Morse coordinates or
! % TMC depending on Set Parameters in the Genetic Input.
! %
! % input variables
! % q:
! % q(1): H1x
! % q(2): y
! % q(3): z
! % q(4): H2x
! % q(5): y
! % q(6): z
! % q(7): H3x
! % q(8): y
! % q(9): z
!
!
!
! % Internal variables:
! % t: primitive coordinates (double[qn])
! % t(1):
! % t(2):
! % t(3):
! % t(4):
! % t(5):
! % t(6):
! % t(7):
! % t(8):
! % t(9):
! % t: dummy (double[qn])
! % p: parameter vector
! % npar: length of parameter vector
! %
! % Output variables
! % s: symmetrized coordinates (double[qn])
! % s(1): CH-symetric streatch
! % s(2): CH-asymetric streatch-ex
! % s(3): CH-asymetric streatch-ey
! % s(4): CH-bend-ex
! % s(5): CH-bend-ey
! % s(6): CH-umbrella
! % s(7): CH-umbrella**2
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
module ctrans_mod
use accuracy_constants, only: dp, idp
implicit none
! precalculate pi, 2*pi and angle to radian conversion
real(dp), parameter :: pi = 4.0_dp*datan(1.0_dp)
real(dp), parameter :: pi2 = 2.0_dp*pi
real(dp), parameter :: ang2rad = pi/180.0_dp
! precalculate roots
real(dp), parameter:: sq2 = 1.0_dp/dsqrt(2.0_dp)
real(dp), parameter:: sq3 = 1.0_dp/dsqrt(3.0_dp)
real(dp), parameter:: sq6 = 1.0_dp/dsqrt(6.0_dp)
! change distances for equilibrium
!real(dp), parameter :: dchequi = 1.02289024_dp
real(dp), parameter :: dchequi = 2.344419_dp ! NO3
!real(dp), parameter :: dchequi = 2.34451900_dp
! see changes
contains
subroutine ctrans(q, x1,x2, invariants)
use dim_parameter, only: qn
integer(idp) k !running indices
real(dp), intent(in) :: q(qn) !given coordinates
real(dp), intent(out) :: x1(qn) !output coordinates symmetry adapted and scaled
real(dp), intent(out) :: x2(qn) !output coordinates symmetry adapted but not scaled
! ANN Variables
real(dp), optional, intent(out) :: invariants(:)
real(dp) :: s(qn),t(qn)
! kartesian coordianates copy from MeF+ so substitute c by n and removed f
real(dp) ch1(3), ch2(3), ch3(3), c_atom(3)
real(dp) nh1(3), nh2(3), nh3(3)
real(dp) zaxis(3), xaxis(3), yaxis(3)
real(dp) ph1(3), ph2(3), ph3(3)
! primitive coordinates
real(dp) dch1, dch2, dch3 !nh-distances
real(dp) umb !Umbrella Angle from xy-plane
! Symmetry coordinates
real(dp) aR !a1-modes H-Dist.,
real(dp) exR, exAng !ex components H-Dist., H-Ang.
real(dp) eyR, eyAng !ey components H-Dist., H-Ang.
! debugging
logical, parameter :: dbg = .false.
! initialize coordinate vectors
s = 0.0_dp
t = 0.0_dp
! write kartesian coords for readability
c_atom(1:3) = q(1:3)
do k = 1, 3
ch1(k) = q(k + 3)
ch2(k) = q(k + 6)
ch3(k) = q(k + 9)
end do
! construct z-axis
nh1 = normalized(ch1)
nh2 = normalized(ch2)
nh3 = normalized(ch3)
zaxis = create_plane(nh1, nh2, nh3)
! calculate bonding distance
dch1 = norm(ch1)
dch2 = norm(ch2)
dch3 = norm(ch3)
! construct symmertic and antisymmetric strech
aR = symmetrize(dch1 - dchequi, dch2 - dchequi, dch3 - dchequi, 'a')
exR = symmetrize(dch1, dch2, dch3, 'x')
eyR = symmetrize(dch1, dch2, dch3, 'y')
! construc x-axis and y axis
ph1 = normalized(project_point_into_plane(nh1, zaxis, c_atom))
xaxis = normalized(ph1)
yaxis = xproduct(zaxis, xaxis) ! right hand side koordinates
! project H atoms into C plane
ph2 = normalized(project_point_into_plane(nh2, zaxis, c_atom))
ph3 = normalized(project_point_into_plane(nh3, zaxis, c_atom))
call construct_HBend(exAng, eyAng, ph1, ph2, ph3, xaxis, yaxis)
umb = construct_umbrella(nh1, nh2, nh3, zaxis)
! set symmetry coordinates and even powers of umbrella
!s(1) = dch1- dchequi !aR
!s(2) = dch2 - dchequi !exR
!s(3) = dch3 - dchequi !eyR
s(1) = aR
s(2) = exR
s(3) = eyR
s(4) = exAng
s(5) = eyAng
s(6) = umb
s(7) = umb**2
s(8) = 0
s(9) = 0
! pairwise distances as second coordinate set
t = 0._dp
call pair_distance(q, t(1:6))
if (dbg) write (6, '("sym coords s=",9f16.8)') s(1:qn)
if (dbg) write (6, '("sym coords t=",9f16.8)') t(1:qn)
if (present(invariants)) then
call get_invariants(s, invariants)
end if
! transform s and t to x1 and x2
x1(1:qn)=s(1:qn)
x1(5)=x1(5)
! set other x coordinate to zero other than strech
!X1(4:qn)=0.0d0
x2(1:qn)=t(1:qn)
end subroutine ctrans
subroutine pair_distance(q, r)
real(dp), intent(in) :: q(9)
real(dp), intent(out) :: r(6)
real(dp) :: atom(3, 4)
integer :: n, k, count
!atom order: H1 H2 H3 N
atom(:, 1:3) = reshape(q, [3, 3])
atom(:, 4) = (/0.0_dp, 0.0_dp, 0.0_dp/)
! disntace order 12 13 14 23 24 34
count = 0
do n = 1, size(atom, 2)
do k = n + 1, size(atom, 2)
count = count + 1
r(count) = sqrt(sum((atom(:, k) - atom(:, n))**2))
end do
end do
end subroutine pair_distance
function morse_and_symmetrize(x,p,pst) result(s)
real(dp), intent(in),dimension(3) :: x
real(dp), intent(in),dimension(11) :: p
integer, intent(in),dimension(2) :: pst
integer :: k
real(dp), dimension(3) :: s
real(dp), dimension(3) :: t
! Morse transform
do k=1,3
t(k) = morse_transform(x(k), p, pst)
end do
s(1) = symmetrize(t(1), t(2), t(3), 'a')
s(2) = symmetrize(t(1), t(2), t(3), 'x')
s(3) = symmetrize(t(1), t(2), t(3), 'y')
end function morse_and_symmetrize
subroutine get_invariants(s, inv_out)
use dim_parameter, only: qn
use select_monom_mod, only: v_e_monom, v_ee_monom
real(dp), intent(in) :: s(qn)
real(dp), intent(out) :: inv_out(:)
! real(dp), parameter :: ck = 1.0_dp, dk = 1.0_dp/ck ! scaling for higher order invariants
real(dp) inv(24)
integer, parameter :: inv_order(12) = & ! the order in which the invariants are selected
& [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
real(dp) Rch, umb, xR, yR, xAng, yAng
! for readability
Rch = s(1)
xR = s(2)
yR = s(3)
xAng = s(4)
yAng = s(5)
umb = s(6)**2
! invarianten
! a moden
inv(1) = Rch
inv(2) = umb
! invariante e pairs
inv(3) = v_e_monom(xR, yR, 1)
inv(4) = v_e_monom(xAng, yAng, 1)
! third order e pairs
inv(5) = v_e_monom(xR, yR, 2)
inv(6) = v_e_monom(xAng, yAng, 2)
! invariant ee coupling
inv(7) = v_ee_monom(xR, yR, xAng, yAng, 1)
! mode combinations
inv(8) = Rch*umb
inv(9) = Rch*v_e_monom(xR, yR, 1)
inv(10) = umb*v_e_monom(xR, yR, 1)
inv(11) = Rch*v_e_monom(xAng, yAng, 1)
inv(12) = umb*v_e_monom(xAng, yAng, 1)
! damp coordinates because of second order and higher invariants
inv(3) = sign(sqrt(abs(inv(3))), inv(3))
inv(4) = sign(sqrt(abs(inv(4))), inv(4))
inv(5) = sign((abs(inv(5))**(1./3.)), inv(5))
inv(6) = sign((abs(inv(6))**(1./3.)), inv(6))
inv(7) = sign((abs(inv(7))**(1./3.)), inv(7))
inv(8) = sign(sqrt(abs(inv(8))), inv(8))
inv(9) = sign((abs(inv(9))**(1./3.)), inv(9))
inv(10) = sign((abs(inv(10))**(1./3.)), inv(10))
inv(11) = sign((abs(inv(11))**(1./3.)), inv(11))
inv(12) = sign((abs(inv(12))**(1./3.)), inv(12))
inv_out(:) = inv(inv_order(1:size(inv_out, 1)))
end subroutine get_invariants
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! % real part of spherical harmonics
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! Ylm shifted to 0 for theta=0
real(dp) function ylm(theta, phi, l, m)
implicit none
real(dp) theta, phi
integer(idp) l, m
ylm = plm2(dcos(theta), l, m)*cos(m*phi) - plm2(1.0_dp, l, m)
end function ylm
!----------------------------------------------------------
real(dp) function plm2(x, l, n)
implicit none
real(dp) x
integer(idp) l, m, n
real(dp) pmm, p_mp1m, pllm
integer(idp) ll
! negative m und bereich von x abfangen
if ((l .lt. 0)&
&.or. (abs(n) .gt. abs(l))&
&.or. (abs(x) .gt. 1.)) then
write (6, '(''bad arguments in legendre'')')
stop
end if
! fix sign of m to compute the positiv m
m = abs(n)
pmm = (-1)**m*dsqrt(fac(2*m))*1./((2**m)*fac(m))& !compute P(m,m) not P(l,l)
&*(dsqrt(1.-x**2))**m
if (l .eq. m) then
plm2 = pmm !P(l,m)=P(m,m)
else
p_mp1m = x*dsqrt(dble(2*m + 1))*pmm !compute P(m+1,m)
if (l .eq. m + 1) then
plm2 = p_mp1m !P(l,m)=P(m+1,m)
else
do ll = m + 2, l
pllm = x*(2*l - 1)/dsqrt(dble(l**2 - m**2))*p_mp1m& ! compute P(m+2,m) up to P(l,m) recursively
&- dsqrt(dble((l - 1)**2 - m**2))&
&/dsqrt(dble(l**2 - m**2))*pmm
! schreibe m+2 und m+1 jeweils fuer die naechste iteration
pmm = p_mp1m !P(m,m) = P(m+1,m)
p_mp1m = pllm !P(m+1,m) = P(m+2,m)
end do
plm2 = pllm !P(l,m)=P(m+k,m), k element N
end if
end if
! sets the phase of -m term right (ignored to gurantee Ylm=(Yl-m)* for JT terms
! if(n.lt.0) then
! plm2 = (-1)**m * plm2 !* fac(l-m)/fac(l+m)
! endif
end function
!----------------------------------------------------------------------------------------------------
real(dp) function fac(i)
integer(idp) i
select case (i)
case (0)
fac = 1.0_dp
case (1)
fac = 1.0_dp
case (2)
fac = 2.0_dp
case (3)
fac = 6.0_dp
case (4)
fac = 24.0_dp
case (5)
fac = 120.0_dp
case (6)
fac = 720.0_dp
case (7)
fac = 5040.0_dp
case (8)
fac = 40320.0_dp
case (9)
fac = 362880.0_dp
case (10)
fac = 3628800.0_dp
case (11)
fac = 39916800.0_dp
case (12)
fac = 479001600.0_dp
case default
write (*, *) 'ERROR: no case for given faculty, Max is 12!'
stop
end select
end function fac
! Does the simplest morse transform possible
! one skaling factor + shift
function morse_transform(x, p, pst) result(t)
real(dp), intent(in) :: x
real(dp), intent(in) :: p(11)
integer, intent(in) :: pst(2)
real(dp) :: t
if (pst(2) == 11) then
t = 1.0_dp - exp(-abs(p(2))*(x - p(1)))
else
error stop 'in morse_transform key required or wrong number of parameters'
end if
end function morse_transform
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! % FUNCTION F(...) ! MAIK DEPRICATING OVER THE TOP MORSE FUNCTION FOR MYSELF
! %
! % Returns exponent of tunable Morse coordinate
! % exponent is polynomial * gaussian (skewed)
! % ilabel = 1 or 2 selects the parameters a and sfac to be used
! %
! % Background: better representation of the prefector in the
! % exponend of the morse function.
! % Formular: f(r) = lest no3 paper
! %
! % Variables:
! % x: distance of atoms (double)
! % p: parameter vector (double[20])
! % ii: 1 for CCl and 2 for CCH (int)
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pure function f(x, p, ii)
integer(idp), intent(in) :: ii !1 for CCL and 2 for CCH
real(dp), intent(in) :: x !coordinate
real(dp), intent(in) :: p(11) !parameter-vector
integer(idp) i !running index
real(dp) r !equilibrium distance
real(dp) gaus !gaus part of f
real(dp) poly !polynom part of f
real(dp) skew !tanh part of f
real(dp) f !prefactor of exponent and returned value
integer(idp) npoly(2) !order of polynom
! Maximum polynom order
npoly(1) = 5
npoly(2) = 5
! p(1): position of equilibrium
! p(2): constant of exponent
! p(3): constant for skewing the gaussian
! p(4): tuning for skewing the gaussian
! p(5): Gaussian exponent
! p(6): Shift of Gaussian maximum
! p(7)...: polynomial coefficients
! p(8+n)...: coefficients of Morse Power series
! 1-exp{[p(2)+exp{-p(5)[x-p(6)]^2}[Taylor{p(7+n)}(x-p(6))]][x-p(1)]}
! Tunable Morse function
! Power series in Tunable Morse coordinates of order m
! exponent is polynomial of order npoly * gaussian + switching function
! set r r-r_e
r = x
r = r - p(1)
! set up skewing function:
skew = 0.5_dp*p(3)*(dtanh(dabs(p(4))*(r - p(6))) + 1.0_dp)
! set up gaussian function:
gaus = dexp(-dabs(p(5))*(r - p(6))**2)
! set up power series:
poly = 0.0_dp
do i = 0, npoly(ii) - 1
poly = poly + p(7 + i)*(r - p(6))**i
end do
! set up full exponent function:
f = dabs(p(2)) + skew + gaus*poly
end function
!----------------------------------------------------------------------------------------------------
pure function xproduct(a, b) result(axb)
real(dp), intent(in) :: a(3), b(3)
real(dp) :: axb(3) !crossproduct a x b
axb(1) = a(2)*b(3) - a(3)*b(2)
axb(2) = a(3)*b(1) - a(1)*b(3)
axb(3) = a(1)*b(2) - a(2)*b(1)
end function xproduct
pure function normalized(v) result(r)
real(dp), intent(in) :: v(:)
real(dp) :: r(size(v))
r = v/norm(v)
end function normalized
pure function norm(v) result(n)
real(dp), intent(in) :: v(:)
real(dp) n
n = dsqrt(sum(v(:)**2))
end function norm
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! % FUNCTION Project_Point_Into_Plane(x,n,r0) result(p)
! % return the to n orthogonal part of a vector x-r0
! % p: projected point in plane
! % x: point being projected
! % n: normalvector of plane
! % r0: Point in plane
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pure function project_point_into_plane(x, n, r0) result(p)
real(dp), intent(in) :: x(:), n(:), r0(:)
real(dp) :: p(size(x)), xs(size(x))
xs = x - r0
p = xs - plane_to_point(x, n, r0)
end function project_point_into_plane
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! % Function Plane_To_Point(x,n,r0) result(p)
! % p: part of n in x
! % x: point being projected
! % n: normalvector of plane
! % r0: Point in plane
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pure function plane_to_point(x, n, r0) result(p)
real(dp), intent(in) :: x(:), n(:), r0(:)
real(dp) p(size(x)), xs(size(x)), nn(size(n))
nn = normalized(n)
xs = x - r0
p = dot_product(nn, xs)*nn
end function plane_to_point
subroutine check_coordinates(q)
! check for faulty kartesain coordinates
real(dp), intent(in) :: q(:)
integer(idp) :: i
if (all(abs(q) <= epsilon(0.0_dp))) then
stop 'Error (ctrans): all kartesian coordinates are<=1d-8'
end if
do i = 1, 9, 3
if (all(abs(q(i:i + 2)) <= epsilon(0.0_dp))) then
write (*, *) q
stop 'Error(ctrans):kartesian coordinates zero for one atom'
end if
end do
end subroutine
pure function rotor_a_to_z(a, z) result(r)
real(dp), intent(in) :: a(3), z(3)
real(dp) :: r(3, 3)
real(dp) :: alpha
real(dp) :: s1(3), s(3, 3), rotor(3, 3)
s1 = xproduct(normalized(a), normalized(z))
alpha = asin(norm(s1))
s(:, 1) = normalized(s1)
s(:, 2) = normalized(z)
s(:, 3) = xproduct(s1, z)
rotor = init_rotor(alpha, 0.0_dp, 0.0_dp)
r = matmul(s, matmul(rotor, transpose(s)))
end function
! function returning Rz(gamma) * Ry(beta) * Rx(alpha) for basis order xyz
pure function init_rotor(alpha, beta, gamma) result(rotor)
real(dp), intent(in) :: alpha, beta, gamma
real(dp) :: rotor(3, 3)
rotor = 0.0_dp
rotor(1, 1) = dcos(beta)*dcos(gamma)
rotor(1, 2) = dsin(alpha)*dsin(beta)*dcos(gamma)&
&- dcos(alpha)*dsin(gamma)
rotor(1, 3) = dcos(alpha)*dsin(beta)*dcos(gamma)&
&+ dsin(alpha)*dsin(gamma)
rotor(2, 1) = dcos(beta)*dsin(gamma)
rotor(2, 2) = dsin(alpha)*dsin(beta)*dsin(gamma)&
&+ dcos(alpha)*dcos(gamma)
rotor(2, 3) = dcos(alpha)*dsin(beta)*dsin(gamma)&
&- dsin(alpha)*dcos(gamma)
rotor(3, 1) = -dsin(beta)
rotor(3, 2) = dsin(alpha)*dcos(beta)
rotor(3, 3) = dcos(alpha)*dcos(beta)
end function init_rotor
pure function create_plane(a, b, c) result(n)
real(dp), intent(in) :: a(3), b(3), c(3)
real(dp) :: n(3)
real(dp) :: axb(3), bxc(3), cxa(3)
axb = xproduct(a, b)
bxc = xproduct(b, c)
cxa = xproduct(c, a)
n = normalized(axb + bxc + cxa)
end function create_plane
function symmetrize(q1, q2, q3, sym) result(s)
real(dp), intent(in) :: q1, q2, q3
character, intent(in) :: sym
real(dp) :: s
select case (sym)
case ('a')
s = (q1 + q2 + q3)*sq3
case ('x')
s = sq6*(2.0_dp*q1 - q2 - q3)
case ('y')
s = sq2*(q2 - q3)
case default
write (*, *) 'ERROR: no rule for symmetrize with sym=', sym
stop
end select
end function symmetrize
subroutine construct_HBend(ex, ey, ph1, ph2, ph3, x_axis, y_axis)
real(dp), intent(in) :: ph1(3), ph2(3), ph3(3)
real(dp), intent(in) :: x_axis(3), y_axis(3)
real(dp), intent(out) :: ex, ey
real(dp) :: x1, y1, alpha1
real(dp) :: x2, y2, alpha2
real(dp) :: x3, y3, alpha3
! get x and y components of projected points
x1 = dot_product(ph1, x_axis)
y1 = dot_product(ph1, y_axis)
x2 = dot_product(ph2, x_axis)
y2 = dot_product(ph2, y_axis)
x3 = dot_product(ph3, x_axis)
y3 = dot_product(ph3, y_axis)
! -> calculate H deformation angles
alpha3 = datan2(y2, x2)
alpha2 = -datan2(y3, x3) !-120*ang2rad
! write(*,*)' atan2'
! write(*,*) 'alpha2:' , alpha2/ang2rad
! write(*,*) 'alpha3:' , alpha3/ang2rad
if (alpha2 .lt. 0) alpha2 = alpha2 + pi2
if (alpha3 .lt. 0) alpha3 = alpha3 + pi2
alpha1 = (pi2 - alpha2 - alpha3)
! write(*,*)' fixed break line'
! write(*,*) 'alpha1:' , alpha1/ang2rad
! write(*,*) 'alpha2:' , alpha2/ang2rad
! write(*,*) 'alpha3:' , alpha3/ang2rad
alpha1 = alpha1 !- 120.0_dp*ang2rad
alpha2 = alpha2 !- 120.0_dp*ang2rad
alpha3 = alpha3 !- 120.0_dp*ang2rad
! write(*,*)' delta alpha'
! write(*,*) 'alpha1:' , alpha1/ang2rad
! write(*,*) 'alpha2:' , alpha2/ang2rad
! write(*,*) 'alpha3:' , alpha3/ang2rad
! write(*,*)
! construct symmetric and antisymmetric H angles
ex = symmetrize(alpha1, alpha2, alpha3, 'x')
ey = symmetrize(alpha1, alpha2, alpha3, 'y')
end subroutine construct_HBend
pure function construct_umbrella(nh1, nh2, nh3, n)&
&result(umb)
real(dp), intent(in) :: nh1(3), nh2(3), nh3(3)
real(dp), intent(in) :: n(3)
real(dp) :: umb
real(dp) :: theta(3)
! calculate projections for umberella angle
theta(1) = dacos(dot_product(n, nh1))
theta(2) = dacos(dot_product(n, nh2))
theta(3) = dacos(dot_product(n, nh3))
! construct umberella angle
umb = sum(theta(1:3))/3.0_dp - 90.0_dp*ang2rad
end function construct_umbrella
pure subroutine construct_sphericals&
&(theta, phi, cf, xaxis, yaxis, zaxis)
real(dp), intent(in) :: cf(3), xaxis(3), yaxis(3), zaxis(3)
real(dp), intent(out) :: theta, phi
real(dp) :: x, y, z, v(3)
v = normalized(cf)
x = dot_product(v, normalized(xaxis))
y = dot_product(v, normalized(yaxis))
z = dot_product(v, normalized(zaxis))
theta = dacos(z)
phi = -datan2(y, x)
end subroutine construct_sphericals
subroutine int2kart(internal, kart)
real(dp), intent(in) :: internal(6)
real(dp), intent(out) :: kart(9)
real(dp) :: h1x, h1y, h1z
real(dp) :: h2x, h2y, h2z
real(dp) :: h3x, h3y, h3z
real(dp) :: dch0, dch1, dch2, dch3
real(dp) :: a1, a2, a3, wci
kart = 0.0_dp
dch1 = dchequi + sq3*internal(1) + 2*sq6*internal(2)
dch2 = dchequi + sq3*internal(1) - sq6*internal(2) + sq2*internal(3)
dch3 = dchequi + sq3*internal(1) - sq6*internal(2) - sq2*internal(3)
a1 = 2*sq6*internal(4)
a2 = -sq6*internal(4) + sq2*internal(5)
a3 = -sq6*internal(4) - sq2*internal(5)
wci = internal(6)
! Berechnung kartesische Koordinaten
! -----------------------
h1x = dch1*cos(wci*ang2rad)
h1y = 0.0
h1z = -dch1*sin(wci*ang2rad)
h3x = dch2*cos((a2 + 120)*ang2rad)*cos(wci*ang2rad)
h3y = dch2*sin((a2 + 120)*ang2rad)*cos(wci*ang2rad)
h3z = -dch2*sin(wci*ang2rad)
h2x = dch3*cos((-a3 - 120)*ang2rad)*cos(wci*ang2rad)
h2y = dch3*sin((-a3 - 120)*ang2rad)*cos(wci*ang2rad)
h2z = -dch3*sin(wci*ang2rad)
kart(1) = h1x
kart(2) = h1y
kart(3) = h1z
kart(4) = h2x
kart(5) = h2y
kart(6) = h2z
kart(7) = h3x
kart(8) = h3y
kart(9) = h3z
end subroutine int2kart
end module ctrans_mod