Coverage for /builds/ase/ase/ase/io/crystal.py: 78.79%

66 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-08-02 00:12 +0000

1# fmt: off 

2 

3from ase.atoms import Atoms 

4from ase.utils import reader, writer 

5 

6 

7@writer 

8def write_crystal(fd, atoms): 

9 """Method to write atom structure in crystal format 

10 (fort.34 format) 

11 """ 

12 

13 ispbc = atoms.get_pbc() 

14 box = atoms.get_cell() 

15 

16 # here it is assumed that the non-periodic direction are z 

17 # in 2D case, z and y in the 1D case. 

18 

19 if ispbc[2]: 

20 fd.write('%2s %2s %2s %23s \n' % 

21 ('3', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)')) 

22 elif ispbc[1]: 

23 fd.write('%2s %2s %2s %23s \n' % 

24 ('2', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)')) 

25 box[2, 2] = 500. 

26 elif ispbc[0]: 

27 fd.write('%2s %2s %2s %23s \n' % 

28 ('1', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)')) 

29 box[2, 2] = 500. 

30 box[1, 1] = 500. 

31 else: 

32 fd.write('%2s %2s %2s %23s \n' % 

33 ('0', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)')) 

34 box[2, 2] = 500. 

35 box[1, 1] = 500. 

36 box[0, 0] = 500. 

37 

38 # write box 

39 # crystal dummy 

40 fd.write(' %.17E %.17E %.17E \n' 

41 % (box[0][0], box[0][1], box[0][2])) 

42 fd.write(' %.17E %.17E %.17E \n' 

43 % (box[1][0], box[1][1], box[1][2])) 

44 fd.write(' %.17E %.17E %.17E \n' 

45 % (box[2][0], box[2][1], box[2][2])) 

46 

47 # write symmetry operations (not implemented yet for 

48 # higher symmetries than C1) 

49 fd.write(' %2s \n' % (1)) 

50 fd.write(f' {1:.17E} {0:.17E} {0:.17E} \n') 

51 fd.write(f' {0:.17E} {1:.17E} {0:.17E} \n') 

52 fd.write(f' {0:.17E} {0:.17E} {1:.17E} \n') 

53 fd.write(f' {0:.17E} {0:.17E} {0:.17E} \n') 

54 

55 # write coordinates 

56 fd.write(' %8s \n' % (len(atoms))) 

57 coords = atoms.get_positions() 

58 tags = atoms.get_tags() 

59 atomnum = atoms.get_atomic_numbers() 

60 for iatom, coord in enumerate(coords): 

61 fd.write('%5i %19.16f %19.16f %19.16f \n' 

62 % (atomnum[iatom] + tags[iatom], 

63 coords[iatom][0], coords[iatom][1], coords[iatom][2])) 

64 

65 

66@reader 

67def read_crystal(fd): 

68 """Method to read coordinates form 'fort.34' files 

69 additionally read information about 

70 periodic boundary condition 

71 """ 

72 lines = fd.readlines() 

73 

74 atoms_pos = [] 

75 anumber_list = [] 

76 my_pbc = [False, False, False] 

77 mycell = [] 

78 

79 if float(lines[4]) != 1: 

80 raise ValueError('High symmetry geometry is not allowed.') 

81 

82 if float(lines[1].split()[0]) < 500.0: 

83 cell = [float(c) for c in lines[1].split()] 

84 mycell.append(cell) 

85 my_pbc[0] = True 

86 else: 

87 mycell.append([1, 0, 0]) 

88 

89 if float(lines[2].split()[1]) < 500.0: 

90 cell = [float(c) for c in lines[2].split()] 

91 mycell.append(cell) 

92 my_pbc[1] = True 

93 else: 

94 mycell.append([0, 1, 0]) 

95 

96 if float(lines[3].split()[2]) < 500.0: 

97 cell = [float(c) for c in lines[3].split()] 

98 mycell.append(cell) 

99 my_pbc[2] = True 

100 else: 

101 mycell.append([0, 0, 1]) 

102 

103 natoms = int(lines[9].split()[0]) 

104 for i in range(natoms): 

105 index = 10 + i 

106 anum = int(lines[index].split()[0]) % 100 

107 anumber_list.append(anum) 

108 

109 position = [float(p) for p in lines[index].split()[1:]] 

110 atoms_pos.append(position) 

111 

112 atoms = Atoms(positions=atoms_pos, numbers=anumber_list, 

113 cell=mycell, pbc=my_pbc) 

114 

115 return atoms