22 INTEGER,
PARAMETER :: default_error_unit = 0, &
23 default_input_unit = 5, &
24 default_output_unit = 6
25 INTEGER :: error_unit = default_error_unit, &
26 output_unit = default_output_unit
30 CHARACTER(LEN=*),
PARAMETER :: routinen =
"xyz2dcd", &
31 version_info = routinen//
" v1.0 (30.06.2020, Matthias Krack)"
33 INTEGER,
PARAMETER :: dp = selected_real_kind(14, 200), &
34 sp = selected_real_kind(6, 30)
35 INTEGER,
PARAMETER :: default_string_length = 240, &
36 cell_file_unit = 10, &
38 xyz_file_unit = default_input_unit
40 REAL(kind=dp),
PARAMETER :: pi = 3.14159265358979323846264338_dp
42 REAL(kind=dp),
PARAMETER :: degree = 180.0_dp/pi
45 CHARACTER(LEN=default_string_length) :: arg, cell_file_name, dcd_file_name, message, remark1, remark2, remark_xyz, &
47 CHARACTER(LEN=5),
DIMENSION(:),
ALLOCATABLE :: atomic_label
48 CHARACTER(LEN=80),
DIMENSION(2) :: remark_dcd
49 INTEGER :: first_frame, i, iarg, iatom, iskip, istat, istep, j, &
50 last_frame, narg, natom, nframe, nframe_read, nremark, stride
51 LOGICAL :: apply_pbc, debug, dump_frame, exists, have_cell_file, have_cell_info, &
52 info, pbc0, print_atomic_displacements, print_scaled_coordinates, &
53 print_scaled_pbc_coordinates, trace_atoms
54 REAL(kind=dp) :: alpha, beta, dt, eps_out_of_box,
gamma, tstep
55 REAL(kind=dp),
DIMENSION(3) :: a, abc, b, c
56 REAL(kind=dp),
DIMENSION(:),
ALLOCATABLE :: atomic_displacement
57 REAL(kind=dp),
DIMENSION(3, 3) :: h, hinv
58 REAL(kind=dp),
DIMENSION(:, :),
ALLOCATABLE :: r, r_pbc, r0, s, s_pbc
63 have_cell_file = .false.
64 have_cell_info = .false.
68 print_scaled_coordinates = .false.
69 print_atomic_displacements = .false.
70 print_scaled_pbc_coordinates = .false.
82 eps_out_of_box = -huge(0.0_dp)
88 narg = command_argument_count()
98 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
103 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
104 READ (unit=arg, fmt=*, err=100) h(i, i)
106 have_cell_info = .true.
108 100
CALL abort_program(routinen,
"Reading -abc arguments (3 reals are expected)")
113 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
114 READ (unit=arg, fmt=*, err=101) h(j, i)
117 have_cell_info = .true.
119 101
CALL abort_program(routinen,
"Reading -cell arguments (9 reals are expected)")
120 CASE (
"-cell_file",
"-cf")
122 CALL get_command_argument(number=iarg,
VALUE=cell_file_name, status=istat)
123 have_cell_file = .true.
124 have_cell_info = .true.
126 CASE (
"-df",
"-dcd_file")
128 CALL get_command_argument(number=iarg,
VALUE=dcd_file_name, status=istat)
130 CASE (
"-debug",
"-d")
134 CASE (
"-displacements",
"-disp")
135 print_atomic_displacements = .true.
138 error_unit = output_unit
140 CASE (
"-first_frame",
"-first",
"-ff")
142 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
143 READ (unit=arg, fmt=*, err=102) first_frame
144 IF (first_frame <= 0)
THEN
145 CALL abort_program(routinen,
"Invalid number for first frame specified: "// &
146 "first_frame must be greater than zero")
149 102
CALL abort_program(routinen,
"Invalid number for first frame specified "// &
150 "(an integer number greater than zero is expected)")
157 CASE (
"-last_frame",
"-last",
"-lf")
159 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
160 READ (unit=arg, fmt=*, err=103) last_frame
161 IF (last_frame <= 0)
THEN
162 CALL abort_program(routinen,
"Invalid number for last frame specified: "// &
163 "last_frame must be greater than zero")
166 103
CALL abort_program(routinen,
"Invalid number for last frame specified "// &
167 "(an integer number greater than zero is expected)")
176 CASE (
"-scaled_coordinates",
"-sc")
177 print_scaled_coordinates = .true.
179 CASE (
"-scaled_pbc_coordinates",
"-spc")
180 print_scaled_pbc_coordinates = .true.
184 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
185 READ (unit=arg, fmt=*, err=104) stride
187 CALL abort_program(routinen,
"Invalid stride for frame dump specified: stride must be greater than zero")
190 104
CALL abort_program(routinen,
"Invalid stride for frame dump specified "// &
191 "(an integer number greater than 0 is expected)")
192 CASE (
"-trace_atoms")
194 CALL get_command_argument(number=iarg,
VALUE=arg, status=istat)
195 READ (unit=arg, fmt=*, err=105) eps_out_of_box
196 IF (eps_out_of_box <= 0.0_dp)
THEN
197 CALL abort_program(routinen,
"Invalid threshold value for -trace_atoms flag specified")
201 105
CALL abort_program(routinen,
"Invalid threshold value for -trace_atoms flag specified")
203 IF (arg(1:1) ==
"-")
THEN
205 CALL abort_program(routinen,
"Unknown command line flag """//trim(arg)//
""" found")
213 IF (.NOT. have_cell_info)
THEN
214 CALL abort_program(routinen,
"No cell information available. Neither -abc, -cell, nor -cell_file flag found")
216 IF (first_frame > last_frame)
THEN
217 CALL abort_program(routinen,
"Number of first frame greater than number of last frame")
219 IF (.NOT. apply_pbc .AND. trace_atoms)
THEN
220 CALL abort_program(routinen,
"The -trace_atoms flag requires the specification of a -pbc flag")
222 IF (print_scaled_coordinates .AND. print_scaled_pbc_coordinates)
THEN
223 CALL abort_program(routinen,
"The -sc flag and the -spc flag are incompatible")
225 IF (.NOT. apply_pbc .AND. print_scaled_coordinates)
THEN
226 CALL abort_program(routinen,
"The -sc flag requires the specification of a -pbc flag")
228 IF (.NOT. apply_pbc .AND. print_scaled_pbc_coordinates)
THEN
229 CALL abort_program(routinen,
"The -spc flag requires the specification of a -pbc flag")
233 IF (have_cell_file)
THEN
234 INQUIRE (file=cell_file_name, exist=exists)
235 IF (.NOT. exists)
CALL abort_program(routinen,
"The specified cell file <"// &
236 trim(cell_file_name)//
"> does not exist")
237 OPEN (unit=cell_file_unit, &
238 file=cell_file_name, &
240 access=
"SEQUENTIAL", &
245 IF (istat /= 0)
CALL abort_program(routinen,
"The cell file <"// &
246 trim(cell_file_name)//
"> could not be opened")
247 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Reading cell file : "//trim(cell_file_name)
251 INQUIRE (file=xyz_file_name, exist=exists)
252 IF (.NOT. exists)
CALL abort_program(routinen,
"The specified XYZ file <"// &
253 trim(xyz_file_name)//
"> does not exist")
254 OPEN (unit=xyz_file_unit, &
255 file=xyz_file_name, &
257 access=
"SEQUENTIAL", &
262 IF (istat /= 0)
CALL abort_program(routinen,
"The XYZ file <"// &
263 trim(xyz_file_name)//
"> could not be opened")
264 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Reading XYZ file : "//trim(xyz_file_name)
267 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) arg
269 CALL abort_program(routinen,
"Reading the first line of the current frame from the XYZ file <"// &
270 trim(xyz_file_name)//
"> failed")
272 IF (arg(1:1) ==
"#")
THEN
273 READ (unit=arg, fmt=*) string, natom
275 READ (unit=arg, fmt=*) natom
278 CALL abort_program(routinen,
"Reading the number of atoms from the XYZ file failed")
280 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) remark_xyz
281 IF (istat /= 0)
CALL abort_program(routinen,
"Reading the second line from the XYZ file <"// &
282 trim(xyz_file_name)//
"> failed")
283 rewind(unit=xyz_file_unit)
286 IF (len_trim(dcd_file_name) == 0)
THEN
287 i = len_trim(xyz_file_name)
288 IF (xyz_file_name(i - 2:i) ==
"xyz")
THEN
289 dcd_file_name = xyz_file_name(1:i - 3)//
"dcd"
291 dcd_file_name = xyz_file_name(1:i)//
".dcd"
294 INQUIRE (file=dcd_file_name, exist=exists)
296 trim(dcd_file_name)//
" exists already")
297 OPEN (unit=dcd_file_unit, &
298 file=dcd_file_name, &
300 access=
"SEQUENTIAL", &
301 form=
"UNFORMATTED", &
304 IF (istat /= 0)
CALL abort_program(routinen,
"The unformatted DCD output file "// &
305 trim(dcd_file_name)//
" could not be opened")
306 IF (info)
WRITE (unit=error_unit, fmt=
"(A)")
"# Writing DCD file : "//trim(dcd_file_name)
313 WRITE (unit=dcd_file_unit)
"CORD", 0, istep, iskip, 0, 0, 0, 0, 0, 0, real(dt, kind=sp), &
314 1, 0, 0, 0, 0, 0, 0, 0, 0, 24
315 remark1 =
"REMARK CORD"//
" DCD file created by "//trim(version_info)
316 remark2 =
"REMARK "//trim(adjustl(remark_xyz))
317 WRITE (unit=dcd_file_unit) 2, remark1(1:80), remark2(1:80)
318 WRITE (unit=dcd_file_unit) natom
321 ALLOCATE (r(natom, 3), stat=istat)
322 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r failed")
325 ALLOCATE (atomic_label(natom), stat=istat)
326 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the vector atomic_label failed")
334 IF (nframe < first_frame)
THEN
337 IF (
modulo(nframe - first_frame, stride) == 0)
THEN
345 IF (have_cell_file)
THEN
347 READ (unit=cell_file_unit, fmt=*, iostat=istat) arg
348 IF (istat < 0)
EXIT frame_loop
352 IF (arg(1:1) ==
"#")
THEN
355 backspace(unit=cell_file_unit)
359 READ (unit=cell_file_unit, fmt=*, iostat=istat) istep, tstep, ((h(j, i), j=1, 3), i=1, 3)
361 CALL abort_program(routinen,
"Reading information from cell file")
366 IF (have_cell_file .OR. (nframe == 1))
THEN
370 abc(1) = sqrt(dot_product(a(1:3), a(1:3)))
371 abc(2) = sqrt(dot_product(b(1:3), b(1:3)))
372 abc(3) = sqrt(dot_product(c(1:3), c(1:3)))
373 alpha =
angle(b(1:3), c(1:3))*degree
374 beta =
angle(a(1:3), c(1:3))*degree
379 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) arg
380 IF (istat < 0)
EXIT frame_loop
382 CALL abort_program(routinen,
"Reading the first line of the current frame from the XYZ file failed")
384 IF (arg(1:1) ==
"#")
THEN
385 READ (unit=arg, fmt=*) string, natom
387 READ (unit=arg, fmt=*) natom
390 CALL abort_program(routinen,
"Reading the number of atoms from the XYZ file failed")
392 IF (natom /=
SIZE(r, 1))
THEN
393 CALL abort_program(routinen,
"Number of atoms changed for the current frame")
397 READ (unit=xyz_file_unit, fmt=
"(A)", iostat=istat) remark_xyz
398 IF (istat /= 0)
CALL abort_program(routinen,
"Reading the second line from the XYZ file failed")
401 IF (info .AND. dump_frame)
THEN
402 WRITE (unit=error_unit, fmt=
"(A,/,A,I0)") &
403 "#",
"# Frame number : ", nframe
404 WRITE (unit=error_unit, fmt=
"(A,/,(A,F12.6))") &
406 "# a [Angstrom] : ", abc(1), &
407 "# b [Angstrom] : ", abc(2), &
408 "# c [Angstrom] : ", abc(3), &
409 "# alpha [degree] : ", alpha, &
410 "# beta [degree] : ", beta, &
411 "# gamma [degree] : ",
gamma
415 WRITE (unit=output_unit, fmt=
"(T2,I0)") natom
416 WRITE (unit=output_unit, fmt=
"(A)") trim(adjustl(remark_xyz))
422 READ (unit=xyz_file_unit, fmt=*) arg
423 IF (arg(1:1) ==
"#")
THEN
426 backspace(unit=xyz_file_unit)
429 READ (unit=xyz_file_unit, fmt=*, iostat=istat) atomic_label(iatom), r(iatom, 1:3)
432 WRITE (unit=message, fmt=
"(A,I0,A,I0,A)") &
433 "Reading line ", iatom + 2,
" of the current frame from XYZ file (atom ", iatom,
") failed"
436 CALL uppercase(atomic_label(iatom) (1:1))
437 IF (len_trim(atomic_label(iatom)) > 1)
CALL lowercase(atomic_label(iatom) (2:2))
438 atomic_label(iatom) = trim(adjustl(atomic_label(iatom)))
439 IF (iatom == natom)
EXIT
444 IF ((nframe == 1) .AND. print_atomic_displacements)
THEN
445 IF (.NOT.
ALLOCATED(r0))
THEN
446 ALLOCATE (r0(natom, 3), stat=istat)
447 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r0 failed")
450 IF (.NOT.
ALLOCATED(atomic_displacement))
THEN
451 ALLOCATE (atomic_displacement(natom), stat=istat)
453 CALL abort_program(routinen,
"Allocation of the vector atomic_displacement failed")
456 atomic_displacement(:) = 0.0_dp
462 IF (.NOT.
ALLOCATED(r_pbc))
THEN
463 ALLOCATE (r_pbc(natom, 3), stat=istat)
464 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array r_pbc failed")
467 IF (.NOT.
ALLOCATED(s))
THEN
468 ALLOCATE (s(natom, 3), stat=istat)
469 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array s failed")
472 IF (.NOT.
ALLOCATED(s_pbc))
THEN
473 ALLOCATE (s_pbc(natom, 3), stat=istat)
474 IF (istat /= 0)
CALL abort_program(routinen,
"Allocation of the array s_pbc failed")
477 CALL pbc(r, r_pbc, s, s_pbc, h, hinv, debug, info, pbc0)
480 r(:, :) = r_pbc(:, :)
484 IF (print_atomic_displacements)
THEN
486 atomic_displacement(iatom) = sqrt((r(iatom, 1) - r0(iatom, 1))**2 + &
487 (r(iatom, 2) - r0(iatom, 2))**2 + &
488 (r(iatom, 3) - r0(iatom, 3))**2)
492 IF (print_scaled_coordinates)
THEN
494 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), s(iatom, 1:3)
496 ELSE IF (print_scaled_pbc_coordinates)
THEN
498 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), s_pbc(iatom, 1:3)
502 WRITE (unit=output_unit, fmt=
"(A5,3(1X,F14.6))") adjustl(atomic_label(iatom)), r(iatom, 1:3)
507 WRITE (unit=dcd_file_unit) abc(1),
gamma, abc(2), beta, alpha, abc(3)
510 WRITE (unit=dcd_file_unit) real(r(1:natom, i), kind=sp)
512 nframe_read = nframe_read + 1
516 IF (nframe >= last_frame)
EXIT
523 IF (have_cell_file)
CLOSE (unit=cell_file_unit)
524 CLOSE (unit=dcd_file_unit)
525 CLOSE (unit=xyz_file_unit)
528 WRITE (unit=error_unit, fmt=
"(A,/,A,I0)") &
530 "# Frames processed : ", nframe_read
531 WRITE (unit=error_unit, fmt=
"(A)") &
533 "# Normal termination of "//trim(version_info)
537 IF (
ALLOCATED(atomic_label))
DEALLOCATE (atomic_label)
538 IF (
ALLOCATED(atomic_displacement))
DEALLOCATE (atomic_displacement)
539 IF (
ALLOCATED(r))
DEALLOCATE (r)
540 IF (
ALLOCATED(r0))
DEALLOCATE (r0)
541 IF (
ALLOCATED(r_pbc))
DEALLOCATE (r_pbc)
542 IF (
ALLOCATED(s))
DEALLOCATE (s)
543 IF (
ALLOCATED(s_pbc))
DEALLOCATE (s_pbc)
555 CHARACTER(LEN=*),
INTENT(IN) :: routine, message
557 CHARACTER(LEN=2*default_string_length) :: error_message
559 error_message =
"*** ERROR in "//trim(routine)//
": "//trim(message)//
" ***"
560 WRITE (unit=default_error_unit, fmt=
"(/,A,/)") trim(error_message)
561 stop
"*** ABNORMAL PROGRAM TERMINATION of xyz2dcd v1.0 ***"
571 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
574 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: a, b
575 REAL(kind=dp) :: angle_ab
577 REAL(kind=dp),
PARAMETER :: eps_geo = 1.0e-6_dp
579 REAL(kind=dp) :: length_of_a, length_of_b
580 REAL(kind=dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
582 length_of_a = sqrt(dot_product(a, a))
583 length_of_b = sqrt(dot_product(b, b))
585 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
586 a_norm(:) = a(:)/length_of_a
587 b_norm(:) = b(:)/length_of_b
588 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
610 REAL(KIND=dp),
INTENT(IN) :: a, b, c, alpha, beta,
gamma
611 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(OUT) :: h
613 CHARACTER(LEN=*),
PARAMETER :: routineN =
'build_h_matrix'
615 REAL(KIND=dp) :: cosa, cosb, cosg, sing
617 cosa = cos(alpha/degree)
618 IF (abs(cosa) < epsilon(0.0_dp)) cosa = 0.0_dp
620 cosb = cos(beta/degree)
621 IF (abs(cosb) < epsilon(0.0_dp)) cosb = 0.0_dp
623 cosg = cos(
gamma/degree)
624 IF (abs(cosg) < epsilon(0.0_dp)) cosg = 0.0_dp
626 sing = sin(
gamma/degree)
627 IF (abs(sing) < epsilon(0.0_dp)) sing = 0.0_dp
638 h(2, 3) = (cosa - cosg*cosb)/sing
639 IF ((1.0_dp - h(1, 3)**2 - h(2, 3)**2) < 0.0_dp)
THEN
640 CALL abort_program(routinen,
"Build of the h matrix failed, check cell information")
642 h(3, 3) = sqrt(1.0_dp - h(1, 3)**2 - h(2, 3)**2)
658 REAL(kind=dp),
DIMENSION(3, 3),
INTENT(IN) :: a
659 REAL(kind=dp) :: det_a
661 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
662 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
663 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
676 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
677 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(OUT) :: hinv
678 REAL(KIND=dp),
INTENT(OUT) :: deth
680 CHARACTER(LEN=*),
PARAMETER :: routineN =
'invert_matrix_3x3'
686 IF (deth < 1.0e-10_dp)
THEN
687 CALL abort_program(routinen,
"Invalid h matrix for cell found; det(h) < 1.0E-10")
690 hinv(1, 1) = (h(2, 2)*h(3, 3) - h(3, 2)*h(2, 3))/deth
691 hinv(2, 1) = (h(2, 3)*h(3, 1) - h(3, 3)*h(2, 1))/deth
692 hinv(3, 1) = (h(2, 1)*h(3, 2) - h(3, 1)*h(2, 2))/deth
694 hinv(1, 2) = (h(1, 3)*h(3, 2) - h(3, 3)*h(1, 2))/deth
695 hinv(2, 2) = (h(1, 1)*h(3, 3) - h(3, 1)*h(1, 3))/deth
696 hinv(3, 2) = (h(1, 2)*h(3, 1) - h(3, 2)*h(1, 1))/deth
698 hinv(1, 3) = (h(1, 2)*h(2, 3) - h(2, 2)*h(1, 3))/deth
699 hinv(2, 3) = (h(1, 3)*h(2, 1) - h(2, 3)*h(1, 1))/deth
700 hinv(3, 3) = (h(1, 1)*h(2, 2) - h(2, 1)*h(1, 2))/deth
710 CHARACTER(LEN=*),
INTENT(INOUT) :: string
714 DO i = 1, len_trim(string)
715 iascii = ichar(string(i:i))
716 IF ((iascii >= 65) .AND. (iascii <= 90))
THEN
717 string(i:i) = char(iascii + 32)
735 SUBROUTINE pbc(r, r_pbc, s, s_pbc, h, hinv, debug, info, pbc0)
744 REAL(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: r
745 REAL(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: r_pbc, s, s_pbc
746 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
747 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(OUT) :: hinv
748 LOGICAL,
INTENT(IN) :: debug, info, pbc0
750 CHARACTER(LEN=*),
PARAMETER :: routineN =
'pbc'
753 LOGICAL :: orthorhombic
754 REAL(KIND=dp) :: deth
757 IF (
SIZE(r, 2) /= 3)
CALL abort_program(routinen,
"Array dimension for r must be 3")
759 orthorhombic = ((h(2, 1) == 0.0_dp) .AND. &
760 (h(3, 1) == 0.0_dp) .AND. &
761 (h(1, 2) == 0.0_dp) .AND. &
762 (h(3, 2) == 0.0_dp) .AND. &
763 (h(1, 3) == 0.0_dp) .AND. &
771 WRITE (unit=error_unit, fmt=
"(A)")
"#"
772 IF (orthorhombic)
THEN
773 WRITE (unit=error_unit, fmt=
"(A)")
"# Cell symmetry : orthorhombic"
775 WRITE (unit=error_unit, fmt=
"(A)")
"# Cell symmetry : non-orthorhombic"
778 WRITE (unit=error_unit, fmt=
"(A)")
"#"
779 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# / ", h(1, :),
" \"
780 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# h = | ", h(2, :),
" |"
781 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# \ ", h(3, :),
" /"
782 WRITE (unit=error_unit, fmt=
"(A)")
"#"
783 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# / ", hinv(1, :),
" \"
784 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# Inv(h) = | ", hinv(2, :),
" |"
785 WRITE (unit=error_unit, fmt=
"(A,3F12.6,A)")
"# \ ", hinv(3, :),
" /"
786 WRITE (unit=error_unit, fmt=
"(A)")
"#"
787 WRITE (unit=error_unit, fmt=
"(A,F0.6)")
"# det(h) = ", deth
792 IF (orthorhombic)
THEN
795 s(:, i) = r(:, i)*hinv(i, i)
798 s(:, :) = matmul(r(:, :), transpose(hinv(:, :)))
802 s_pbc(:, :) = s(:, :) - anint(s(:, :))
804 s_pbc(:, :) = s(:, :) - floor(s(:, :))
807 IF (orthorhombic)
THEN
809 r_pbc(:, i) = s_pbc(:, i)*h(i, i)
812 r_pbc(:, :) = matmul(s_pbc(:, :), transpose(h(:, :)))
823 WRITE (unit=*, fmt=
"(T2,A)") &
825 "Program flags for "//trim(version_info)//
":", &
827 " -abc <3 reals> : Cell vector lengths in Angstrom", &
828 " -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", &
829 " -cell_file, -cf <file> : Name of the cell file in CP2K format", &
830 " -debug, -d : Print debug information", &
831 " -eo : Write standard output and standard error to the same logical unit", &
832 " -first_frame, -ff <int> : Number of the first frame which is dumped", &
833 " -help, -h : Print this information", &
834 " -info, -i : Print additional information for each frame (see also -debug flag)", &
835 " -last_frame, -lf <int> : Number of the last frame which is dumped", &
836 " -pbc : Apply the periodic boundary conditions (PBC) to each frame before it is dumped", &
837 " (origin at lower left)", &
838 " -pbc0 : Apply the periodic boundary conditions (PBC) to each frame before it is dumped", &
839 " (origin at box centre)", &
840 " -scaled_coordinates, -sc : Print the scaled coordinates", &
841 " -scaled_pbc_coordinates, -spc : Print the scaled coordinates after periodic boundary conditions (PBC) have been applied", &
842 " -stride <int> : Stride for frame dump (allows to skip frames, e.g. by dumping each 10th frame)", &
843 " -trace_atoms <real> : Print the atoms which left the simulation box given a threshold value in scaled units", &
846 WRITE (unit=*, fmt=
"(T2,A)") &
849 " xyz2dcd <optional flags> <cell information: -abc <3 reals>, -cell <9 reals>, or -cell_file <file>> <XYZ file>", &
851 "Specific usage examples:", &
853 " xyz2dcd -abc 27.341 27.341 27.341 project-pos-1.xyz", &
854 " xyz2dcd -cell 27.341 0.0 0.0 0.0 27.341 0.0 0.0 0.0 27.341 project-pos-1.xyz", &
855 " xyz2dcd -cell_file project-1.cell project-pos-1.xyz", &
858 WRITE (unit=*, fmt=
"(T2,A)") &
861 " - The -info and the -debug flags provide a more detailed output which is especially handy for tracing problems", &
862 " - The input coordinates and cell vectors should be in Angstrom", &
874 CHARACTER(LEN=*),
INTENT(INOUT) :: string
878 DO i = 1, len_trim(string)
879 iascii = ichar(string(i:i))
880 IF ((iascii >= 97) .AND. (iascii <= 122))
THEN
881 string(i:i) = char(iascii - 32)
898 CHARACTER(LEN=5),
DIMENSION(:),
INTENT(IN) :: atomic_label
899 REAL(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: r, s
900 REAL(KIND=dp),
INTENT(IN) :: eps_out_of_box
901 REAL(KIND=dp),
DIMENSION(3, 3),
INTENT(IN) :: h
903 INTEGER :: i, iatom, natom, ncount
904 REAL(KIND=dp) :: rl, s_max, s_min, sl
905 REAL(KIND=dp),
DIMENSION(3) :: dr, ds
908 IF (eps_out_of_box <= 0.0_dp)
RETURN
910 s_max = 1.0_dp + eps_out_of_box
911 s_min = -eps_out_of_box
915 IF (any(s(iatom, :) < s_min) .OR. &
916 any(s(iatom, :) > s_max))
THEN
918 IF (ncount == 1)
THEN
919 WRITE (unit=error_unit, fmt=
"(A)") &
921 "# Atoms out of box:", &
922 "# Atom index label x y z |dr| |ds|"
926 IF (s(iatom, i) < 0.0_dp) ds(i) = 0.0_dp
927 IF (s(iatom, i) >= 1.0_dp) ds(i) = 1.0_dp
929 ds(:) = s(iatom, :) - ds(:)
930 sl = sqrt(ds(1)**2 + ds(2)**2 + ds(3)**2)
931 dr(:) = matmul(h(:, :), ds(:))
932 rl = sqrt(dr(1)**2 + dr(2)**2 + dr(3)**2)
933 WRITE (unit=error_unit, fmt=
"(A,I10,1X,A5,5(1X,F14.6))") &
934 "# ", iatom, adjustr(atomic_label(iatom)), r(iatom, :), rl, sl
937 WRITE (unit=error_unit, fmt=
"(A,I0,A)")
"# ", ncount,
" atom(s) out of box"
subroutine abort_program(routine, message)
...
subroutine write_out_of_box_atoms(atomic_label, r, s, eps_out_of_box, h)
...
subroutine invert_matrix_3x3(h, hinv, deth)
...
subroutine build_h_matrix(a, b, c, alpha, beta, gamma, h)
...
real(kind=dp) function det_3x3(a)
...
subroutine print_help()
...
subroutine pbc(r, r_pbc, s, s_pbc, a, b, c, alpha, beta, gamma, debug, info, pbc0, h, hinv)
...
subroutine lowercase(string)
...
pure real(kind=dp) function angle(a, b)
Calculation of the angle between the vectors a and b. The angle is returned in radians.
subroutine uppercase(string)
...
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...