def set_positions(self, spos_ac, atom_partition=None): move_wfs = (self.kpt_u[0].psit_nG is not None and self.spos_ac is not None) if move_wfs: paste_wfs = self.wfs_mover.cut_wfs(self, spos_ac) # This will update the positions -- and transfer, if necessary -- # the projection matrices which may be necessary for updating # the wavefunctions. WaveFunctions.set_positions(self, spos_ac, atom_partition) if move_wfs and paste_wfs is not None: paste_wfs() self.set_orthonormalized(False) self.pt.set_positions(spos_ac, atom_partition) self.allocate_arrays_for_projections(self.pt.my_atom_indices) self.positions_set = True
def set_positions(self, spos_ac): WaveFunctions.set_positions(self, spos_ac) self.set_orthonormalized(False) self.pt.set_positions(spos_ac) self.allocate_arrays_for_projections(self.pt.my_atom_indices) self.positions_set = True
def set_positions(self, spos_ac): self.timer.start('Basic WFS set positions') WaveFunctions.set_positions(self, spos_ac) self.timer.stop('Basic WFS set positions') self.timer.start('Basis functions set positions') self.basis_functions.set_positions(spos_ac) self.timer.stop('Basis functions set positions') if self.ksl is not None: self.basis_functions.set_matrix_distribution(self.ksl.Mstart, self.ksl.Mstop) nq = len(self.kd.ibzk_qc) nao = self.setups.nao mynbands = self.bd.mynbands Mstop = self.ksl.Mstop Mstart = self.ksl.Mstart mynao = Mstop - Mstart if self.ksl.using_blacs: # XXX # S and T have been distributed to a layout with blacs, so # discard them to force reallocation from scratch. # # TODO: evaluate S and T when they *are* distributed, thus saving # memory and avoiding this problem self.S_qMM = None self.T_qMM = None S_qMM = self.S_qMM T_qMM = self.T_qMM if S_qMM is None: # XXX # First time: assert T_qMM is None if self.ksl.using_blacs: # XXX self.tci.set_matrix_distribution(Mstart, mynao) S_qMM = np.empty((nq, mynao, nao), self.dtype) T_qMM = np.empty((nq, mynao, nao), self.dtype) for kpt in self.kpt_u: if kpt.C_nM is None: kpt.C_nM = np.empty((mynbands, nao), self.dtype) self.allocate_arrays_for_projections( self.basis_functions.my_atom_indices) self.P_aqMi = {} for a in self.basis_functions.my_atom_indices: ni = self.setups[a].ni self.P_aqMi[a] = np.empty((nq, nao, ni), self.dtype) for kpt in self.kpt_u: q = kpt.q kpt.P_aMi = dict([(a, P_qMi[q]) for a, P_qMi in self.P_aqMi.items()]) self.timer.start('TCI: Calculate S, T, P') # Calculate lower triangle of S and T matrices: self.tci.calculate(spos_ac, S_qMM, T_qMM, self.P_aqMi) add_paw_correction_to_overlap(self.setups, self.P_aqMi, S_qMM, self.ksl.Mstart, self.ksl.Mstop) self.timer.stop('TCI: Calculate S, T, P') S_MM = None # allow garbage collection of old S_qMM after redist S_qMM = self.ksl.distribute_overlap_matrix(S_qMM) T_qMM = self.ksl.distribute_overlap_matrix(T_qMM) for kpt in self.kpt_u: q = kpt.q kpt.S_MM = S_qMM[q] kpt.T_MM = T_qMM[q] if (debug and self.band_comm.size == 1 and self.gd.comm.rank == 0 and nao > 0 and not self.ksl.using_blacs): # S and T are summed only on comm master, so check only there from numpy.linalg import eigvalsh self.timer.start('Check positive definiteness') for S_MM in S_qMM: tri2full(S_MM, UL='L') smin = eigvalsh(S_MM).real.min() if smin < 0: raise RuntimeError('Overlap matrix has negative ' 'eigenvalue: %e' % smin) self.timer.stop('Check positive definiteness') self.positions_set = True self.S_qMM = S_qMM self.T_qMM = T_qMM
def set_positions(self, spos_ac): self.timer.start('Basic WFS set positions') WaveFunctions.set_positions(self, spos_ac) self.timer.stop('Basic WFS set positions') self.timer.start('Basis functions set positions') self.basis_functions.set_positions(spos_ac) self.timer.stop('Basis functions set positions') if self.ksl is not None: self.basis_functions.set_matrix_distribution(self.ksl.Mstart, self.ksl.Mstop) nq = len(self.kd.ibzk_qc) nao = self.setups.nao mynbands = self.mynbands Mstop = self.ksl.Mstop Mstart = self.ksl.Mstart mynao = Mstop - Mstart if self.ksl.using_blacs: # XXX # S and T have been distributed to a layout with blacs, so # discard them to force reallocation from scratch. # # TODO: evaluate S and T when they *are* distributed, thus saving # memory and avoiding this problem self.S_qMM = None self.T_qMM = None S_qMM = self.S_qMM T_qMM = self.T_qMM if S_qMM is None: # XXX # First time: assert T_qMM is None if self.ksl.using_blacs: # XXX self.tci.set_matrix_distribution(Mstart, mynao) S_qMM = np.empty((nq, mynao, nao), self.dtype) T_qMM = np.empty((nq, mynao, nao), self.dtype) for kpt in self.kpt_u: if kpt.C_nM is None: kpt.C_nM = np.empty((mynbands, nao), self.dtype) self.allocate_arrays_for_projections( self.basis_functions.my_atom_indices) self.P_aqMi = {} for a in self.basis_functions.my_atom_indices: ni = self.setups[a].ni self.P_aqMi[a] = np.empty((nq, nao, ni), self.dtype) for kpt in self.kpt_u: q = kpt.q kpt.P_aMi = dict([(a, P_qMi[q]) for a, P_qMi in self.P_aqMi.items()]) self.timer.start('TCI: Calculate S, T, P') # Calculate lower triangle of S and T matrices: self.tci.calculate(spos_ac, S_qMM, T_qMM, self.P_aqMi) add_paw_correction_to_overlap(self.setups, self.P_aqMi, S_qMM, self.ksl.Mstart, self.ksl.Mstop) self.timer.stop('TCI: Calculate S, T, P') S_MM = None # allow garbage collection of old S_qMM after redist S_qMM = self.ksl.distribute_overlap_matrix(S_qMM) T_qMM = self.ksl.distribute_overlap_matrix(T_qMM) for kpt in self.kpt_u: q = kpt.q kpt.S_MM = S_qMM[q] kpt.T_MM = T_qMM[q] if (debug and self.band_comm.size == 1 and self.gd.comm.rank == 0 and nao > 0 and not self.ksl.using_blacs): # S and T are summed only on comm master, so check only there from numpy.linalg import eigvalsh self.timer.start('Check positive definiteness') for S_MM in S_qMM: tri2full(S_MM, UL='L') smin = eigvalsh(S_MM).real.min() if smin < 0: raise RuntimeError('Overlap matrix has negative ' 'eigenvalue: %e' % smin) self.timer.stop('Check positive definiteness') self.positions_set = True self.S_qMM = S_qMM self.T_qMM = T_qMM
def set_positions(self, spos_ac, atom_partition=None, move_wfs=False): oldspos_ac = self.spos_ac with self.timer('Basic WFS set positions'): WaveFunctions.set_positions(self, spos_ac, atom_partition) with self.timer('Basis functions set positions'): self.basis_functions.set_positions(spos_ac) if self.ksl is not None: self.basis_functions.set_matrix_distribution(self.ksl.Mstart, self.ksl.Mstop) nq = len(self.kd.ibzk_qc) nao = self.setups.nao mynbands = self.bd.mynbands Mstop = self.ksl.Mstop Mstart = self.ksl.Mstart mynao = Mstop - Mstart #if self.ksl.using_blacs: # XXX # S and T have been distributed to a layout with blacs, so # discard them to force reallocation from scratch. # # TODO: evaluate S and T when they *are* distributed, thus saving # memory and avoiding this problem for kpt in self.kpt_u: kpt.S_MM = None kpt.T_MM = None # Free memory in case of old matrices: self.S_qMM = self.T_qMM = self.P_aqMi = None if self.dtype == complex and oldspos_ac is not None: update_phases([kpt.C_nM for kpt in self.kpt_u], [kpt.q for kpt in self.kpt_u], self.kd.ibzk_qc, spos_ac, oldspos_ac, self.setups, Mstart) for kpt in self.kpt_u: if kpt.C_nM is None: kpt.C_nM = np.empty((mynbands, nao), self.dtype) if 0:#self.debug_tci: #if self.ksl.using_blacs: # self.tci.set_matrix_distribution(Mstart, mynao) oldS_qMM = np.empty((nq, mynao, nao), self.dtype) oldT_qMM = np.empty((nq, mynao, nao), self.dtype) oldP_aqMi = {} for a in self.basis_functions.my_atom_indices: ni = self.setups[a].ni oldP_aqMi[a] = np.empty((nq, nao, ni), self.dtype) # Calculate lower triangle of S and T matrices: self.timer.start('tci calculate') #self.tci.calculate(spos_ac, oldS_qMM, oldT_qMM, # oldP_aqMi) self.timer.stop('tci calculate') self.timer.start('mktci') manytci = self.tciexpansions.get_manytci_calculator( self.setups, self.gd, spos_ac, self.kd.ibzk_qc, self.dtype, self.timer) self.timer.stop('mktci') self.manytci = manytci self.newtci = manytci.tci my_atom_indices = self.basis_functions.my_atom_indices self.timer.start('ST tci') newS_qMM, newT_qMM = manytci.O_qMM_T_qMM(self.gd.comm, Mstart, Mstop, self.ksl.using_blacs) self.timer.stop('ST tci') self.timer.start('P tci') P_qIM = manytci.P_qIM(my_atom_indices) self.timer.stop('P tci') self.P_aqMi = newP_aqMi = manytci.P_aqMi(my_atom_indices) self.P_qIM = P_qIM # XXX atomic correction # TODO # OK complex/conj, periodic images # OK scalapack # derivatives/forces # sparse # use symmetry/conj tricks to reduce calculations # enable caching of spherical harmonics #if self.atomic_correction.name != 'dense': #from gpaw.lcao.newoverlap import newoverlap #self.P_neighbors_a, self.P_aaqim = newoverlap(self, spos_ac) self.atomic_correction.gobble_data(self) #if self.atomic_correction.name == 'scipy': # Pold_qIM = self.atomic_correction.Psparse_qIM # for q in range(nq): # maxerr = abs(Pold_qIM[q] - P_qIM[q]).max() # print('sparse maxerr', maxerr) # assert maxerr == 0 self.atomic_correction.add_overlap_correction(self, newS_qMM) if self.debug_tci: self.atomic_correction.add_overlap_correction(self, oldS_qMM) if self.atomic_correction.implements_distributed_projections(): my_atom_indices = self.atomic_correction.get_a_values() else: my_atom_indices = self.basis_functions.my_atom_indices self.allocate_arrays_for_projections(my_atom_indices) #S_MM = None # allow garbage collection of old S_qMM after redist if self.debug_tci: oldS_qMM = self.ksl.distribute_overlap_matrix(oldS_qMM, root=-1) oldT_qMM = self.ksl.distribute_overlap_matrix(oldT_qMM, root=-1) newS_qMM = self.ksl.distribute_overlap_matrix(newS_qMM, root=-1) newT_qMM = self.ksl.distribute_overlap_matrix(newT_qMM, root=-1) #if (debug and self.bd.comm.size == 1 and self.gd.comm.rank == 0 and # nao > 0 and not self.ksl.using_blacs): # S and T are summed only on comm master, so check only there # from numpy.linalg import eigvalsh # self.timer.start('Check positive definiteness') # for S_MM in S_qMM: # tri2full(S_MM, UL='L') # smin = eigvalsh(S_MM).real.min() # if smin < 0: # raise RuntimeError('Overlap matrix has negative ' # 'eigenvalue: %e' % smin) # self.timer.stop('Check positive definiteness') self.positions_set = True if self.debug_tci: Serr = np.abs(newS_qMM - oldS_qMM).max() Terr = np.abs(newT_qMM - oldT_qMM).max() print('S maxerr', Serr) print('T maxerr', Terr) try: assert Terr < 1e-15, Terr except AssertionError: np.set_printoptions(precision=6) if self.world.rank == 0: print(newT_qMM) print(oldT_qMM) print(newT_qMM - oldT_qMM) raise assert Serr < 1e-15, Serr assert len(oldP_aqMi) == len(newP_aqMi) for a in oldP_aqMi: Perr = np.abs(oldP_aqMi[a] - newP_aqMi[a]).max() assert Perr < 1e-15, (a, Perr) for kpt in self.kpt_u: q = kpt.q kpt.S_MM = newS_qMM[q] kpt.T_MM = newT_qMM[q] self.S_qMM = newS_qMM self.T_qMM = newT_qMM # Elpa wants to reuse the decomposed form of S_qMM. # We need to keep track of the existence of that object here, # since this is where we change S_qMM. Hence, expect this to # become arrays after the first diagonalization: self.decomposed_S_qMM = [None] * len(self.S_qMM)