def func(T): if T > 0.6: return -1 #print " @ T =", T, ":" geometry.t_t = T geometry.w_delta = last_gtr_delta[0] it = u.self_consistent_matsubara_iteration(geometry, output_func=None, **kw) for k, d, v in it: rel_err = d.residual_norm() / abs(d.get()).max() #sys.stdout.write("%g(%.1g) " % (rel_err, abs(d.get()).max())) #sys.stdout.flush() if rel_err < 1e-3 and v < 1e-4: break if abs(d.get()).max() < tol: geometry.w_delta = 0.0 geometry.w_phase = 0.0 break dmax = abs(geometry.w_delta).max() if dmax == 0: #sys.stdout.write("=> N\n") return -1 last_gtr_delta[0] = geometry.w_delta.copy() #sys.stdout.write("=> S (%g)\n" % dmax) return dmax
def test_bilayer_matsubara(): global g, Delta_0, omega_D, lambda_0, d_A, d_B g.w_delta[...] = Delta_0 Delta_1 = bilayer_delta(lambda_0, omega_D, d_A, d_B) # Note: again need the whole energy range up to omega_D, # because the Thouless energy is much larger than the enery gap # and omega_D! it = u.self_consistent_matsubara_iteration(g, max_ne=200) for k, d, violation in it: print "Iter %d: relative residual %.2g" % ( k, d.relative_residual_norm()) if (d.relative_residual_norm() < 1e-4 and violation < 1e-5): break else: raise RuntimeError("Did not converge") assert allclose(g.w_delta[0,:], Delta_1, rtol=1e-2), g.w_delta[0,0]
def func(T): print " @ T =", T, ":" geometry.t_t = T geometry.w_delta = last_gtr_delta[0] if matsubara: it = u.self_consistent_matsubara_iteration(geometry, output_func=None, **kw) else: solver = u.CurrentSolver(geometry) it = u.self_consistent_realtime_iteration(solver, output_func=None, **kw) zero_count = 0 for k, d, v in it: rel_err = d.residual_norm() / abs(d.get()).max() sys.stdout.write("%g(%.2g) " % (rel_err, abs(d.get()).max())) sys.stdout.flush() if abs(d.get()).max() < 1e-3: zero_count += 1 else: zero_count = 0 if zero_count > 4: geometry.w_delta = 0.0 geometry.w_phase = 0.0 break if rel_err < 1e-4 and v < 1e-4: break dmax = abs(geometry.w_delta).max() if dmax == 0: sys.stdout.write("=> N\n") return -1 last_gtr_delta[0] = geometry.w_delta.copy() sys.stdout.write("=> S (%g)\n" % dmax) return dmax
def main(): g = get_geometry(pi/2) file_name = 'nonlocal_thermovoltage_spectral.h5' # It is possible to do a self-consistent iteration, but this is quite # slow. # # Change False to True below, if you want to try that: do_selfconsistent_iteration = False # Load data from a file, if it exists solver = u.CurrentSolver.resume(file_name, g, ne=200, chunksize=50) solver.set_solvers(kin_solver=u.KIN_SOLVER_BLOCK, sp_solver=u.SP_SOLVER_TWPBVP) # Solve and save spectral quantities to a file. # This takes some time, so we'll want to avoid redoing it unnecessarily. # # calculage_G=True instructs the solver also to calculate a spectral # conductance matrix for the circuit, which can be used to conveniently # evaluate currents given distribution functions in the terminals. # if not do_selfconsistent_iteration: solver.solve_spectral_and_save_if_needed(file_name, calculate_G=True) # Solve thermovoltage vs. temperature dT = 0.05 # ... and write results to a text file output = open('nonlocal_thermovoltage.dat', 'w') print >> output, "%% %14s %14s" % ("T (E_T)", "dV/dT (ueV/K)") if do_selfconsistent_iteration: Ts = logspace(log10(dT + 1e-4), log10(10), 15)[1:] else: Ts = logspace(log10(dT + 1e-4), log10(10), 100) for T in Ts: # (Optional) self-consistent iteration if do_selfconsistent_iteration: g.t_mu = 0 g.t_t = T it = u.self_consistent_matsubara_iteration(g, max_ne=50) #it = u.self_consistent_realtime_iteration(solver) for k, d, I_error in it: print >> sys.stderr, "%% Self-consistent iteration %d (residual %g)" % (k, d.residual_norm()) if (d.residual_norm() < 1e-3 * 100 and I_error < 1e-5): break else: raise RuntimeError("Self-cons. iteration didn't converge!") solver.solve_spectral() solver.calculate_G() solver.save("nonlocal_thermovoltage_T_%.2f.h5" % T) # Compute the thermovoltage: g.t_mu = 0 g.t_t = T g.t_t[11] += dT # Make the terminals 0, 3, 4, 5, 11 to float # Currents entering them flow in wires 0, 3, 4, 5, 7 def zero_currents(): Ic, Ie = solver.get_currents_from_G(w_jT=[0,3,4,5,7], w_jL=[]) #Ic, Ie = solver.get_currents(w_jT=[0,3,4,5,7], w_jL=[], ix=0) return [Ic[0], Ic[3], Ic[4], Ic[5], Ic[7]] def set_potentials(z): g.t_mu[0], g.t_mu[3], g.t_mu[4], g.t_mu[5], g.t_mu[11] = z u.optimize_parameters_for([0,0,0,0,0], zero_currents, set_potentials) # Print the thermovoltage at terminal 4 in ueV/K print >> output, " %14g %14g" % (T, g.t_mu[4] / dT * 86.17343) # Solve the kinetic equations for some temperature and a larger # temperature difference, and dump the result for inspection. g.t_t = 1e-4 g.t_t[11] = 8 solver.solve_kinetic() solver.save('dump.h5') output.close()