root / ase / calculators / interface.py @ 1
Historique | Voir | Annoter | Télécharger (4,86 ko)
1 |
import numpy as np |
---|---|
2 |
|
3 |
|
4 |
class Calculator: |
5 |
"""Class for demonstrating the ASE-calculator interface.
|
6 |
|
7 |
A good implementation of a calculator should store a copy of the
|
8 |
atoms object used for the last calculation. When one of the
|
9 |
*get_potential_energy*, *get_forces*, or *get_stress* methods is
|
10 |
called, the calculator should check if anything has changed since
|
11 |
the last calculation and only do the calculation if it's really
|
12 |
needed. The Atoms class implements the methods *__eq__* and
|
13 |
*__ne__* that can be used for checking identity (using *==* and
|
14 |
*!=*): Two sets of atoms are considered identical if they have the
|
15 |
same positions, atomic numbers, unit cell and periodic boundary
|
16 |
conditions."""
|
17 |
|
18 |
def get_potential_energy(self, atoms=None, force_consistent=False): |
19 |
"""Return total energy.
|
20 |
|
21 |
Both the energy extrapolated to zero Kelvin and the energy
|
22 |
consistent with the forces (the free energy) can be
|
23 |
returned."""
|
24 |
return 0.0 |
25 |
|
26 |
def get_forces(self, atoms): |
27 |
"""Return the forces."""
|
28 |
return np.zeros((len(atoms), 3)) |
29 |
|
30 |
def get_stress(self, atoms): |
31 |
"""Return the stress."""
|
32 |
return np.zeros((3, 3)) |
33 |
|
34 |
def calculation_required(self, atoms, quantities): |
35 |
"""Check if a calculation is required.
|
36 |
|
37 |
Check if the quantities in the *quantities* list have already
|
38 |
been calculated for the atomic configuration *atoms*. The
|
39 |
quantities can be one or more of: 'energy', 'forces', 'stress',
|
40 |
and 'magmoms'."""
|
41 |
return False |
42 |
|
43 |
def set_atoms(self, atoms): |
44 |
"""Let the calculator know the atoms.
|
45 |
|
46 |
This method is optional. If it exists, it will be called when
|
47 |
the *Atoms.set_calculator()* method is called.
|
48 |
|
49 |
*Don't* store a reference to *atoms* - that will create a
|
50 |
cyclic reference loop! Store a copy instead."""
|
51 |
self.atoms = atoms.copy()
|
52 |
|
53 |
|
54 |
class DFTCalculator(Calculator): |
55 |
"""Class for demonstrating the ASE interface to DFT-calculators."""
|
56 |
|
57 |
def get_number_of_bands(self): |
58 |
"""Return the number of bands."""
|
59 |
return 42 |
60 |
|
61 |
def get_xc_functional(self): |
62 |
"""Return the XC-functional identifier.
|
63 |
|
64 |
'LDA', 'PBE', ..."""
|
65 |
return 'LDA' |
66 |
|
67 |
def get_bz_k_points(self): |
68 |
"""Return all the k-points in the 1. Brillouin zone.
|
69 |
|
70 |
The coordinates are relative to reciprocal latice vectors."""
|
71 |
return np.zeros((1, 3)) |
72 |
|
73 |
def get_number_of_spins(self): |
74 |
"""Return the number of spins in the calculation.
|
75 |
|
76 |
Spin-paired calculations: 1, spin-polarized calculation: 2."""
|
77 |
return 1 |
78 |
|
79 |
def get_spin_polarized(self): |
80 |
"""Is it a spin-polarized calculation?"""
|
81 |
return False |
82 |
|
83 |
def get_ibz_k_points(self): |
84 |
"""Return k-points in the irreducible part of the Brillouin zone.
|
85 |
|
86 |
The coordinates are relative to reciprocal latice vectors."""
|
87 |
return np.zeros((1, 3)) |
88 |
|
89 |
def get_k_point_weights(self): |
90 |
"""Weights of the k-points.
|
91 |
|
92 |
The sum of all weights is one."""
|
93 |
return np.ones(1) |
94 |
|
95 |
def get_pseudo_density(self, spin=None, pad=True): |
96 |
"""Return pseudo-density array.
|
97 |
|
98 |
If *spin* is not given, then the total density is returned.
|
99 |
Otherwise, the spin up or down density is returned (spin=0 or
|
100 |
1)."""
|
101 |
return np.zeros((40, 40, 40)) |
102 |
|
103 |
def get_effective_potential(self, spin=0, pad=True): |
104 |
"""Return pseudo-effective-potential array."""
|
105 |
return np.zeros((40, 40, 40)) |
106 |
|
107 |
def get_pseudo_wave_function(self, band=0, kpt=0, spin=0, broadcast=True, |
108 |
pad=True):
|
109 |
"""Return pseudo-wave-function array."""
|
110 |
return np.zeros((40, 40, 40)) |
111 |
|
112 |
def get_eigenvalues(self, kpt=0, spin=0): |
113 |
"""Return eigenvalue array."""
|
114 |
return np.arange(42, float) |
115 |
|
116 |
def get_occupation_numbers(self, kpt=0, spin=0): |
117 |
"""Return occupation number array."""
|
118 |
return np.ones(42) |
119 |
|
120 |
def get_fermi_level(self): |
121 |
"""Return the Fermi level."""
|
122 |
return 0.0 |
123 |
|
124 |
def initial_wannier(self, initialwannier, kpointgrid, fixedstates, |
125 |
edf, spin): |
126 |
"""Initial guess for the shape of wannier functions.
|
127 |
|
128 |
Use initial guess for wannier orbitals to determine rotation
|
129 |
matrices U and C.
|
130 |
"""
|
131 |
raise NotImplementedError |
132 |
|
133 |
return c, U
|
134 |
|
135 |
def get_wannier_localization_matrix(self, nbands, dirG, kpoint, |
136 |
nextkpoint, G_I, spin): |
137 |
"""Calculate integrals for maximally localized Wannier functions."""
|
138 |
|
139 |
def get_magnetic_moment(self, atoms=None): |
140 |
"""Return the total magnetic moment."""
|
141 |
return self.occupation.magmom |
142 |
|
143 |
def get_number_of_grid_points(self): |
144 |
"""Return the shape of arrays."""
|
145 |
return self.gd.N_c |
146 |
|
147 |
|