Coverage for gpaw/output.py: 91%

111 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2025-07-14 00:18 +0000

1import numpy as np 

2from gpaw.cgpaw import get_num_threads 

3from ase import Atoms 

4from ase.data import chemical_symbols 

5from ase.geometry import cell_to_cellpar 

6from ase.units import Bohr 

7 

8 

9def print_cell(gd, pbc_c, log): 

10 

11 log("""Unit cell: 

12 periodic x y z points spacing""") 

13 h_c = gd.get_grid_spacings() 

14 for c in range(3): 

15 log(' %d. axis: %s %10.6f %10.6f %10.6f %3d %8.4f' 

16 % ((c + 1, ['no ', 'yes'][int(pbc_c[c])]) + 

17 tuple(Bohr * gd.cell_cv[c]) + 

18 (gd.N_c[c], Bohr * h_c[c]))) 

19 

20 par = cell_to_cellpar(gd.cell_cv * Bohr) 

21 log('\n Lengths: {:10.6f} {:10.6f} {:10.6f}'.format(*par[:3])) 

22 log(' Angles: {:10.6f} {:10.6f} {:10.6f}\n'.format(*par[3:])) 

23 

24 h_eff = gd.dv**(1.0 / 3.0) * Bohr 

25 log(f'Effective grid spacing dv^(1/3) = {h_eff:.4f}') 

26 log() 

27 

28 

29def print_positions(atoms, log, magmom_av): 

30 log(plot(atoms)) 

31 log('\nAtomic positions and initial magnetic moments') 

32 log('\nPositions:') 

33 symbols = atoms.get_chemical_symbols() 

34 for a, pos_v in enumerate(atoms.get_positions()): 

35 symbol = symbols[a] 

36 log('{0:>4} {1:3} {2[0]:11.6f} {2[1]:11.6f} {2[2]:11.6f}' 

37 ' ({3[0]:7.4f}, {3[1]:7.4f}, {3[2]:7.4f})' 

38 .format(a, symbol, pos_v, magmom_av[a])) 

39 log() 

40 

41 

42def print_parallelization_details(wfs, ham, log): 

43 log('Total number of cores used:', wfs.world.size) 

44 if wfs.kd.comm.size > 1: 

45 log('Parallelization over k-points:', wfs.kd.comm.size) 

46 

47 # Domain decomposition settings: 

48 coarsesize = tuple(wfs.gd.parsize_c) 

49 finesize = tuple(ham.finegd.parsize_c) 

50 

51 try: # Only planewave density 

52 xc_gd = ham.xc_gd 

53 except AttributeError: 

54 xc_gd = ham.finegd 

55 xcsize = tuple(xc_gd.parsize_c) 

56 

57 if any(np.prod(size) != 1 for size in [coarsesize, finesize, xcsize]): 

58 title = 'Domain decomposition:' 

59 template = '%d x %d x %d' 

60 log(title, template % coarsesize) 

61 if coarsesize != finesize: 

62 log(' ' * len(title), template % finesize, '(fine grid)') 

63 if xcsize != finesize: 

64 log(' ' * len(title), template % xcsize, '(xc only)') 

65 

66 if wfs.bd.comm.size > 1: # band parallelization 

67 log('Parallelization over states: %d' % wfs.bd.comm.size) 

68 

69 if get_num_threads() > 1: # OpenMP threading 

70 log(f'OpenMP threads: {get_num_threads()}') 

71 log() 

72 

73 

74def plot(atoms: Atoms) -> str: 

75 """Ascii-art plot of the atoms.""" 

76 

77 # y 

78 # | 

79 # .-- x 

80 # / 

81 # z 

82 

83 if atoms.cell.handedness != 1: 

84 # See example we can't handle in test_ascii_art() 

85 return '' 

86 

87 cell_cv = atoms.get_cell() 

88 if atoms.cell.orthorhombic: 

89 plot_box = True 

90 else: 

91 atoms = atoms.copy() 

92 atoms.cell = [1, 1, 1] 

93 atoms.center(vacuum=2.0) 

94 cell_cv = atoms.get_cell() 

95 plot_box = False 

96 

97 cell = np.diagonal(cell_cv) / Bohr 

98 positions = atoms.get_positions() / Bohr 

99 numbers = atoms.get_atomic_numbers() 

100 

101 s = 1.3 

102 nx, ny, nz = nxyz = (s * cell * (1.0, 0.25, 0.5) + 0.5).astype(int) 

103 sx, sy, sz = nxyz / cell 

104 grid = Grid(nx + ny + 4, nz + ny + 1) 

105 positions = (positions % cell + cell) % cell 

106 ij = np.dot(positions, [(sx, 0), (sy, sy), (0, sz)]) 

107 ij = np.around(ij).astype(int) 

108 for a, Z in enumerate(numbers): 

109 symbol = chemical_symbols[Z] 

110 i, j = ij[a] 

111 depth = positions[a, 1] 

112 for n, c in enumerate(symbol): 

113 grid.put(c, i + n + 1, j, depth) 

114 if plot_box: 

115 k = 0 

116 for i, j in [(1, 0), (1 + nx, 0)]: 

117 grid.put('*', i, j) 

118 grid.put('.', i + ny, j + ny) 

119 if k == 0: 

120 grid.put('*', i, j + nz) 

121 grid.put('.', i + ny, j + nz + ny) 

122 for y in range(1, ny): 

123 grid.put('/', i + y, j + y, y / sy) 

124 if k == 0: 

125 grid.put('/', i + y, j + y + nz, y / sy) 

126 for z in range(1, nz): 

127 if k == 0: 

128 grid.put('|', i, j + z) 

129 grid.put('|', i + ny, j + z + ny) 

130 k = 1 

131 for i, j in [(1, 0), (1, nz)]: 

132 for x in range(1, nx): 

133 if k == 1: 

134 grid.put('-', i + x, j) 

135 grid.put('-', i + x + ny, j + ny) 

136 k = 0 

137 return '\n'.join([''.join([chr(x) for x in line]) 

138 for line in np.transpose(grid.grid)[::-1]]) 

139 

140 

141class Grid: 

142 def __init__(self, i, j): 

143 self.grid = np.zeros((i, j), np.int8) 

144 self.grid[:] = ord(' ') 

145 self.depth = np.zeros((i, j)) 

146 self.depth[:] = 1e10 

147 

148 def put(self, c, i, j, depth=1e9): 

149 if depth < self.depth[i, j]: 

150 self.grid[i, j] = ord(c) 

151 self.depth[i, j] = depth