Coverage for gpaw/test/utilities/test_ewald.py: 100%
96 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.utilities.ewald import Ewald
5def test_utilities_ewald():
6 verbose = True
8 # References for Madelung constants with homogenous background charges:
9 # M.P. Marder, "Condensed Matter Physics", J. Wiley, (2000),
10 # scaled to the Wigner-Seitz radius.
11 # References for Madelung constants of ionic crystals:
12 # Y. Sakamoto, The J. of Chem. Phys., vol. 28, (1958), p. 164,
13 # scaled to the nearest neighbor distance.
15 if 1: # fcc
16 cell = np.array([[0., .5, .5], [.5, .0, .5], [.5, .5, .0]])
17 basis = np.array([[0., 0., 0.]])
18 charges = np.array([1.])
19 r = np.array([0.0, 0.0, 0.0])
20 charges = np.array([1])
21 ewald = Ewald(cell)
22 e = ewald.get_electrostatic_potential(r, basis, charges,
23 excludefroml0=0)
24 a_this = -e * ewald.get_wigner_seitz_radius(sum(charges))
25 a_ref = 1.79175
26 if verbose:
27 print('Madelung energy, fcc:', a_this, a_this - a_ref)
28 assert abs(a_this - a_ref) < 1e-5
30 if 1: # hcp
31 a = 1.
32 c = np.sqrt(8. / 3.) * a
33 cell = np.array([[.5 * a, -0.5 * np.sqrt(3) * a, 0],
34 [.5 * a, 0.5 * np.sqrt(3) * a, 0], [0., 0., c]])
35 basis = np.array([[.5 * a, .5 / np.sqrt(3) * a, 0.],
36 [.5 * a, -.5 / np.sqrt(3) * a, 0.5 * c]])
37 r = np.array([.5 * a, .5 / np.sqrt(3) * a, 0.])
38 charges = np.array([1., 1.])
39 ewald = Ewald(cell)
40 e = ewald.get_electrostatic_potential(r, basis, charges,
41 excludefroml0=0)
42 a_this = -e * ewald.get_wigner_seitz_radius(sum(charges))
43 a_ref = 1.79168
44 if verbose:
45 print('Madelung energy, hcp:', a_this, a_this - a_ref)
46 assert abs(a_this - a_ref) < 1e-5
48 if 1: # simple cubic
49 cell = np.diag([1., 1., 1.])
50 basis = np.array([[0., 0., 0.]])
51 charges = np.array([1.])
52 r = np.array([0.0, 0.0, 0.0])
53 charges = np.array([1])
54 ewald = Ewald(cell)
55 e = ewald.get_electrostatic_potential(r, basis, charges,
56 excludefroml0=0)
57 a_this = -e * ewald.get_wigner_seitz_radius(1)
58 a_ref = 1.76012
59 if verbose:
60 print('Madelung energy, sc:', a_this, a_this - a_ref)
61 assert abs(a_this - a_ref) < 1e-5
63 if 1: # NaCl
64 cell = np.array([[0., .5, .5], [.5, .0, .5], [.5, .5, .0]])
65 basis = np.array([[0., 0., 0.], [.5, .5, .5]])
66 r = np.array([0.0, 0.0, 0.0])
67 charges = np.array([1, -1])
68 ewald = Ewald(cell)
69 e = ewald.get_electrostatic_potential(r, basis, charges,
70 excludefroml0=0)
71 a_this = -0.5 * e
72 a_ref = 1.7475645946331822
73 if verbose:
74 print('Madelung constant, NaCl (B1):', a_this, a_this - a_ref)
75 assert abs(a_this - a_ref) < 1e-13
77 if 0: # NaCl
78 cell = np.diag((1., 1., 1.))
79 basis = np.array([[0., 0., 0.], [.5, .5, .0],
80 [.5, .0, .5], [.0, .5, .5],
81 [.5, 0., 0.], [.0, .5, .0],
82 [.0, .0, .5], [.5, .5, .5]])
83 r = np.array([0.0, 0.0, 0.0])
84 charges = np.array([1, 1, 1, 1, -1, -1, -1, -1])
85 ewald = Ewald(cell)
86 e = ewald.get_electrostatic_potential(r, basis, charges,
87 excludefroml0=0)
88 a_this = -0.5 * e
89 a_ref = 1.7475645946331822
90 if verbose:
91 print('Madelung constant, NaCl (B1):', a_this, a_this - a_ref)
92 assert abs(a_this - a_ref) < 1e-13
94 if 1: # CsCl
95 cell = np.diag((1., 1., 1.))
96 basis = np.array([[0., 0., 0.], [.5, .5, .5]])
97 r = np.array([0.0, 0.0, 0.0])
98 charges = np.array([1, -1])
99 ewald = Ewald(cell)
100 e = ewald.get_electrostatic_potential(r, basis, charges,
101 excludefroml0=0)
102 a_this = -.5 * np.sqrt(3.) * e
103 a_ref = 1.76267477307099
104 if verbose:
105 print('Madelung constant, CsCl (B2):', a_this, a_this - a_ref)
106 assert abs(a_this - a_ref) < 1e-13
108 if 1: # Zincblende, cubic ZnS
109 cell = np.array([[.0, .5, .5], [.5, .0, .5], [.5, .5, .0]])
110 basis = np.array([[0., 0., 0.], [.25, .25, .25]])
111 r = np.array([0.0, 0.0, 0.0])
112 charges = np.array([1, -1])
113 ewald = Ewald(cell)
114 e = ewald.get_electrostatic_potential(r, basis, charges,
115 excludefroml0=0)
116 a_this = -0.25 * np.sqrt(3) * e
117 a_ref = 1.63805505338879
118 if verbose:
119 print('Madelung constant, Zincblende (B3):',
120 a_this, a_this - a_ref)
121 assert abs(a_this - a_ref) < 1e-13
123 if 1: # Ideal Wurtzite, ZnS, (B4)
124 a = 1.
125 c = np.sqrt(8. / 3.) * a
126 u = 3. / 8.
127 cell = np.array([[.5 * a, -0.5 * np.sqrt(3) * a, 0],
128 [.5 * a, 0.5 * np.sqrt(3) * a, 0], [0., 0., c]])
129 basis = np.array([[.5 * a, .5 / np.sqrt(3) * a, 0.],
130 [.5 * a, -.5 / np.sqrt(3) * a, 0.5 * c],
131 [.5 * a, .5 / np.sqrt(3) * a, u * c],
132 [.5 * a, -.5 / np.sqrt(3) * a, (.5 + u) * c]])
133 r = np.array([.5 * a, .5 / np.sqrt(3) * a, 0.])
134 charges = np.array([1., 1., -1, -1])
135 ewald = Ewald(cell)
136 e = ewald.get_electrostatic_potential(r, basis, charges,
137 excludefroml0=0)
138 a_this = -1. * u * c * e
139 a_ref = 1.64132162737
140 if verbose:
141 print('Madelung constant, Ideal Wurtzite (B4):', a_this,
142 a_this - a_ref)
143 assert abs(a_this - a_ref) < 1e-11