Coverage for gpaw/new/pwfd/builder.py: 98%
63 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
1from math import pi
3import numpy as np
5from gpaw.new.builder import DFTComponentsBuilder
6from gpaw.new.pwfd.ibzwfs import PWFDIBZWaveFunctions
7from gpaw.new.lcao.eigensolver import LCAOEigensolver
8from gpaw.new.lcao.hamiltonian import LCAOHamiltonian
9from gpaw.new.pwfd.wave_functions import PWFDWaveFunctions
10from gpaw.core.arrays import XArrayWithNoData
13class PWFDDFTComponentsBuilder(DFTComponentsBuilder):
14 def __init__(self,
15 atoms,
16 params,
17 *,
18 comm=None,
19 log=None):
20 super().__init__(atoms, params, comm=comm, log=log)
21 qspiral = params.mode.qspiral
22 self.qspiral_v = (None if qspiral is None else
23 qspiral @ self.grid.icell * (2 * pi))
25 def create_eigensolver(self, hamiltonian):
26 from gpaw.dft import DefaultEigensolver
27 es = self.params.eigensolver
28 if isinstance(es, DefaultEigensolver):
29 es = es.from_param({'name': 'davidson', **es.params})
30 return es.build(
31 self.nbands,
32 self.wf_desc,
33 self.communicators['b'],
34 hamiltonian,
35 self.params.convergence.get('bands', 'occupied'),
36 self.setups,
37 self.atoms)
39 def read_ibz_wave_functions(self, reader):
40 kpt_comm, band_comm, domain_comm = (self.communicators[x]
41 for x in 'kbd')
43 def create_wfs(spin: int, q: int, k: int, kpt_c, weight: float):
44 psit_nG = XArrayWithNoData(
45 comm=band_comm,
46 dims=(self.nbands,),
47 desc=self.wf_desc.new(kpt=kpt_c),
48 xp=self.xp)
49 wfs = PWFDWaveFunctions(
50 spin=spin,
51 q=q,
52 k=k,
53 weight=weight,
54 psit_nX=psit_nG, # type: ignore
55 setups=self.setups,
56 relpos_ac=self.relpos_ac,
57 atomdist=self.atomdist,
58 ncomponents=self.ncomponents,
59 qspiral_v=self.qspiral_v)
61 return wfs
63 ibzwfs = PWFDIBZWaveFunctions.create(
64 ibz=self.ibz,
65 ncomponents=self.ncomponents,
66 create_wfs_func=create_wfs,
67 kpt_comm=self.communicators['k'],
68 kpt_band_comm=self.communicators['D'],
69 comm=self.communicators['w'])
71 # Set eigenvalues, occupations, etc..
72 self.read_wavefunction_values(reader, ibzwfs)
74 return ibzwfs
76 def create_ibz_wave_functions(self, basis, potential):
77 from gpaw.new.lcao.builder import create_lcao_ibzwfs
79 if self.params.random:
80 return self.create_random_ibz_wave_functions()
82 # sl_default = self.params.parallel['sl_default']
83 # sl_lcao = self.params.parallel['sl_lcao'] or sl_default
85 lcao_dtype = complex if \
86 np.issubdtype(self.dtype, np.complexfloating) else float
88 lcaonbands = min(self.nbands,
89 basis.Mmax * (2 if self.ncomponents == 4 else 1))
90 lcao_ibzwfs, _ = create_lcao_ibzwfs(
91 basis,
92 self.ibz, self.communicators, self.setups,
93 self.relpos_ac, self.grid, lcao_dtype,
94 lcaonbands, self.ncomponents, self.atomdist, self.nelectrons)
96 self.log('\nDiagonalizing LCAO Hamiltonian', flush=True)
98 hamiltonian = LCAOHamiltonian(basis)
99 LCAOEigensolver(basis).iterate(
100 lcao_ibzwfs, None, potential, hamiltonian)
102 self.log('Converting LCAO to grid', flush=True)
104 def create_wfs(spin, q, k, kpt_c, weight):
105 lcaowfs = lcao_ibzwfs.wfs_qs[q][spin]
106 assert lcaowfs.spin == spin
108 # Convert to PW-coefs in PW-mode:
109 psit_nX = self.convert_wave_functions_from_uniform_grid(
110 lcaowfs.C_nM, basis, kpt_c, q)
112 mylcaonbands, nao = lcaowfs.C_nM.dist.shape
113 mynbands = len(psit_nX.data)
114 eig_n = np.empty(self.nbands)
115 eig_n[:lcaonbands] = lcaowfs._eig_n
116 eig_n[lcaonbands:] = 100.0 # set high value for random wfs.
117 if mylcaonbands < mynbands:
118 psit_nX[mylcaonbands:].randomize(
119 seed=self.communicators['w'].rank)
120 wfs = PWFDWaveFunctions(
121 psit_nX=psit_nX,
122 spin=spin,
123 q=q,
124 k=k,
125 weight=weight,
126 setups=self.setups,
127 relpos_ac=self.relpos_ac,
128 atomdist=self.atomdist,
129 ncomponents=self.ncomponents,
130 qspiral_v=self.qspiral_v)
131 wfs._eig_n = eig_n
132 return wfs
134 return PWFDIBZWaveFunctions.create(
135 ibz=self.ibz,
136 ncomponents=self.ncomponents,
137 create_wfs_func=create_wfs,
138 kpt_comm=self.communicators['k'],
139 kpt_band_comm=self.communicators['D'],
140 comm=self.communicators['w'])
142 def create_random_ibz_wave_functions(self):
143 self.log('Initializing wave functions with random numbers')
145 def create_wfs(spin, q, k, kpt_c, weight):
146 desc = self.wf_desc.new(kpt=kpt_c)
147 psit_nX = desc.empty(
148 dims=(self.nbands,),
149 comm=self.communicators['b'],
150 xp=self.xp)
151 psit_nX.randomize()
153 wfs = PWFDWaveFunctions(
154 psit_nX=psit_nX,
155 spin=spin,
156 q=q,
157 k=k,
158 weight=weight,
159 setups=self.setups,
160 relpos_ac=self.relpos_ac,
161 atomdist=self.atomdist,
162 ncomponents=self.ncomponents,
163 qspiral_v=self.qspiral_v)
165 return wfs
167 return PWFDIBZWaveFunctions.create(
168 ibz=self.ibz,
169 ncomponents=self.ncomponents,
170 create_wfs_func=create_wfs,
171 kpt_comm=self.communicators['k'],
172 kpt_band_comm=self.communicators['D'],
173 comm=self.communicators['w'])