Coverage for gpaw/output.py: 91%
111 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-14 00:18 +0000
« 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
9def print_cell(gd, pbc_c, log):
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])))
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:]))
24 h_eff = gd.dv**(1.0 / 3.0) * Bohr
25 log(f'Effective grid spacing dv^(1/3) = {h_eff:.4f}')
26 log()
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()
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)
47 # Domain decomposition settings:
48 coarsesize = tuple(wfs.gd.parsize_c)
49 finesize = tuple(ham.finegd.parsize_c)
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)
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)')
66 if wfs.bd.comm.size > 1: # band parallelization
67 log('Parallelization over states: %d' % wfs.bd.comm.size)
69 if get_num_threads() > 1: # OpenMP threading
70 log(f'OpenMP threads: {get_num_threads()}')
71 log()
74def plot(atoms: Atoms) -> str:
75 """Ascii-art plot of the atoms."""
77 # y
78 # |
79 # .-- x
80 # /
81 # z
83 if atoms.cell.handedness != 1:
84 # See example we can't handle in test_ascii_art()
85 return ''
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
97 cell = np.diagonal(cell_cv) / Bohr
98 positions = atoms.get_positions() / Bohr
99 numbers = atoms.get_atomic_numbers()
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]])
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
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