PROGRESS  master
prg_syrotation_mod.F90
Go to the documentation of this file.
1 
6 
7  implicit none
8 
9  private
10 
11  integer, parameter :: dp = kind(1.0d0)
12 
14  type, public :: rotation_type
15  character(20) :: jobname
16  character(50) :: typeofrot
18  integer :: patom1
20  integer :: patom2
22  integer :: catom
24  integer :: catom2
26  real(dp) :: pq1(3)
28  real(dp) :: pq2(3)
30  real(dp) :: v1(3)
32  real(dp) :: v2(3)
34  real(dp) :: vq(3)
36  integer :: rotate_atoms(2)
37  end type rotation_type
38 
40 
41 contains
42 
45  subroutine prg_parse_rotation(rot, filename)
46 
48  implicit none
49  integer, parameter :: nkey_char = 2, nkey_int = 6, nkey_re = 15, nkey_log = 1
50  character(20) :: jobname
51  character(len=*) :: filename
52  type(rotation_type), intent(inout) :: rot
53 
54  !Library of keywords with the respective defaults.
55  character(len=50), parameter :: keyvector_char(nkey_char) = [character(len=100) :: &
56  'Jobname=','TypeOfRotation=']
57  character(len=100) :: valvector_char(nkey_char) = [character(len=100) :: &
58  'MyJob','DirToDir']
59 
60  character(len=50), parameter :: keyvector_int(nkey_int) = [character(len=50) :: &
61  'Atom1=','Atom2=','CAtom=','CAtom2=','ListToRot1=','ListToRot2=']
62  integer :: valvector_int(nkey_int) = (/ &
63  0,0,0,0,1,10000000/)
64 
65  character(len=50), parameter :: keyvector_re(nkey_re) = [character(len=50) :: &
66  'PQ1X=','PQ1Y=','PQ1Z=','PQ2X=','PQ2Y=','PQ2Z=','V1X=','V1Y=', &
67  &'V1Z=','V2X=','V2Y=','V2Z=','VQX=','VQY=','VQZ=']
68  real(dp) :: valvector_re(nkey_re) = (/&
69  0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0/)
70 
71  character(len=50), parameter :: keyvector_log(nkey_log) = [character(len=100) :: &
72  'DUMMY=']
73  logical :: valvector_log(nkey_log) = (/&
74  .false./)
75 
76  !Start and stop characters
77  character(len=50), parameter :: startstop(2) = [character(len=50) :: &
78  'ROTATION{', '}']
79 
80  call prg_parsing_kernel(keyvector_char,valvector_char&
81  ,keyvector_int,valvector_int,keyvector_re,valvector_re,&
82  keyvector_log,valvector_log,trim(filename),startstop)
83 
84  rot%jobname= valvector_char(1)
85  rot%typeofrot= valvector_char(2)
86 
87  rot%patom1= valvector_int(1)
88  rot%patom2= valvector_int(2)
89  rot%catom= valvector_int(3)
90  rot%catom2= valvector_int(4)
91  rot%rotate_atoms(1)= valvector_int(5)
92  rot%rotate_atoms(2)= valvector_int(6)
93 
94  rot%pq1(1)= valvector_re(1)
95  rot%pq1(2)= valvector_re(2)
96  rot%pq1(3)= valvector_re(3)
97 
98  rot%pq2(1)= valvector_re(4)
99  rot%pq2(2)= valvector_re(5)
100  rot%pq2(3)= valvector_re(6)
101 
102  rot%v1(1)= valvector_re(7)
103  rot%v1(2)= valvector_re(8)
104  rot%v1(3)= valvector_re(9)
105 
106  rot%v2(1)= valvector_re(10)
107  rot%v2(2)= valvector_re(11)
108  rot%v2(3)= valvector_re(12)
109 
110  rot%vQ(1)= valvector_re(13)
111  rot%vQ(2)= valvector_re(14)
112  rot%vQ(3)= valvector_re(15)
113 
114  end subroutine prg_parse_rotation
115 
116 
138  subroutine prg_rotate(rot,r,verbose)
139  integer :: natoms, catom, catom2, i
140  integer :: k, l, patom1, patom2
141  integer :: rotate_atoms(2)
142  integer, intent(in) :: verbose
143  real(dp) :: mat(3,3), p1minusc1(3), vtr(3)
144  real(dp) :: alpha, angle, d, deformation
145  real(dp) :: dotprod, dv1, dv2, hinge(3)
146  real(dp) :: hinge2, hingedotp1minusc1, pq1(3), pq2(3)
147  real(dp) :: pi, v1(3), v11(3), v1mod
148  real(dp) :: v1x, v1y, v1z, v1zversor
149  real(dp) :: v2(3), v22(3), vn(3), vq(3)
150  real(dp) :: vad(3), vdirn(3), vp(3), vr11(3)
151  real(dp) :: vr2(3), vr22(3)
152  real(dp), allocatable :: rr(:,:), v(:,:), vr(:,:), vr1(:,:)
153  real(dp), intent(inout) :: r(:,:)
154  type(rotation_type), intent(in) :: rot
155 
156  pi=3.1415926535897993d0
157  alpha= 0.0_dp
158  alpha= (alpha/180.0_dp)*pi
159 
160  natoms = size(r, dim=2)
161 
162  allocate(v(3,natoms))
163  allocate(vr(3,natoms))
164  allocate(vr1(3,natoms))
165  allocate(rr(3,natoms))
166 
167  vr=0.0_dp
168  vr1=0.0_dp
169  rr=0.0_dp
170  v=0.0_dp
171 
172  patom1=rot%patom1 !Rotation atom indices
173  patom2=rot%patom2
174  catom=rot%catom !Rotation center
175  catom2=rot%catom2 !Second rotation center
176 
177  pq1(1)=rot%pq1(1) !Initial director point
178  pq1(2)=rot%pq1(2)
179  pq1(3)=rot%pq1(3)
180 
181  pq2(1)=rot%pq2(1) !Final director point
182  pq2(2)=rot%pq2(2)
183  pq2(3)=rot%pq2(3)
184 
185  v1(1)=rot%v1(1) !Initial anchored vector
186  v1(2)=rot%v1(2)
187  v1(3)=rot%v1(3)
188 
189  v2(1)=rot%v2(1) !Final anchored vector
190  v2(2)=rot%v2(2)
191  v2(3)=rot%v2(3)
192 
193  vq(1)=rot%vQ(1) !Rotation center
194  vq(2)=rot%vQ(2)
195  vq(3)=rot%vQ(3)
196 
197  rotate_atoms(1)=rot%rotate_atoms(1) !index for first rotated atom
198  rotate_atoms(2)=rot%rotate_atoms(2)
199 
200  if(rotate_atoms(2).gt.natoms) rotate_atoms(2)=natoms
201 
202  if(patom1.ne.0)then
203  pq1(1)=r(1,patom1)
204  pq1(2)=r(2,patom1)
205  pq1(3)=r(3,patom1)
206 
207  pq2(1)=r(1,patom2)
208  pq2(2)=r(2,patom2)
209  pq2(3)=r(3,patom2)
210 
211  vq(1)=r(1,catom)
212  vq(2)=r(2,catom)
213  vq(3)=r(3,catom)
214  endif
215 
216  if(catom2.ne.0)then
217  hinge=r(:,catom2)-r(:,catom)
218  hinge2=hinge(1)**2+hinge(2)**2+hinge(3)**2
219  p1minusc1=pq1(:)-r(:,catom)
220  hingedotp1minusc1=hinge(1)*p1minusc1(1) + hinge(2)*p1minusc1(2) + hinge(3)*p1minusc1(3)
221  vq(:)=r(:,catom) + hinge(:)*hingedotp1minusc1/hinge2
222  write(*,*)vq(:)
223  write(*,*)hinge(:)
224  write(*,*)hingedotp1minusc1/hinge2
225  endif
226 
227  if(v1(1).eq.0.0_dp.and.v1(2).eq.0.0_dp.and.v1(3).eq.0.0_dp)then
228  v1=pq1-vq
229  endif
230 
231  if(v2(1).eq.0.0_dp.and.v2(2).eq.0.0_dp.and.v2(3).eq.0.0_dp)then
232  v2=pq2-vq
233  endif
234 
235  vtr(1)=0.0_dp !Translation
236  vtr(2)=0.0_dp
237  vtr(3)=0.0_dp
238 
239  dv1=dsqrt(v1(1)**2+v1(2)**2+v1(3)**2) !Angle between v1 y v2
240  dv2=dsqrt(v2(1)**2+v2(2)**2+v2(3)**2)
241  dotprod=v1(1)*v2(1)+v1(2)*v2(2)+v1(3)*v2(3)
242  alpha=-acos(dotprod/(dv1*dv2))
243 
244  if(alpha.eq.0.0_dp)write(*,*)'V1 and V2 are in the same direction'
245  if(abs(alpha-pi).lt.1.0e-10)write(*,*)'V1 and V2 are in the same direction'
246 
247  if(verbose >= 1) write(*,*)'alpha=',alpha
248 
249  do i=rotate_atoms(1),rotate_atoms(2)
250  r(1,i) = r(1,i)-vq(1)
251  r(2,i) = r(2,i)-vq(2)
252  r(3,i) = r(3,i)-vq(3)
253  enddo
254 
255  vad=v1+v2
256 
257  vn(1)=v1(2)*v2(3)-v1(3)*v2(2)
258  vn(2)=-v1(1)*v2(3)+v2(1)*v1(3)
259  vn(3)=v1(1)*v2(2)-v2(1)*v1(2)
260 
261  vp(1)=vn(2)*vad(3)-vn(3)*vad(2)
262  vp(2)=-vn(1)*vad(3)+vad(1)*vn(3)
263  vp(3)=vn(1)*vad(2)-vad(1)*vn(2)
264 
265  d=dsqrt(vad(1)**2+vad(2)**2+vad(3)**2)
266  vad=vad/d
267 
268  d=dsqrt(vp(1)**2+vp(2)**2+vp(3)**2)
269  vp=vp/d
270 
271  d=dsqrt(vn(1)**2+vn(2)**2+vn(3)**2)
272  vn=vn/d
273 
274  !Projection onto vad vp and vn
275 
276  do i=rotate_atoms(1),rotate_atoms(2)
277  v(1,i)=r(1,i)*vad(1)+r(2,i)*vad(2)+r(3,i)*vad(3)
278  v(2,i)=r(1,i)*vp(1)+r(2,i)*vp(2)+r(3,i)*vp(3)
279  v(3,i)=r(1,i)*vn(1)+r(2,i)*vn(2)+r(3,i)*vn(3)
280  enddo
281 
282  !Rotation matrix
283 
284  mat(1,1)=cos(alpha)
285  mat(2,1)=sin(alpha)
286  mat(3,1)=0.0_dp
287  mat(1,2)=-sin(alpha)
288  mat(2,2)=cos(alpha)
289  mat(3,2)=0.0_dp
290  mat(1,3)=0.0_dp
291  mat(2,3)=0.0_dp
292  mat(3,3)=1.0_dp
293 
294  !Rotation
295 
296  do l=rotate_atoms(1),rotate_atoms(2)
297  do i=1,3
298  do k=1,3
299  vr(i,l)=vr(i,l)+mat(k,i)*v(k,l)
300  enddo
301  enddo
302  enddo
303 
304  !Basis set change
305 
306  do i=rotate_atoms(1),rotate_atoms(2)
307  vr1(1,i)=vr(1,i)*vad(1) + vr(2,i)*vp(1) + vr(3,i)*vn(1)
308  vr1(2,i)=vr(1,i)*vad(2) + vr(2,i)*vp(2) + vr(3,i)*vn(2)
309  vr1(3,i)=vr(1,i)*vad(3) + vr(2,i)*vp(3) + vr(3,i)*vn(3)
310  enddo
311 
312  if(alpha.eq.0.0_dp)vr1=r
313  if(abs(alpha-pi).lt.1.0e-10)vr1=-r
314 
315  do i=rotate_atoms(1),rotate_atoms(2)
316  rr(1,i)=vr1(1,i)+vq(1)+vtr(1)
317  rr(2,i)=vr1(2,i)+vq(2)+vtr(2)
318  rr(3,i)=vr1(3,i)+vq(3)+vtr(3)
319  enddo
320 
321  do i=rotate_atoms(1),rotate_atoms(2)
322  r(1,i)=rr(1,i)
323  r(2,i)=rr(2,i)
324  r(3,i)=rr(3,i)
325  enddo
326 
327  deformation=0.0d0
328 
329  do i=rotate_atoms(1),rotate_atoms(2)
330  d=dsqrt((r(1,1)-r(1,i))**2+(r(2,1)-r(2,i))**2+(r(3,1)-r(3,i))**2)
331  deformation=deformation + d
332  d=dsqrt((rr(1,1)-rr(1,i))**2+(rr(2,1)-rr(2,i))**2+(rr(3,1)-rr(3,i))**2)
333  deformation=deformation - d
334  enddo
335 
336  if(deformation >= 0.001_dp)then
337  write(*,*)'Rotation failed ...'
338  write(*,*)'Deformation=',deformation
339  endif
340 
341  end subroutine prg_rotate
342 
343 end module prg_syrotation_mod
Some general parsing functions.
subroutine, public prg_parsing_kernel(keyvector_char, valvector_char, keyvector_int, valvector_int, keyvector_re, valvector_re, keyvector_log, valvector_log, filename, startstop)
The general parsing function. It is used to vectorize a set of "keywords" "value" pairs as included i...
A module to rotate the coordinates of a sybsystem in chemical systems.
subroutine, public prg_rotate(rot, r, verbose)
Rotation routine.
subroutine, public prg_parse_rotation(rot, filename)
The parser for rotation.
integer, parameter dp