def test_a(self): """Test whether SimPhony gives the same result *at* grid points. This test should always pass, since the BZGridQcomplex object is filled by calculating eigen-energies and eigen-vectors using SimPhony. Unfortunately, due to rounding errors, this test can fail to run if an out-of-bounds interpolation point is required by brille. The moveinto keyword is what makes it possible to verify the "interpolation" result against the SimPhony result. This same keyword also opens up the possibility of rounding-errors leading to a runtime error of brille. With the moveinto keyword omitted (or set to True), out-of-zone grid points *will* likely have different polarization vectors compared to the SimPhony result as one interpolates at q=Q-τ and the other calculates at Q. It's unclear if this difference is important for intensity calculations. """ i_data = load_interpolation_data('nb') symsim = BrEu(i_data, halfN=(2, 2, 2)) q_rlu = symsim.grid.rlu int_freq, int_vecs = symsim.frqs_vecs(q_rlu, interpolate=True, moveinto=False) sim_freq, sim_vecs = symsim.frqs_vecs(q_rlu, interpolate=False) ad_freq = np.abs(int_freq - sim_freq).magnitude as_freq = np.abs(int_freq + sim_freq).magnitude # Check if |interpolated-simulated|/|interpolated+simulated|>1e-14 # AND if |interpolated-simulated|>1e-14 unequal_freq = (ad_freq > 1e-14 * as_freq) * (ad_freq > 1e-14) self.assertFalse(unequal_freq.any()) # The vectors only need to be equal up to an arbitrary phase # which is equivalent to saying that the inner product between # equal ion eigenvectors for each branch should have ||ϵ⋅ϵ||²≡1 n_pt, n_br, n_io, n_d = int_vecs.shape int_vecs = int_vecs.reshape(n_pt * n_br * n_io, n_d) sim_vecs = sim_vecs.reshape(n_pt * n_br * n_io, n_d) product = [hermitian_product(x, y) for x, y in zip(int_vecs, sim_vecs)] self.assertTrue(np.isclose(np.abs(product), 1).all())
def test_NaCl(self): # fetch and load the NaCl.castep_bin file from the brille repository idata = get_InterpolationData_object('NaCl') # Do not sort the modes on neighbouring trellis vertices to make comparison with Euphonic easier breu = BrEu(idata, sort=False, trellis=True, max_volume=0.1, parallel=False) # pick a trellis Q vertex inside the irreducible polyhedron, away from the boundaries: q_ir = breu.grid.rlu[6:7] # shape = (1,3) # pull together the pointgroup operations ptgr = b.PointSymmetry(breu.grid.BrillouinZone.lattice.hall) # and apply each to q_ir to find q_nu = R^T_nu q_ir q_nu = np.einsum('xji,aj->xi', ptgr.W, q_ir) # use brille to find eigenenergies and eigenvectors at each q_nu # this *should* be only an application of the rotation, so # all omega_nu are expected to be identical # and all epsilon_nu will be permuted as Gamma(q|nu) dictates br_omega_nu, br_epsilon_nu = breu.frqs_vecs(q_nu, interpolate=True) # use Euphonic to diagonalise the dynamical matrix at each q_nu eu_omega_nu, eu_epsilon_nu = breu.frqs_vecs(q_nu, interpolate=False) # verify that all brille eigenvalues are identical for each q_nu self.assertTrue(np.allclose(np.diff(br_omega_nu.magnitude, axis=0), 0.)) # and that these results match the Euphonic results self.assertTrue(np.allclose(br_omega_nu.magnitude, eu_omega_nu.magnitude)) # Now that we're sure the permutation is the same, we can verify the eigenvectors # brille stores and returns eigenvectors expressed in units of the conventional direct lattice # while euphonic calculates, returns, and stores them in a cartesian coordinate system defined # relative to the lattice by its lat_vec matrix. # A brille.spglib method handles conversion between these descriptions: br_epsilon_nu_xyz = breu.brspgl.conventional_to_orthogonal_eigenvectors(br_epsilon_nu) # The eigenvectors returned by brille and those from Euphonic should be the same up to an overall complex phase factor # the eigenvectors are normalised, so the phase is calculated directly antiphase_per_q_per_mode = np.exp(-1J*np.angle(np.einsum('qmij,qmij->qm', np.conj(eu_epsilon_nu), br_epsilon_nu_xyz))) # and removed from the cartesian coordinate eigenvectors br_epsilon_nu_xyz_phased = np.array([[x0*y0 for x0,y0 in zip(x,y)] for x,y in zip(antiphase_per_q_per_mode, br_epsilon_nu_xyz)]) # now all eigenvectors returned from brille should be the same as # calculated by Euphonic directly self.assertTrue(np.allclose(br_epsilon_nu_xyz_phased, eu_epsilon_nu))
# SQWS = (SQW_0, SQW_N, SQW_S) # times =(intt, part, simt) # uncer =(intu, paru, simu) # FIG_0, AX_0 = pp.subplots(1, len(SQWS)) # for i, (dat, t,u) in enumerate(zip(SQWS,times,uncer)): # pp.sca(AX_0[i]) # pp.pcolormesh(px, py, np.real(dat.reshape(inshape)), shading='flat') # pp.title('{:5.3f}±{:5.3f} s'.format(t,u)) # pp.axis('square') # # pp.show() # q = np.random.rand(10000, 3) * 10 senb = BrEu(nb, mesh=True, parallel=True, max_size=0.0001, lattice_ratio=2.) tictoc.tic() while not (tictoc.elapsed() > 60 or tictoc.relative_uncertainty() < 0.05): senb(q, interpolate=False) tictoc.toc() eu_time_point = tictoc.average() / q.shape[0] * 10**6 eu_delt_point = tictoc.uncertainty() / q.shape[0] * 10**6 nthreads = np.arange(1, os.cpu_count() // 2 + 1, dtype='int') it = np.nditer([nthreads, None, None], op_dtypes=('int', 'double', 'double')) for n, t, u in it: tictoc.tic() while not (tictoc.elapsed() > 60 or tictoc.relative_uncertainty() < 0.05): senb(q, threads=n) tictoc.toc()
def test_b(self): """Do something.""" i_data = load_interpolation_data('nb') symsim = BrEu(i_data, halfN=(10, 10, 10)) print(symsim.grid.centre_sort_perm())
axis=1) return Z def pcolormesh(X, Y, Z, *args, **kwargs): return pp.pcolormesh(cen2corner(X), cen2corner(Y), Z, *args, **kwargs) tictoc.tic() nb = load_interpolation_data('La2Zr2O7') details['euphonic_load_seconds'] = tictoc.toc() q = np.random.rand(100000, 3) * 10 - 5 tictoc.tic() senb = BrEu(nb, trellis=True, parallel=True, max_volume=0.0001) details['breu_setup_seconds'] = tictoc.toc() tictoc.tic() while not (tictoc.elapsed() > 30 or tictoc.relative_uncertainty() < 0.05): senb.w_q(q, interpolate=False) tictoc.toc() eu_time_point = tictoc.average() / q.shape[0] * 10**6 eu_delt_point = tictoc.uncertainty() / q.shape[0] * 10**6 details['euphonic_us_per_point'] = eu_time_point details['euphonic_us_per_point_uncertainty'] = eu_delt_point it = np.nditer([details['n_threads'], None, None], op_dtypes=('int', 'double', 'double')) for n, t, u in it:
dX = np.diff(X, axis=0) / 2 X = np.concatenate((X[:-1] - dX, X[np.newaxis, -1] - dX[np.newaxis, -1], X[np.newaxis, -1] + dX[np.newaxis, -1]), axis=0) dY = np.diff(X, axis=1) / 2 X = np.concatenate( (X[:, :-1] - dY, X[:, np.newaxis, -1] - dY[:, np.newaxis, -1], X[:, np.newaxis, -1] + dY[:, np.newaxis, -1]), axis=1) return X # Construct a brille BZTrellisQdc object from a Euphonic object. # parallel=False ensures the Euphonic C module is *not* used. nacl = BrEu(get_InterpolationData_object('NaCl'), trellis=True, max_volume=1e-5, parallel=False) # but we want to use the brille C++ module nacl.parallel = True # Define a path through reciprocal space from (000) to (123) xi = np.linspace(0, 1, 100) qhkl = np.vstack((xi, 2 * xi, 3 * xi)).T # Interpolate the mode energies at qhkl w_q = nacl.w_q(qhkl).magnitude bz = nacl.grid.BrillouinZone # plot the first Brillouin zones for (000), (111), (022), and (113) and path fig = pp.figure(figsize=pp.figaspect(2)) ax = fig.add_axes([0, 0, 1, 1], projection='3d') ax.view_init(5, 300)
return pp.pcolormesh(cen2corner(X), cen2corner(Y), Z, *args, **kwargs) # Next investigate now choice of tetrahedra levels size # effect point-interpolation time q = np.random.rand(10000,3)*10 nb = load_interpolation_data('nb') max_sizes = 1/(10**np.linspace(6,12,5))**(1/3) num_levels = np.arange(1,7).reshape(6,1) print('Interpolation of {} points:'.format(q.shape[0])) it = np.nditer([max_sizes,num_levels, None, None, None],op_dtypes=('double','int','double','double','double')) for m, n, s, i, ie in it: tictoc.tic() se = BrEu(nb, mesh=True, max_size=m, num_levels=n) s[...] = tictoc.toc() tictoc.tic() while not (tictoc.elapsed() > 5 or tictoc.relative_uncertainty() < 0.01): # while not (tictoc.elapsed() > 1 or tictoc.relative_uncertainty() < 0.5): se.w_q(q) tictoc.toc() i[...] = tictoc.average() ie[...] = tictoc.uncertainty() print('levels {:d}: <time>={:5.3f}({:5.3f}) sum(time)={:5.2f} sec'.format(n,i,ie,tictoc.elapsed())) setup_time = it.operands[2] interpolation_time = it.operands[3] interpolation_uncertainty = it.operands[4] # pp.figure() # pp.errorbar(num_levels, interpolation_time, yerr=interpolation_uncertainty, marker='o', linestyle='-')
Z = np.concatenate( (Z[:, :-1] - dY, Z[:, np.newaxis, -1] - dY[:, np.newaxis, -1], Z[:, np.newaxis, -1] + dY[:, np.newaxis, -1]), axis=1) return Z def pcolormesh(X, Y, Z, *args, **kwargs): return pp.pcolormesh(cen2corner(X), cen2corner(Y), Z, *args, **kwargs) nb = load_interpolation_data('nb') q = np.random.rand(10000, 3) * 10 - 5 senb = BrEu(nb, nest=True, parallel=True, max_volume=0.0001, max_branchings=5) tictoc.tic() while not (tictoc.elapsed() > 60 or tictoc.relative_uncertainty() < 0.05): senb.w_q(q, interpolate=False) tictoc.toc() eu_time_point = tictoc.average() / q.shape[0] * 10**6 eu_delt_point = tictoc.uncertainty() / q.shape[0] * 10**6 nthreads = np.arange(1, os.cpu_count() // 2 + 1, dtype='int') it = np.nditer([nthreads, None, None], op_dtypes=('int', 'double', 'double')) for n, t, u in it: tictoc.tic() while not (tictoc.elapsed() > 20 or tictoc.relative_uncertainty() < 0.05): senb.w_q(q, threads=n) tictoc.toc()
return pp.pcolormesh(cen2corner(X), cen2corner(Y), Z, *args, **kwargs) # Next investigate now choice of tetrahedra levels size # effect point-interpolation time q = np.random.rand(10000, 3) * 10 nb = load_interpolation_data('nb') max_sizes = 1 / (10**np.linspace(6, 12, 5))**(1 / 3) print('Interpolation of {} points:'.format(q.shape[0])) it = np.nditer([max_sizes, None, None, None], op_dtypes=('double', 'double', 'double', 'double')) for m, s, i, ie in it: tictoc.tic() se = BrEu(nb, trellis=True, max_volume=m) s[...] = tictoc.toc() tictoc.tic() while not (tictoc.elapsed() > 5 or tictoc.relative_uncertainty() < 0.01): # while not (tictoc.elapsed() > 1 or tictoc.relative_uncertainty() < 0.5): se.w_q(q) tictoc.toc() i[...] = tictoc.average() ie[...] = tictoc.uncertainty() print('max volume {:f}: <time>={:5.3f}({:5.3f}) sum(time)={:5.2f} sec'. format(m, i, ie, tictoc.elapsed())) setup_time = it.operands[1] interpolation_time = it.operands[2] interpolation_uncertainty = it.operands[3] # pp.figure()
# inshape = qx.shape # px = cen2corner(qx) # py = cen2corner(qy) qx = qx.reshape(qx.size, 1) qy = qy.reshape(qy.size, 1) qxyz = np.concatenate((qx, qy, 0 * qx), axis=1) nb = load_interpolation_data('nb') interpolation_trellis_ratios = 2**np.arange(-3, 1.51, 0.1) print('Interpolation of {} points:'.format(qx.size)) it = np.nditer([interpolation_trellis_ratios, None, None]) for tr, i, ie in it: se = BrEu(nb, mesh=True, max_size=0.01, lattice_ratio=tr) tictoc.tic() while not (tictoc.elapsed() > 5 or tictoc.relative_uncertainty() < 0.01): # while not (tictoc.elapsed() > 1 or tictoc.relative_uncertainty() < 0.5): se(qxyz) tictoc.toc() i[...] = tictoc.average() ie[...] = tictoc.uncertainty() print( 'ratio {:6.4f}: <time>={:5.3f}({:5.3f}) sum(time)={:5.2f} sec'.format( tr, i, ie, tictoc.elapsed())) interpolation_time = it.operands[1] interpolation_uncertainty = it.operands[2] pp.figure() pp.errorbar(interpolation_trellis_ratios,
Z = np.concatenate( (Z[:, :-1] - dY, Z[:, np.newaxis, -1] - dY[:, np.newaxis, -1], Z[:, np.newaxis, -1] + dY[:, np.newaxis, -1]), axis=1) return Z def pcolormesh(X, Y, Z, *args, **kwargs): return pp.pcolormesh(cen2corner(X), cen2corner(Y), Z, *args, **kwargs) nb = load_interpolation_data('nb') q = np.random.rand(10000, 3) * 10 senb = BrEu(nb, mesh=True, parallel=True, max_size=0.0001, num_levels=5) tictoc.tic() while not (tictoc.elapsed() > 60 or tictoc.relative_uncertainty() < 0.05): senb.w_q(q, interpolate=False) tictoc.toc() eu_time_point = tictoc.average() / q.shape[0] * 10**6 eu_delt_point = tictoc.uncertainty() / q.shape[0] * 10**6 nthreads = np.arange(1, os.cpu_count() // 2 + 1, dtype='int') it = np.nditer([nthreads, None, None], op_dtypes=('int', 'double', 'double')) for n, t, u in it: tictoc.tic() while not (tictoc.elapsed() > 20 or tictoc.relative_uncertainty() < 0.05): senb.w_q(q, threads=n) tictoc.toc()