def check_and_plot(self, A_nn, A0_nn, digits, keywords=''): # Construct fingerprint of input matrices for comparison fingerprint = np.array([md5_array(A_nn, numeric=True), md5_array(A0_nn, numeric=True)]) # Compare fingerprints across all processors fingerprints = np.empty((world.size, 2), np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') # If assertion fails, catch temporarily while plotting, then re-raise try: self.assertAlmostEqual(np.abs(A_nn-A0_nn).max(), 0, digits) except AssertionError: if world.rank == 0 and mpl is not None: from matplotlib.figure import Figure fig = Figure() ax = fig.add_axes([0.0, 0.1, 1.0, 0.83]) ax.set_title(self.__class__.__name__) im = ax.imshow(np.abs(A_nn-A0_nn), interpolation='nearest') fig.colorbar(im) fig.text(0.5, 0.05, 'Keywords: ' + keywords, \ horizontalalignment='center', verticalalignment='top') from matplotlib.backends.backend_agg import FigureCanvasAgg img = 'ut_hsops_%s_%s.png' % (self.__class__.__name__, \ '_'.join(keywords.split(','))) FigureCanvasAgg(fig).print_figure(img.lower(), dpi=90) raise
def check_and_plot(self, A_nn, A0_nn, digits, keywords=''): # Construct fingerprint of input matrices for comparison fingerprint = np.array( [md5_array(A_nn, numeric=True), md5_array(A0_nn, numeric=True)]) # Compare fingerprints across all processors fingerprints = np.empty((world.size, 2), np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') # If assertion fails, catch temporarily while plotting, then re-raise try: self.assertAlmostEqual(np.abs(A_nn - A0_nn).max(), 0, digits) except AssertionError: if world.rank == 0 and mpl is not None: from matplotlib.figure import Figure fig = Figure() ax = fig.add_axes([0.0, 0.1, 1.0, 0.83]) ax.set_title(self.__class__.__name__) im = ax.imshow(np.abs(A_nn - A0_nn), interpolation='nearest') fig.colorbar(im) fig.text(0.5, 0.05, 'Keywords: ' + keywords, \ horizontalalignment='center', verticalalignment='top') from matplotlib.backends.backend_agg import FigureCanvasAgg img = 'ut_hsops_%s_%s.png' % (self.__class__.__name__, \ '_'.join(keywords.split(','))) FigureCanvasAgg(fig).print_figure(img.lower(), dpi=90) raise
def test_overlap_inverse_before(self): kpt = self.wfs.kpt_u[0] kpt.P_ani = self.pt.dict(self.bd.mynbands) ppo = ProjectorPairOverlap(self.wfs, self.atoms) # Compare fingerprints across all processors fingerprint = np.array([md5_array(ppo.B_aa, numeric=True)]) fingerprints = np.empty(world.size, np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') work_nG = np.empty_like(self.psit_nG) self.pt.integrate(self.psit_nG, kpt.P_ani, kpt.q) P0_ani = dict([(a,P_ni.copy()) for a,P_ni in kpt.P_ani.items()]) ppo.apply_inverse(self.psit_nG, work_nG, self.wfs, kpt, calculate_P_ani=False) res_nG = np.empty_like(self.psit_nG) ppo.apply(work_nG, res_nG, self.wfs, kpt, calculate_P_ani=True) del work_nG P_ani = self.pt.dict(self.bd.mynbands) self.pt.integrate(res_nG, P_ani, kpt.q) abserr = np.empty(1, dtype=float) for n in range(self.nbands): band_rank, myn = self.bd.who_has(n) if band_rank == self.bd.comm.rank: abserr[:] = np.abs(self.psit_nG[myn] - res_nG[myn]).max() self.gd.comm.max(abserr) self.bd.comm.broadcast(abserr, band_rank) self.assertAlmostEqual(abserr.item(), 0, 10) self.check_and_plot(P_ani, P0_ani, 10, 'overlap,inverse,before')
def update_references(self, kpt_u, rank_a): requests = [] kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm for u in range(self.kd_old.nks): kpt_rank, myu = self.kd_old.who_has(u) for n in range(self.bd.nbands): band_rank, myn = self.bd.who_has(n) for a in range(self.natoms): domain_rank = rank_a[a] if kpt_comm.rank == kpt_rank and \ band_comm.rank == band_rank and \ domain_comm.rank == domain_rank: kpt = kpt_u[myu] chk = md5_array(kpt.P_ani[a][myn], numeric=True) if world.rank == 0: self.chk_una[u, n, a] = chk else: requests.append(world.send(np.array([chk], \ dtype=np.int64), 0, 1303+a, block=False)) elif world.rank == 0: world_rank = rank_a[a] + \ band_rank * domain_comm.size + \ kpt_rank * domain_comm.size * band_comm.size chk = self.chk_una[u, n, a:a + 1] #XXX hack to get pointer requests.append(world.receive(chk, world_rank, \ 1303+a, block=False)) world.waitall(requests) world.broadcast(self.chk_una, 0)
def compare_atoms(atoms, comm=world): """Check whether atoms objects are identical on all processors.""" # Construct fingerprint: # ASE may return slightly different atomic positions (e.g. due # to MKL) so compare only first 8 decimals of positions fingerprint = np.array([md5_array(array, numeric=True) for array in [atoms.positions.round(8), atoms.cell, atoms.pbc * 1.0, atoms.get_initial_magnetic_moments()]]) # Compare fingerprints: fingerprints = np.empty((comm.size, 4), fingerprint.dtype) comm.all_gather(fingerprint, fingerprints) mismatches = fingerprints.ptp(0) if debug: dumpfile = 'compare_atoms' for i in np.argwhere(mismatches).ravel(): itemname = ['positions', 'cell', 'pbc', 'magmoms'][i] itemfps = fingerprints[:, i] itemdata = [atoms.positions, atoms.cell, atoms.pbc * 1.0, atoms.get_initial_magnetic_moments()][i] if comm.rank == 0: print('DEBUG: compare_atoms failed for %s' % itemname) itemfps.dump('%s_fps_%s.pickle' % (dumpfile, itemname)) itemdata.dump('%s_r%04d_%s.pickle' % (dumpfile, comm.rank, itemname)) # Use only the atomic positions from rank 0 comm.broadcast(atoms.positions, 0) return not mismatches.any()
def compare_atoms(atoms, comm=world): """Check whether atoms objects are identical on all processors.""" # Construct fingerprint: fingerprint = np.array([md5_array(array, numeric=True) for array in [atoms.positions, atoms.cell, atoms.pbc * 1.0, atoms.get_initial_magnetic_moments()]]) # Compare fingerprints: fingerprints = np.empty((comm.size, 4), fingerprint.dtype) comm.all_gather(fingerprint, fingerprints) mismatches = fingerprints.ptp(0) if debug: dumpfile = 'compare_atoms' for i in np.argwhere(mismatches).ravel(): itemname = ['positions', 'cell', 'pbc', 'magmoms'][i] itemfps = fingerprints[:, i] itemdata = [atoms.positions, atoms.cell, atoms.pbc * 1.0, atoms.get_initial_magnetic_moments()][i] if comm.rank == 0: print 'DEBUG: compare_atoms failed for %s' % itemname itemfps.dump('%s_fps_%s.pickle' % (dumpfile, itemname)) itemdata.dump('%s_r%04d_%s.pickle' % (dumpfile, comm.rank, itemname)) return not mismatches.any()
def update_references(self, kpt_u, rank_a): requests = [] kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm for u in range(self.kd_old.nks): kpt_rank, myu = self.kd_old.who_has(u) for n in range(self.bd.nbands): band_rank, myn = self.bd.who_has(n) for a in range(self.natoms): domain_rank = rank_a[a] if kpt_comm.rank == kpt_rank and \ band_comm.rank == band_rank and \ domain_comm.rank == domain_rank: kpt = kpt_u[myu] chk = md5_array(kpt.P_ani[a][myn], numeric=True) if world.rank == 0: self.chk_una[u,n,a] = chk else: requests.append(world.send(np.array([chk], \ dtype=np.int64), 0, 1303+a, block=False)) elif world.rank == 0: world_rank = rank_a[a] + \ band_rank * domain_comm.size + \ kpt_rank * domain_comm.size * band_comm.size chk = self.chk_una[u,n,a:a+1] #XXX hack to get pointer requests.append(world.receive(chk, world_rank, \ 1303+a, block=False)) world.waitall(requests) world.broadcast(self.chk_una, 0)
def create_random_atoms(gd, nmolecules=10, name='NH2', mindist=4.5 / Bohr): """Create gas-like collection of atoms from randomly placed molecules. Applies rigid motions to molecules, translating the COM and/or rotating by a given angle around an axis of rotation through the new COM. These atomic positions obey the minimum distance requirement to zero-boundaries. Warning: This is only intended for testing parallel grid/LFC consistency. """ atoms = Atoms(cell=gd.cell_cv * Bohr, pbc=gd.pbc_c) # Store the original state of the random number generator randstate = np.random.get_state() seed = np.array([md5_array(data, numeric=True) for data in [nmolecules, gd.cell_cv, gd.pbc_c, gd.N_c]]).astype(int) np.random.seed(seed % 4294967296) for m in range(nmolecules): amol = molecule(name) amol.set_cell(gd.cell_cv * Bohr) # Rotate the molecule around COM according to three random angles # The rotation axis is given by spherical angles phi and theta v,phi,theta = np.random.uniform(0.0, 2*np.pi, 3) # theta [0,pi[ really axis = np.array([cos(phi)*sin(theta), sin(phi)*sin(theta), cos(theta)]) amol.rotate(axis, v) # Find the scaled length we must transverse along the given axes such # that the resulting displacement vector is `mindist` from the cell # face corresponding to that direction (plane with unit normal n_v). sdist_c = np.empty(3) if not gd.orthogonal: for c in range(3): n_v = gd.xxxiucell_cv[c] / np.linalg.norm(gd.xxxiucell_cv[c]) sdist_c[c] = mindist / np.dot(gd.cell_cv[c], n_v) else: sdist_c[:] = mindist / gd.cell_cv.diagonal() assert np.all(sdist_c > 0), 'Displacment vectors must be inside cell.' # Scaled dimensions of the smallest possible box centered on the COM spos_ac = amol.get_scaled_positions() # NB! must not do a "% 1.0" scom_c = np.dot(gd.icell_cv, amol.get_center_of_mass()) sbox_c = np.abs(spos_ac-scom_c[np.newaxis,:]).max(axis=0) sdelta_c = (1-np.array(gd.pbc_c)) * (sbox_c + sdist_c) assert (sdelta_c < 1.0-sdelta_c).all(), 'Box is too tight to fit atoms.' scenter_c = [np.random.uniform(d,1-d) for d in sdelta_c] center_v = np.dot(scenter_c, gd.cell_cv) # Translate the molecule such that COM is located at random center offset_av = (center_v-amol.get_center_of_mass()/Bohr)[np.newaxis,:] amol.set_positions(amol.get_positions()+offset_av*Bohr) assert np.linalg.norm(center_v-amol.get_center_of_mass()/Bohr) < 1e-9 atoms.extend(amol) # Restore the original state of the random number generator np.random.set_state(randstate) assert compare_atoms(atoms) return atoms
def create_random_atoms(gd, nmolecules=10, name='H2O', mindist=4.5 / Bohr): """Create gas-like collection of atoms from randomly placed molecules. Applies rigid motions to molecules, translating the COM and/or rotating by a given angle around an axis of rotation through the new COM. These atomic positions obey the minimum distance requirement to zero-boundaries. Warning: This is only intended for testing parallel grid/LFC consistency. """ atoms = Atoms(cell=gd.cell_cv * Bohr, pbc=gd.pbc_c) # Store the original state of the random number generator randstate = np.random.get_state() np.random.seed(np.array([md5_array(data, numeric=True) for data in [nmolecules, gd.cell_cv, gd.pbc_c, gd.N_c]]).astype(int)) for m in range(nmolecules): amol = molecule(name) amol.set_cell(gd.cell_cv * Bohr) # Rotate the molecule around COM according to three random angles # The rotation axis is given by spherical angles phi and theta v,phi,theta = np.random.uniform(0.0, 2*np.pi, 3) # theta [0,pi[ really axis = np.array([cos(phi)*sin(theta), sin(phi)*sin(theta), cos(theta)]) amol.rotate(axis, v) # Find the scaled length we must transverse along the given axes such # that the resulting displacement vector is `mindist` from the cell # face corresponding to that direction (plane with unit normal n_v). sdist_c = np.empty(3) if not gd.orthogonal: for c in range(3): n_v = gd.xxxiucell_cv[c] / np.linalg.norm(gd.xxxiucell_cv[c]) sdist_c[c] = mindist / np.dot(gd.cell_cv[c], n_v) else: sdist_c[:] = mindist / gd.cell_cv.diagonal() assert np.all(sdist_c > 0), 'Displacment vectors must be inside cell.' # Scaled dimensions of the smallest possible box centered on the COM spos_ac = amol.get_scaled_positions() # NB! must not do a "% 1.0" scom_c = np.dot(gd.icell_cv, amol.get_center_of_mass()) sbox_c = np.abs(spos_ac-scom_c[np.newaxis,:]).max(axis=0) sdelta_c = (1-np.array(gd.pbc_c)) * (sbox_c + sdist_c) assert (sdelta_c < 1.0-sdelta_c).all(), 'Box is too tight to fit atoms.' scenter_c = [np.random.uniform(d,1-d) for d in sdelta_c] center_v = np.dot(scenter_c, gd.cell_cv) # Translate the molecule such that COM is located at random center offset_av = (center_v-amol.get_center_of_mass()/Bohr)[np.newaxis,:] amol.set_positions(amol.get_positions()+offset_av*Bohr) assert np.linalg.norm(center_v-amol.get_center_of_mass()/Bohr) < 1e-9 atoms.extend(amol) # Restore the original state of the random number generator np.random.set_state(randstate) assert compare_atoms(atoms) return atoms
def check_values(self, M_asp, rank_a): self.holm_nielsen_check(M_asp.keys()) # Compare to reference checksums ret = True domain_comm = self.gd.comm for s in range(self.kd_old.nspins): for a in range(self.natoms): domain_rank = rank_a[a] if domain_comm.rank == domain_rank: chk = md5_array(M_asp[a][s], numeric=True) ret &= (chk == self.chk_sa[s, a]) self.assertTrue(ret)
def check_values(self, M_asp, rank_a): self.holm_nielsen_check(M_asp.keys()) # Compare to reference checksums ret = True domain_comm = self.gd.comm for s in range(self.kd_old.nspins): for a in range(self.natoms): domain_rank = rank_a[a] if domain_comm.rank == domain_rank: chk = md5_array(M_asp[a][s], numeric=True) ret &= (chk == self.chk_sa[s,a]) self.assertTrue(ret)
def test_projection_linearity(self): kpt = self.wfs.kpt_u[0] Q_ani = self.pt.dict(self.bd.mynbands) self.pt.integrate(self.psit_nG, Q_ani, q=kpt.q) for Q_ni in Q_ani.values(): self.assertTrue(Q_ni.dtype == self.dtype) P0_ani = dict([(a, Q_ni.copy()) for a, Q_ni in Q_ani.items()]) self.pt.add(self.psit_nG, Q_ani, q=kpt.q) self.pt.integrate(self.psit_nG, P0_ani, q=kpt.q) #rank_a = self.gd.get_ranks_from_positions(spos_ac) #my_atom_indices = np.argwhere(self.gd.comm.rank == rank_a).ravel() # ~ a ~ a' #TODO XXX should fix PairOverlap-ish stuff for < p | phi > overlaps # i i' #spos_ac = self.pt.spos_ac # NewLFC doesn't have this spos_ac = self.atoms.get_scaled_positions() % 1.0 gpo = GridPairOverlap(self.gd, self.setups) B_aa = gpo.calculate_overlaps(spos_ac, self.pt) # Compare fingerprints across all processors fingerprint = np.array([md5_array(B_aa, numeric=True)]) fingerprints = np.empty(world.size, np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') P_ani = dict([(a, Q_ni.copy()) for a, Q_ni in Q_ani.items()]) for a1 in range(len(self.atoms)): if a1 in P_ani.keys(): P_ni = P_ani[a1] else: # Atom a1 is not in domain so allocate a temporary buffer P_ni = np.zeros(( self.bd.mynbands, self.setups[a1].ni, ), dtype=self.dtype) for a2, Q_ni in Q_ani.items(): # B_aa are the projector overlaps across atomic pairs B_ii = gpo.extract_atomic_pair_matrix(B_aa, a1, a2) P_ni += np.dot(Q_ni, B_ii.T) #sum over a2 and last i in B_ii self.gd.comm.sum(P_ni) self.check_and_plot(P_ani, P0_ani, 8, 'projection,linearity')
def test_projection_linearity(self): kpt = self.wfs.kpt_u[0] Q_ani = self.pt.dict(self.bd.mynbands) self.pt.integrate(self.psit_nG, Q_ani, q=kpt.q) for Q_ni in Q_ani.values(): self.assertTrue(Q_ni.dtype == self.dtype) P0_ani = dict([(a,Q_ni.copy()) for a,Q_ni in Q_ani.items()]) self.pt.add(self.psit_nG, Q_ani, q=kpt.q) self.pt.integrate(self.psit_nG, P0_ani, q=kpt.q) #rank_a = self.gd.get_ranks_from_positions(spos_ac) #my_atom_indices = np.argwhere(self.gd.comm.rank == rank_a).ravel() # ~ a ~ a' #TODO XXX should fix PairOverlap-ish stuff for < p | phi > overlaps # i i' #spos_ac = self.pt.spos_ac # NewLFC doesn't have this spos_ac = self.atoms.get_scaled_positions() % 1.0 gpo = GridPairOverlap(self.gd, self.setups) B_aa = gpo.calculate_overlaps(spos_ac, self.pt) # Compare fingerprints across all processors fingerprint = np.array([md5_array(B_aa, numeric=True)]) fingerprints = np.empty(world.size, np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') P_ani = dict([(a,Q_ni.copy()) for a,Q_ni in Q_ani.items()]) for a1 in range(len(self.atoms)): if a1 in P_ani.keys(): P_ni = P_ani[a1] else: # Atom a1 is not in domain so allocate a temporary buffer P_ni = np.zeros((self.bd.mynbands,self.setups[a1].ni,), dtype=self.dtype) for a2, Q_ni in Q_ani.items(): # B_aa are the projector overlaps across atomic pairs B_ii = gpo.extract_atomic_pair_matrix(B_aa, a1, a2) P_ni += np.dot(Q_ni, B_ii.T) #sum over a2 and last i in B_ii self.gd.comm.sum(P_ni) self.check_and_plot(P_ani, P0_ani, 8, 'projection,linearity')
def update_references(self, M_asp, rank_a): requests = [] domain_comm = self.gd.comm for s in range(self.kd_old.nspins): for a in range(self.natoms): domain_rank = rank_a[a] if domain_comm.rank == domain_rank: chk = md5_array(M_asp[a][s], numeric=True) if domain_comm.rank == 0: self.chk_sa[s,a] = chk else: requests.append(domain_comm.send(np.array([chk], \ dtype=np.int64), 0, 2606+a, block=False)) elif domain_comm.rank == 0: chk = self.chk_sa[s,a:a+1] #XXX hack to get pointer requests.append(domain_comm.receive(chk, domain_rank, \ 2606+a, block=False)) domain_comm.waitall(requests) domain_comm.broadcast(self.chk_sa, 0)
def update_references(self, M_asp, rank_a): requests = [] domain_comm = self.gd.comm for s in range(self.kd_old.nspins): for a in range(self.natoms): domain_rank = rank_a[a] if domain_comm.rank == domain_rank: chk = md5_array(M_asp[a][s], numeric=True) if domain_comm.rank == 0: self.chk_sa[s, a] = chk else: requests.append(domain_comm.send(np.array([chk], \ dtype=np.int64), 0, 2606+a, block=False)) elif domain_comm.rank == 0: chk = self.chk_sa[s, a:a + 1] #XXX hack to get pointer requests.append(domain_comm.receive(chk, domain_rank, \ 2606+a, block=False)) domain_comm.waitall(requests) domain_comm.broadcast(self.chk_sa, 0)
def check_values(self, kpt_u, rank_a): for kpt in kpt_u: self.holm_nielsen_check(kpt.P_ani.keys()) # Compare to reference checksums ret = True kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm for u in range(self.kd_old.nks): kpt_rank, myu = self.kd_old.who_has(u) for n in range(self.bd.nbands): band_rank, myn = self.bd.who_has(n) for a in range(self.natoms): domain_rank = rank_a[a] if kpt_comm.rank == kpt_rank and \ band_comm.rank == band_rank and \ domain_comm.rank == domain_rank: kpt = kpt_u[myu] chk = md5_array(kpt.P_ani[a][myn], numeric=True) ret &= (chk == self.chk_una[u,n,a]) self.assertTrue(ret)
def check_values(self, kpt_u, rank_a): for kpt in kpt_u: self.holm_nielsen_check(kpt.P_ani.keys()) # Compare to reference checksums ret = True kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm for u in range(self.kd_old.nks): kpt_rank, myu = self.kd_old.who_has(u) for n in range(self.bd.nbands): band_rank, myn = self.bd.who_has(n) for a in range(self.natoms): domain_rank = rank_a[a] if kpt_comm.rank == kpt_rank and \ band_comm.rank == band_rank and \ domain_comm.rank == domain_rank: kpt = kpt_u[myu] chk = md5_array(kpt.P_ani[a][myn], numeric=True) ret &= (chk == self.chk_una[u, n, a]) self.assertTrue(ret)
def test_extrapolate_inverse(self): kpt = self.wfs.kpt_u[0] ppo = ProjectorPairOverlap(self.wfs, self.atoms) # Compare fingerprints across all processors fingerprint = np.array([md5_array(ppo.B_aa, numeric=True)]) fingerprints = np.empty(world.size, np.int64) world.all_gather(fingerprint, fingerprints) if fingerprints.ptp(0).any(): raise RuntimeError('Distributed matrices are not identical!') work_nG = np.empty_like(self.psit_nG) P_ani = ppo.apply_inverse(self.psit_nG, work_nG, self.wfs, kpt, \ calculate_P_ani=True, extrapolate_P_ani=True) P0_ani = self.pt.dict(self.bd.mynbands) self.pt.integrate(work_nG, P0_ani, kpt.q) del work_nG self.check_and_plot(P_ani, P0_ani, 11, 'extrapolate,inverse')
def test_contents_projection(self): # Distribute inverse effective charges to everybody in domain all_Qeff_a = np.empty(len(self.atoms), dtype=float) for a,rank in enumerate(self.rank_a): if rank == self.gd.comm.rank: Qeff = np.array([self.Qeff_a[a]]) else: Qeff = np.empty(1, dtype=float) self.gd.comm.broadcast(Qeff, rank) all_Qeff_a[a] = Qeff # Check absolute values consistency of inverse effective charges self.assertAlmostEqual(np.abs(1./self.Z_a-np.abs(all_Qeff_a)).max(), 0, 9) # Check sum of inverse effective charges against total self.assertAlmostEqual(all_Qeff_a.sum(), self.Qtotal, 9) # Make sure that we all agree on inverse effective charges fingerprint = np.array([md5_array(all_Qeff_a, numeric=True)]) all_fingerprints = np.empty(world.size, fingerprint.dtype) world.all_gather(fingerprint, all_fingerprints) if all_fingerprints.ptp(0).any(): raise RuntimeError('Distributed eff. charges are not identical!')
def test_contents_projection(self): # Distribute inverse effective charges to everybody in domain all_Qeff_a = np.empty(len(self.atoms), dtype=float) for a, rank in enumerate(self.rank_a): if rank == self.gd.comm.rank: Qeff = np.array([self.Qeff_a[a]]) else: Qeff = np.empty(1, dtype=float) self.gd.comm.broadcast(Qeff, rank) all_Qeff_a[a] = Qeff # Check absolute values consistency of inverse effective charges self.assertAlmostEqual( np.abs(1. / self.Z_a - np.abs(all_Qeff_a)).max(), 0, 9) # Check sum of inverse effective charges against total self.assertAlmostEqual(all_Qeff_a.sum(), self.Qtotal, 9) # Make sure that we all agree on inverse effective charges fingerprint = np.array([md5_array(all_Qeff_a, numeric=True)]) all_fingerprints = np.empty(world.size, fingerprint.dtype) world.all_gather(fingerprint, all_fingerprints) if all_fingerprints.ptp(0).any(): raise RuntimeError('Distributed eff. charges are not identical!')
representation_nn[i1, i2, nop] /= norm1 * norm2 # Calculate traces of irreducible representations # If bands i1 and i2 are accidentally degenerate (i.e. not due to symmetry) # they belong to different irreducible representations and the # corresponding representation matrix elements are zero for all # symmetry operations. for i1 in range(ndeg): for i2 in range(ndeg): if np.any(abs(representation_nn[i1, i2, :]) > 0.01): characters[n + i1, :] += representation_nn[i2, i2, :] symdone[n + i1] = True # Use four decimals for characters characters = np.round(characters, 4) # Use characters as fingerprints fingerprints = np.array([md5_array(row) for row in characters]) fmt = "%6.4f " * nops for i in range(nbands): print(fmt % tuple([c for c in characters[i, :nops]])) # Correct?!? character table characters_reference = np.array( ((1.0, 1.0, 1.0, 1.0, 1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (1.0, 1.0, 1.0, 1.0, 1.0))) assert np.all(np.abs(characters_reference - characters) < 1.0e-4) os.remove('Si_gamma.gpw')
# Calculate traces of irreducible representations # If bands i1 and i2 are accidentally degenerate (i.e. not due to symmetry) # they belong to different irreducible representations and the # corresponding representation matrix elements are zero for all # symmetry operations. for i1 in range(ndeg): for i2 in range(ndeg): if np.any(abs(representation_nn[i1, i2, :]) > 0.01): characters[n + i1, :] += representation_nn[i2, i2, :] symdone[n + i1] = True # Use four decimals for characters characters = np.round(characters, 4) # Use characters as fingerprints fingerprints = np.array([md5_array(row) for row in characters]) fmt = "%6.4f " * nops for i in range(nbands): print(fmt % tuple([c for c in characters[i, :nops]])) # Correct?!? character table characters_reference = np.array(((1.0, 1.0, 1.0, 1.0, 1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (3.0, 1.0, 0.0, -1.0, -1.0), (1.0, 1.0, 1.0, 1.0, 1.0))) assert np.all(np.abs(characters_reference-characters) < 1.0e-4)