23 INTEGER,
PARAMETER :: default_error_unit = 0, &
24 default_input_unit = 5, &
25 default_output_unit = 6
26 INTEGER :: error_unit = default_error_unit, &
27 output_unit = default_output_unit
31 CHARACTER(LEN=*),
PARAMETER :: routinen =
"xyz2dcd", &
32 version_info = routinen//
" v1.0 (30.06.2020, Matthias Krack)"
34 INTEGER,
PARAMETER :: dp = selected_real_kind(14, 200), &
35 sp = selected_real_kind(6, 30)
36 INTEGER,
PARAMETER :: default_string_length = 240, &
37 cell_file_unit = 10, &
39 xyz_file_unit = default_input_unit
41 REAL(kind=dp),
PARAMETER :: pi = 3.14159265358979323846264338_dp
43 REAL(kind=dp),
PARAMETER :: degree = 180.0_dp/pi
46 CHARACTER(LEN=default_string_length) :: arg, cell_file_name, dcd_file_name, message, remark1, remark2, remark_xyz, &
48 CHARACTER(LEN=5),
DIMENSION(:),
ALLOCATABLE :: atomic_label
49 CHARACTER(LEN=80),
DIMENSION(2) :: remark_dcd
50 INTEGER :: first_frame, i, iarg, iatom, iskip, istat, istep, j, &
51 last_frame, narg, natom, nframe, nframe_read, nremark, stride
52 LOGICAL :: apply_pbc, debug, dump_frame, exists, have_cell_file, have_cell_info, &
53 info, pbc0, print_atomic_displacements, print_scaled_coordinates, &
54 print_scaled_pbc_coordinates, trace_atoms
55 REAL(kind=dp) :: alpha, beta, dt, eps_out_of_box,
gamma, tstep
56 REAL(kind=dp),
DIMENSION(3) :: a, abc, b, c
57 REAL(kind=dp),
DIMENSION(:),
ALLOCATABLE :: atomic_displacement
58 REAL(kind=dp),
DIMENSION(3, 3) :: h, hinv
59 REAL(kind=dp),
DIMENSION(:, :),
ALLOCATABLE :: r, r_pbc, r0, s, s_pbc
64 have_cell_file = .false.
65 have_cell_info = .false.
69 print_scaled_coordinates = .false.
70 print_atomic_displacements = .false.
71 print_scaled_pbc_coordinates = .false.
83 eps_out_of_box = -huge(0.0_dp)
89 narg = command_argument_count()
93 CALL abort_program(routinen,
"No input file(s) specified")
99 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
104 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
105 READ (unit=arg, fmt=*, err=100) h(i, i)
107 have_cell_info = .true.
109100
CALL abort_program(routinen,
"Reading -abc arguments (3 reals are expected)")
114 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
115 READ (unit=arg, fmt=*, err=101) h(j, i)
118 have_cell_info = .true.
120101
CALL abort_program(routinen,
"Reading -cell arguments (9 reals are expected)")
121 CASE (
"-cell_file",
"-cf")
123 CALL get_command_argument(number=iarg,
VALUE=cell_file_name, status=istat)
124 have_cell_file = .true.
125 have_cell_info = .true.
127 CASE (
"-df",
"-dcd_file")
129 CALL get_command_argument(number=iarg,
VALUE=dcd_file_name, status=istat)
131 CASE (
"-debug",
"-d")
135 CASE (
"-displacements",
"-disp")
136 print_atomic_displacements = .true.
139 error_unit = output_unit
141 CASE (
"-first_frame",
"-first",
"-ff")
143 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
144 READ (unit=arg, fmt=*, err=102) first_frame
145 IF (first_frame <= 0)
THEN
146 CALL abort_program(routinen,
"Invalid number for first frame specified: "// &
147 "first_frame must be greater than zero")
150102
CALL abort_program(routinen,
"Invalid number for first frame specified "// &
151 "(an integer number greater than zero is expected)")
158 CASE (
"-last_frame",
"-last",
"-lf")
160 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
161 READ (unit=arg, fmt=*, err=103) last_frame
162 IF (last_frame <= 0)
THEN
163 CALL abort_program(routinen,
"Invalid number for last frame specified: "// &
164 "last_frame must be greater than zero")
167103
CALL abort_program(routinen,
"Invalid number for last frame specified "// &
168 "(an integer number greater than zero is expected)")
177 CASE (
"-scaled_coordinates",
"-sc")
178 print_scaled_coordinates = .true.
180 CASE (
"-scaled_pbc_coordinates",
"-spc")
181 print_scaled_pbc_coordinates = .true.
185 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
186 READ (unit=arg, fmt=*, err=104) stride
188 CALL abort_program(routinen,
"Invalid stride for frame dump specified: stride must be greater than zero")
191104
CALL abort_program(routinen,
"Invalid stride for frame dump specified "// &
192 "(an integer number greater than 0 is expected)")
193 CASE (
"-trace_atoms")
195 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
196 READ (unit=arg, fmt=*, err=105) eps_out_of_box
197 IF (eps_out_of_box <= 0.0_dp)
THEN
198 CALL abort_program(routinen,
"Invalid threshold value for -trace_atoms flag specified")
202105
CALL abort_program(routinen,
"Invalid threshold value for -trace_atoms flag specified")
204 IF (arg(1:1) ==
"-")
THEN
206 CALL abort_program(routinen,
"Unknown command line flag """//trim(arg)//
""" found")
214 IF (.NOT. have_cell_info)
THEN
215 CALL abort_program(routinen,
"No cell information available. Neither -abc, -cell, nor -cell_file flag found")
217 IF (first_frame > last_frame)
THEN
218 CALL abort_program(routinen,
"Number of first frame greater than number of last frame")
220 IF (.NOT. apply_pbc .AND. trace_atoms)
THEN
221 CALL abort_program(routinen,
"The -trace_atoms flag requires the specification of a -pbc flag")
223 IF (print_scaled_coordinates .AND. print_scaled_pbc_coordinates)
THEN
224 CALL abort_program(routinen,
"The -sc flag and the -spc flag are incompatible")
226 IF (.NOT. apply_pbc .AND. print_scaled_coordinates)
THEN
227 CALL abort_program(routinen,
"The -sc flag requires the specification of a -pbc flag")
229 IF (.NOT. apply_pbc .AND. print_scaled_pbc_coordinates)
THEN
230 CALL abort_program(routinen,
"The -spc flag requires the specification of a -pbc flag")
234 IF (have_cell_file)
THEN
235 INQUIRE (file=cell_file_name, exist=exists)
236 IF (.NOT. exists)
CALL abort_program(routinen,
"The specified cell file <"// &
237 trim(cell_file_name)//
"> does not exist")
238 OPEN (unit=cell_file_unit, &
239 file=cell_file_name, &
241 access=
"SEQUENTIAL", &
246 IF (istat /= 0)
CALL abort_program(routinen,
"The cell file <"// &
247 trim(cell_file_name)//
"> could not be opened")
248 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Reading cell file : "//trim(cell_file_name)
252 INQUIRE (file=xyz_file_name, exist=exists)
253 IF (.NOT. exists)
CALL abort_program(routinen,
"The specified XYZ file <"// &
254 trim(xyz_file_name)//
"> does not exist")
255 OPEN (unit=xyz_file_unit, &
256 file=xyz_file_name, &
258 access=
"SEQUENTIAL", &
263 IF (istat /= 0)
CALL abort_program(routinen,
"The XYZ file <"// &
264 trim(xyz_file_name)//
"> could not be opened")
265 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Reading XYZ file : "//trim(xyz_file_name)
268 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) arg
270 CALL abort_program(routinen,
"Reading the first line of the current frame from the XYZ file <"// &
271 trim(xyz_file_name)//
"> failed")
273 IF (arg(1:1) ==
"#")
THEN
274 READ (unit=arg, fmt=*) string, natom
276 READ (unit=arg, fmt=*) natom
279 CALL abort_program(routinen,
"Reading the number of atoms from the XYZ file failed")
281 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) remark_xyz
282 IF (istat /= 0)
CALL abort_program(routinen,
"Reading the second line from the XYZ file <"// &
283 trim(xyz_file_name)//
"> failed")
284 rewind(unit=xyz_file_unit)
287 IF (len_trim(dcd_file_name) == 0)
THEN
288 i = len_trim(xyz_file_name)
289 IF (xyz_file_name(i - 2:i) ==
"xyz")
THEN
290 dcd_file_name = xyz_file_name(1:i - 3)//
"dcd"
292 dcd_file_name = xyz_file_name(1:i)//
".dcd"
295 INQUIRE (file=dcd_file_name, exist=exists)
296 IF (exists)
CALL abort_program(routinen,
"The DCD file "// &
297 trim(dcd_file_name)//
" exists already")
298 OPEN (unit=dcd_file_unit, &
299 file=dcd_file_name, &
301 access=
"SEQUENTIAL", &
302 form=
"UNFORMATTED", &
305 IF (istat /= 0)
CALL abort_program(routinen,
"The unformatted DCD output file "// &
306 trim(dcd_file_name)//
" could not be opened")
307 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Writing DCD file : "//trim(dcd_file_name)
314 WRITE (unit=dcd_file_unit)
"CORD", 0, istep, iskip, 0, 0, 0, 0, 0, 0, real(dt, kind=sp), &
315 1, 0, 0, 0, 0, 0, 0, 0, 0, 24
316 remark1 =
"REMARK CORD"//
" DCD file created by "//trim(version_info)
317 remark2 =
"REMARK "//trim(adjustl(remark_xyz))
318 WRITE (unit=dcd_file_unit) 2, remark1(1:80), remark2(1:80)
319 WRITE (unit=dcd_file_unit) natom
322 ALLOCATE (r(natom, 3), stat=istat)
323 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r failed")
326 ALLOCATE (atomic_label(natom), stat=istat)
327 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the vector atomic_label failed")
335 IF (nframe < first_frame)
THEN
338 IF (
modulo(nframe - first_frame, stride) == 0)
THEN
346 IF (have_cell_file)
THEN
348 READ (unit=cell_file_unit, fmt=*, iostat=istat) arg
349 IF (istat < 0)
EXIT frame_loop
351 CALL abort_program(routinen,
"Reading line from cell file")
353 IF (arg(1:1) ==
"#")
THEN
356 backspace(unit=cell_file_unit)
360 READ (unit=cell_file_unit, fmt=*, iostat=istat) istep, tstep, ((h(j, i), j=1, 3), i=1, 3)
362 CALL abort_program(routinen,
"Reading information from cell file")
367 IF (have_cell_file .OR. (nframe == 1))
THEN
371 abc(1) = norm2(a(1:3))
372 abc(2) = norm2(b(1:3))
373 abc(3) = norm2(c(1:3))
374 alpha = angle(b(1:3), c(1:3))*degree
375 beta = angle(a(1:3), c(1:3))*degree
376 gamma = angle(a(1:3), b(1:3))*degree
380 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) arg
381 IF (istat < 0)
EXIT frame_loop
383 CALL abort_program(routinen,
"Reading the first line of the current frame from the XYZ file failed")
385 IF (arg(1:1) ==
"#")
THEN
386 READ (unit=arg, fmt=*) string, natom
388 READ (unit=arg, fmt=*) natom
391 CALL abort_program(routinen,
"Reading the number of atoms from the XYZ file failed")
393 IF (natom /=
SIZE(r, 1))
THEN
394 CALL abort_program(routinen,
"Number of atoms changed for the current frame")
398 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) remark_xyz
399 IF (istat /= 0)
CALL abort_program(routinen,
"Reading the second line from the XYZ file failed")
402 IF (info .AND. dump_frame)
THEN
403 WRITE (unit=error_unit, fmt=
"(A,/,A,I0)") &
404 "#",
"# Frame number : ", nframe
405 WRITE (unit=error_unit, fmt=
"(A,/,(A,F12.6))") &
407 "# a [Angstrom] : ", abc(1), &
408 "# b [Angstrom] : ", abc(2), &
409 "# c [Angstrom] : ", abc(3), &
410 "# alpha [degree] : ", alpha, &
411 "# beta [degree] : ", beta, &
412 "# gamma [degree] : ",
gamma
416 WRITE (unit=output_unit, fmt=
"(T2,I0)") natom
417 WRITE (unit=output_unit, fmt=
"(A)") trim(adjustl(remark_xyz))
423 READ (unit=xyz_file_unit, fmt=*) arg
424 IF (arg(1:1) ==
"#")
THEN
427 backspace(unit=xyz_file_unit)
430 READ (unit=xyz_file_unit, fmt=*, iostat=istat) atomic_label(iatom), r(iatom, 1:3)
433 WRITE (unit=message, fmt=
"(A,I0,A,I0,A)") &
434 "Reading line ", iatom + 2,
" of the current frame from XYZ file (atom ", iatom,
") failed"
435 CALL abort_program(routinen, trim(message))
437 CALL uppercase(atomic_label(iatom) (1:1))
438 IF (len_trim(atomic_label(iatom)) > 1)
CALL lowercase(atomic_label(iatom) (2:2))
439 atomic_label(iatom) = trim(adjustl(atomic_label(iatom)))
440 IF (iatom == natom)
EXIT
445 IF ((nframe == 1) .AND. print_atomic_displacements)
THEN
446 IF (.NOT.
ALLOCATED(r0))
THEN
447 ALLOCATE (r0(natom, 3), stat=istat)
448 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r0 failed")
451 IF (.NOT.
ALLOCATED(atomic_displacement))
THEN
452 ALLOCATE (atomic_displacement(natom), stat=istat)
454 CALL abort_program(routinen,
"Allocation of the vector atomic_displacement failed")
457 atomic_displacement(:) = 0.0_dp
463 IF (.NOT.
ALLOCATED(r_pbc))
THEN
464 ALLOCATE (r_pbc(natom, 3), stat=istat)
465 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r_pbc failed")
468 IF (.NOT.
ALLOCATED(s))
THEN
469 ALLOCATE (s(natom, 3), stat=istat)
470 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array s failed")
473 IF (.NOT.
ALLOCATED(s_pbc))
THEN
474 ALLOCATE (s_pbc(natom, 3), stat=istat)
475 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array s_pbc failed")
478 CALL pbc(r, r_pbc, s, s_pbc, h, hinv, debug, info, pbc0)
479 CALL write_out_of_box_atoms(atomic_label, r, s, eps_out_of_box, h)
481 r(:, :) = r_pbc(:, :)
485 IF (print_atomic_displacements)
THEN
487 atomic_displacement(iatom) = sqrt((r(iatom, 1) - r0(iatom, 1))**2 + &
488 (r(iatom, 2) - r0(iatom, 2))**2 + &
489 (r(iatom, 3) - r0(iatom, 3))**2)
493 IF (print_scaled_coordinates)
THEN
495 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), s(iatom, 1:3)
497 ELSE IF (print_scaled_pbc_coordinates)
THEN
499 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), s_pbc(iatom, 1:3)
503 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), r(iatom, 1:3)
508 WRITE (unit=dcd_file_unit) abc(1),
gamma, abc(2), beta, alpha, abc(3)
511 WRITE (unit=dcd_file_unit) real(r(1:natom, i), kind=sp)
513 nframe_read = nframe_read + 1
517 IF (nframe >= last_frame)
EXIT frame_loop
524 IF (have_cell_file)
CLOSE (unit=cell_file_unit)
525 CLOSE (unit=dcd_file_unit)
526 CLOSE (unit=xyz_file_unit)
529 WRITE (unit=error_unit, fmt=
"(A,/,A,I0)") &
531 "# Frames processed : ", nframe_read
532 WRITE (unit=error_unit, fmt=
"(A)") &
534 "# Normal termination of "//trim(version_info)
538 IF (
ALLOCATED(atomic_label))
DEALLOCATE (atomic_label)
539 IF (
ALLOCATED(atomic_displacement))
DEALLOCATE (atomic_displacement)
540 IF (
ALLOCATED(r))
DEALLOCATE (r)
541 IF (
ALLOCATED(r0))
DEALLOCATE (r0)
542 IF (
ALLOCATED(r_pbc))
DEALLOCATE (r_pbc)
543 IF (
ALLOCATED(s))
DEALLOCATE (s)
544 IF (
ALLOCATED(s_pbc))
DEALLOCATE (s_pbc)
553 SUBROUTINE abort_program(routine, message)
556 CHARACTER(LEN=*),
INTENT(IN) :: routine, message
558 CHARACTER(LEN=2*default_string_length) :: error_message
560 error_message =
"*** ERROR in "//trim(routine)//
": "//trim(message)//
" ***"
561 WRITE (unit=default_error_unit, fmt=
"(/,A,/)") trim(error_message)
562 stop
"*** ABNORMAL PROGRAM TERMINATION of xyz2dcd v1.0 ***"
564 END SUBROUTINE abort_program
572 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
575 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: a, b
576 REAL(kind=dp) :: angle_ab
578 REAL(kind=dp),
PARAMETER :: eps_geo = 1.0e-6_dp
580 REAL(kind=dp) :: length_of_a, length_of_b
581 REAL(kind=dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
583 length_of_a = norm2(a)
584 length_of_b = norm2(b)
586 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
587 a_norm(:) = a(:)/length_of_a
588 b_norm(:) = b(:)/length_of_b
589 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
606 SUBROUTINE build_h_matrix(a, b, c, alpha, beta, gamma, h)
611 REAL(kind=dp),
INTENT(IN) :: a, b, c, alpha, beta,
gamma
612 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(OUT) :: h
614 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_h_matrix'
616 REAL(kind=dp) :: cosa, cosb, cosg, sing
618 cosa = cos(alpha/degree)
619 IF (abs(cosa) < epsilon(0.0_dp)) cosa = 0.0_dp
621 cosb = cos(beta/degree)
622 IF (abs(cosb) < epsilon(0.0_dp)) cosb = 0.0_dp
624 cosg = cos(
gamma/degree)
625 IF (abs(cosg) < epsilon(0.0_dp)) cosg = 0.0_dp
627 sing = sin(
gamma/degree)
628 IF (abs(sing) < epsilon(0.0_dp)) sing = 0.0_dp
639 h(2, 3) = (cosa - cosg*cosb)/sing
640 IF ((1.0_dp - h(1, 3)**2 - h(2, 3)**2) < 0.0_dp)
THEN
641 CALL abort_program(routinen,
"Build of the h matrix failed, check cell information")
643 h(3, 3) = sqrt(1.0_dp - h(1, 3)**2 - h(2, 3)**2)
649 END SUBROUTINE build_h_matrix
656 FUNCTION det_3x3(a)
RESULT(det_a)
659 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(IN) :: a
660 REAL(kind=dp) :: det_a
662 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
663 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
664 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
674 SUBROUTINE invert_matrix_3x3(h, hinv, deth)
677 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
678 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(OUT) :: hinv
679 REAL(kind=dp),
INTENT(OUT) :: deth
681 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invert_matrix_3x3'
687 IF (deth < 1.0e-10_dp)
THEN
688 CALL abort_program(routinen,
"Invalid h matrix for cell found; det(h) < 1.0E-10")
691 hinv(1, 1) = (h(2, 2)*h(3, 3) - h(3, 2)*h(2, 3))/deth
692 hinv(2, 1) = (h(2, 3)*h(3, 1) - h(3, 3)*h(2, 1))/deth
693 hinv(3, 1) = (h(2, 1)*h(3, 2) - h(3, 1)*h(2, 2))/deth
695 hinv(1, 2) = (h(1, 3)*h(3, 2) - h(3, 3)*h(1, 2))/deth
696 hinv(2, 2) = (h(1, 1)*h(3, 3) - h(3, 1)*h(1, 3))/deth
697 hinv(3, 2) = (h(1, 2)*h(3, 1) - h(3, 2)*h(1, 1))/deth
699 hinv(1, 3) = (h(1, 2)*h(2, 3) - h(2, 2)*h(1, 3))/deth
700 hinv(2, 3) = (h(1, 3)*h(2, 1) - h(2, 3)*h(1, 1))/deth
701 hinv(3, 3) = (h(1, 1)*h(2, 2) - h(2, 1)*h(1, 2))/deth
703 END SUBROUTINE invert_matrix_3x3
709 SUBROUTINE lowercase(string)
711 CHARACTER(LEN=*),
INTENT(INOUT) :: string
715 DO i = 1, len_trim(string)
716 iascii = ichar(string(i:i))
717 IF ((iascii >= 65) .AND. (iascii <= 90))
THEN
718 string(i:i) = char(iascii + 32)
722 END SUBROUTINE lowercase
736 SUBROUTINE pbc(r, r_pbc, s, s_pbc, h, hinv, debug, info, pbc0)
745 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: r
746 REAL(kind=dp),
DIMENSION(:, :),
INTENT(OUT) :: r_pbc, s, s_pbc
747 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
748 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(OUT) :: hinv
749 LOGICAL,
INTENT(IN) :: debug, info, pbc0
751 CHARACTER(LEN=*),
PARAMETER :: routinen =
'pbc'
754 LOGICAL :: orthorhombic
755 REAL(kind=dp) :: deth
758 IF (
SIZE(r, 2) /= 3)
CALL abort_program(routinen,
"Array dimension for r must be 3")
760 orthorhombic = ((h(2, 1) == 0.0_dp) .AND. &
761 (h(3, 1) == 0.0_dp) .AND. &
762 (h(1, 2) == 0.0_dp) .AND. &
763 (h(3, 2) == 0.0_dp) .AND. &
764 (h(1, 3) == 0.0_dp) .AND. &
769 CALL invert_matrix_3x3(h, hinv, deth)
772 WRITE (unit=error_unit, fmt=
"(A)")
"#"
773 IF (orthorhombic)
THEN
774 WRITE (unit=error_unit, fmt=
"(A)")
"# Cell symmetry : orthorhombic"
776 WRITE (unit=error_unit, fmt=
"(A)")
"# Cell symmetry : non-orthorhombic"
779 WRITE (unit=error_unit, fmt=
"(A)")
"#"
780 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# / ", h(1, :),
" \"
781 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# h = | ", h(2, :),
" |"
782 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# \ ", h(3, :),
" /"
783 WRITE (unit=error_unit, fmt=
"(A)")
"#"
784 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# / ", hinv(1, :),
" \"
785 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# Inv(h) = | ", hinv(2, :),
" |"
786 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# \ ", hinv(3, :),
" /"
787 WRITE (unit=error_unit, fmt=
"(A)")
"#"
788 WRITE (unit=error_unit, fmt=
"(A,F0.6)")
"# det(h) = ", deth
793 IF (orthorhombic)
THEN
796 s(:, i) = r(:, i)*hinv(i, i)
799 s(:, :) = matmul(r(:, :), transpose(hinv(:, :)))
803 s_pbc(:, :) = s(:, :) - anint(s(:, :))
805 s_pbc(:, :) = s(:, :) - floor(s(:, :))
808 IF (orthorhombic)
THEN
810 r_pbc(:, i) = s_pbc(:, i)*h(i, i)
813 r_pbc(:, :) = matmul(s_pbc(:, :), transpose(h(:, :)))
821 SUBROUTINE print_help()
824 WRITE (unit=*, fmt=
"(T2,A)") &
826 "Program flags for "//trim(version_info)//
":", &
828 " -abc <3 reals> : Cell vector lengths in Angstrom", &
829 " -cell <9 reals> : Cell vectors: a(x) a(y) a(z) b(x) b(y) b(z) c(x) c(y) c(z) in Angstrom", &
830 " -cell_file, -cf <file> : Name of the cell file in CP2K format", &
831 " -debug, -d : Print debug information", &
832 " -eo : Write standard output and standard error to the same logical unit", &
833 " -first_frame, -ff <int> : Number of the first frame which is dumped", &
834 " -help, -h : Print this information", &
835 " -info, -i : Print additional information for each frame (see also -debug flag)", &
836 " -last_frame, -lf <int> : Number of the last frame which is dumped", &
837 " -pbc : Apply the periodic boundary conditions (PBC) to each frame before it is dumped", &
838 " (origin at lower left)", &
839 " -pbc0 : Apply the periodic boundary conditions (PBC) to each frame before it is dumped", &
840 " (origin at box centre)", &
841 " -scaled_coordinates, -sc : Print the scaled coordinates", &
842 " -scaled_pbc_coordinates, -spc : Print the scaled coordinates after periodic boundary conditions (PBC) have been applied", &
843 " -stride <int> : Stride for frame dump (allows to skip frames, e.g. by dumping each 10th frame)", &
844 " -trace_atoms <real> : Print the atoms which left the simulation box given a threshold value in scaled units", &
847 WRITE (unit=*, fmt=
"(T2,A)") &
850 " xyz2dcd <optional flags> <cell information: -abc <3 reals>, -cell <9 reals>, or -cell_file <file>> <XYZ file>", &
852 "Specific usage examples:", &
854 " xyz2dcd -abc 27.341 27.341 27.341 project-pos-1.xyz", &
855 " xyz2dcd -cell 27.341 0.0 0.0 0.0 27.341 0.0 0.0 0.0 27.341 project-pos-1.xyz", &
856 " xyz2dcd -cell_file project-1.cell project-pos-1.xyz", &
859 WRITE (unit=*, fmt=
"(T2,A)") &
862 " - The -info and the -debug flags provide a more detailed output which is especially handy for tracing problems", &
863 " - The input coordinates and cell vectors should be in Angstrom", &
866 END SUBROUTINE print_help
872 SUBROUTINE uppercase(string)
875 CHARACTER(LEN=*),
INTENT(INOUT) :: string
879 DO i = 1, len_trim(string)
880 iascii = ichar(string(i:i))
881 IF ((iascii >= 97) .AND. (iascii <= 122))
THEN
882 string(i:i) = char(iascii - 32)
886 END SUBROUTINE uppercase
896 SUBROUTINE write_out_of_box_atoms(atomic_label, r, s, eps_out_of_box, h)
899 CHARACTER(LEN=5),
DIMENSION(:),
INTENT(IN) :: atomic_label
900 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: r, s
901 REAL(kind=dp),
INTENT(IN) :: eps_out_of_box
902 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
904 INTEGER :: i, iatom, natom, ncount
905 REAL(kind=dp) :: rl, s_max, s_min, sl
906 REAL(kind=dp),
DIMENSION(3) :: dr, ds
909 IF (eps_out_of_box <= 0.0_dp)
RETURN
911 s_max = 1.0_dp + eps_out_of_box
912 s_min = -eps_out_of_box
916 IF (any(s(iatom, :) < s_min) .OR. &
917 any(s(iatom, :) > s_max))
THEN
919 IF (ncount == 1)
THEN
920 WRITE (unit=error_unit, fmt=
"(A)") &
922 "# Atoms out of box:", &
923 "# Atom index label x y z |dr| |ds|"
927 IF (s(iatom, i) < 0.0_dp) ds(i) = 0.0_dp
928 IF (s(iatom, i) >= 1.0_dp) ds(i) = 1.0_dp
930 ds(:) = s(iatom, :) - ds(:)
931 sl = sqrt(ds(1)**2 + ds(2)**2 + ds(3)**2)
932 dr(:) = matmul(h(:, :), ds(:))
933 rl = sqrt(dr(1)**2 + dr(2)**2 + dr(3)**2)
934 WRITE (unit=error_unit, fmt=
"(A,I10,1X,A5,5(1X,F14.6))") &
935 "# ", iatom, adjustr(atomic_label(iatom)), r(iatom, :), rl, sl
938 WRITE (unit=error_unit, fmt=
"(A,I0,A)")
"# ", ncount,
" atom(s) out of box"
940 END SUBROUTINE write_out_of_box_atoms
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Calculation of the incomplete Gamma function F_n(t) for multi-center integrals over Cartesian Gaussia...