def ssft(self, potential, dt=-.1j*50e-6, max_its = 10000, start_psi = None, precision= 1e-8): self.dt = dt ## kinetic energy part self.T = hbar**2*self.k**2/(2*self.p.m) self.exp_T = scipy.exp(-1j*self.dt/(2.*hbar)*self.T) self.exp_2T = scipy.exp(-1j*self.dt/(hbar)*self.T) if start_psi == None: ## Initialize psi to TF-solution psi = self.rand_psi() else: psi = self.Normalize(start_psi) psi_old = scipy.array(psi) exp_prefactor = -1j*self.dt/hbar psik = scipy.fftpack.fft(psi) psik *= self.exp_T psi = scipy.fftpack.ifft(psik) for i in scipy.arange(max_its): # print i if scipy.iscomplex(self.dt): psi = self.Normalize(psi) psi *= scipy.exp(exp_prefactor*(potential+self.interaction(psi))) psik = scipy.fftpack.fft(psi) psik *= self.exp_2T psi = scipy.fftpack.ifft(psik) if precision != None: if ((scipy.absolute(psi-psi_old)/scipy.absolute(psi)).sum() < precision)*(i>50): break else: psi_old = psi if scipy.iscomplex(self.dt): psi = self.Normalize(psi) psi *= scipy.exp(-1j*self.dt/hbar*(potential+self.interaction(psi))) psik = scipy.fftpack.fft(psi) psik *= self.exp_T psi = scipy.fftpack.ifft(psik) if (i == max_its-1)*(precision != None): logging.warning('warning: algorithm did not converge!') return self.Normalize(psi)
def __call__(self, field, skip=1): ''' Plot field. ''' super(Plotter2d, self).__call__(field) dims = [0] * 4 dimnames = ('time', 'lev', 'lat', 'lon') xind = dimnames.index(self.axes[0]) dims[xind] = slice(None) yind = dimnames.index(self.axes[1]) dims[yind] = slice(None) # Find plot arguments dd = dict(lon=field.grid['lon'][0, :], lat=field.grid['lat'][:, 0], lev=field.grid['lev'], time=field.time) args = [] args.append(dd[self.axes[0]][::skip]) args.append(dd[self.axes[1]][::skip]) if xind > yind: z = field.data[dims][::skip, ::skip] else: z = sp.ma.transpose(field.data[dims][::skip, ::skip]) args.append(sp.real(z)) if sp.any(sp.iscomplex(z.view(sp.ndarray))): args.append(sp.imag(z)) cs = self.method(*args, **self.copts) if isinstance(cs, mlib.contour.ContourSet): if cs.filled: if self.cbar_opts is not None: cb = pl.colorbar(**self.cbar_opts) units = getattr(field, 'units', "") cb.set_label(units) else: cs.clabel(**self.clab_opts) # If x-axis is time, apply default time formatting if self.axes[0] == 'time': fig = pl.gcf() fig.autofmt_xdate() return cs
def take_step_split(self, dtau, ham_is_Herm=True): """Take a time-step dtau using the split-step integrator. This is the one-site version of a DMRG-like time integrator described at: http://arxiv.org/abs/1408.5056 It has a fourth-order local error and is symmetric. It requires iteratively computing two matrix exponentials per site, and thus has less predictable CPU time requirements than the Euler or RK4 methods. NOTE: This requires the expokit extension, which is included in evoMPS but must be compiled during, e.g. using setup.py to build all extensions. Parameters ---------- dtau : complex The (imaginary or real) amount of imaginary time (tau) to step. ham_is_Herm : bool Whether the Hamiltonian is really Hermitian. If so, the lanczos method will be used for imaginary time evolution. """ #TODO: Compute eta. self.eta_sq.fill(0) self.eta = 0 assert self.canonical_form == 'right', 'take_step_split only implemented for right canonical form' assert self.ham_sites == 2, 'take_step_split only implemented for nearest neighbour Hamiltonians' dtau *= -1 from expokit_expmv import zexpmv, zexpmvh if sp.iscomplex(dtau) or not ham_is_Herm: expmv = zexpmv fac = 1.j dtau = sp.imag(dtau) else: expmv = zexpmvh fac = 1 norm_est = abs(self.H_expect.real) KL = [None] * (self.N + 1) KL[1] = sp.zeros((self.D[1], self.D[1]), dtype=self.typ) for n in xrange(1, self.N + 1): lop = Vari_Opt_Single_Site_Op(self, n, KL[n - 1], tau=fac) #print "Befor A", n, sp.inner(self.A[n].ravel().conj(), lop.matvec(self.A[n].ravel())).real An = expmv(lop, self.A[n].ravel(), dtau/2., norm_est=norm_est) self.A[n] = An.reshape((self.q[n], self.D[n - 1], self.D[n])) self.l[n] = tm.eps_l_noop(self.l[n - 1], self.A[n], self.A[n]) norm = m.adot(self.l[n], self.r[n]) self.A[n] /= sp.sqrt(norm) #print "After A", n, sp.inner(self.A[n].ravel().conj(), lop.matvec(self.A[n].ravel())).real, norm.real #shift centre matrix right (RCF is like having a centre "matrix" at "1") G = tm.restore_LCF_l_seq(self.A[n - 1:n + 1], self.l[n - 1:n + 1], sanity_checks=self.sanity_checks) if n > 1: self.AA[n - 1] = tm.calc_AA(self.A[n - 1], self.A[n]) self.C[n - 1] = tm.calc_C_mat_op_AA(self.ham[n - 1], self.AA[n - 1]) KL[n], ex = tm.calc_K_l(KL[n - 1], self.C[n - 1], self.l[n - 2], self.r[n], self.A[n], self.AA[n - 1]) if n < self.N: lop2 = Vari_Opt_SC_op(self, n, KL[n], tau=fac) #print "Befor G", n, sp.inner(G.ravel().conj(), lop2.matvec(G.ravel())).real G = expmv(lop2, G.ravel(), -dtau/2., norm_est=norm_est) G = G.reshape((self.D[n], self.D[n])) norm = sp.trace(self.l[n].dot(G).dot(self.r[n].dot(G.conj().T))) G /= sp.sqrt(norm) #print "After G", n, sp.inner(G.ravel().conj(), lop2.matvec(G.ravel())).real, norm.real for s in xrange(self.q[n + 1]): self.A[n + 1][s] = G.dot(self.A[n + 1][s]) self.AA[n] = tm.calc_AA(self.A[n], self.A[n + 1]) self.C[n] = tm.calc_C_mat_op_AA(self.ham[n], self.AA[n]) for n in xrange(self.N, 0, -1): lop = Vari_Opt_Single_Site_Op(self, n, KL[n - 1], tau=fac, sanity_checks=self.sanity_checks) #print "Before A", n, sp.inner(self.A[n].ravel().conj(), lop.matvec(self.A[n].ravel())).real An = expmv(lop, self.A[n].ravel(), dtau/2., norm_est=norm_est) self.A[n] = An.reshape((self.q[n], self.D[n - 1], self.D[n])) self.l[n] = tm.eps_l_noop(self.l[n - 1], self.A[n], self.A[n]) norm = m.adot(self.l[n], self.r[n]) self.A[n] /= sp.sqrt(norm) #print "After A", n, sp.inner(self.A[n].ravel().conj(), lop.matvec(self.A[n].ravel())).real, norm.real #shift centre matrix left (LCF is like having a centre "matrix" at "N") Gi = tm.restore_RCF_r_seq(self.A[n - 1:n + 1], self.r[n - 1:n + 1], sanity_checks=self.sanity_checks) if n < self.N: self.AA[n] = tm.calc_AA(self.A[n], self.A[n + 1]) self.C[n] = tm.calc_C_mat_op_AA(self.ham[n], self.AA[n]) self.calc_K(n_low=n, n_high=n) if n > 1: lop2 = Vari_Opt_SC_op(self, n - 1, KL[n - 1], tau=fac, sanity_checks=self.sanity_checks) Gi = expmv(lop2, Gi.ravel(), -dtau/2., norm_est=norm_est) Gi = Gi.reshape((self.D[n - 1], self.D[n - 1])) norm = sp.trace(self.l[n - 1].dot(Gi).dot(self.r[n - 1].dot(Gi.conj().T))) G /= sp.sqrt(norm) #print "After G", n, sp.inner(Gi.ravel().conj(), lop2.matvec(Gi.ravel())).real, norm.real for s in xrange(self.q[n - 1]): self.A[n - 1][s] = self.A[n - 1][s].dot(Gi) self.AA[n - 1] = tm.calc_AA(self.A[n - 1], self.A[n]) self.C[n - 1] = tm.calc_C_mat_op_AA(self.ham[n - 1], self.AA[n - 1])
A * A # matrix multiplication A ** 2 # Matrix 2 to the power of 2 (same as A*A) B = 5 * sp.diag([1.0, 3, 5]) sp.mat(B) # converts B to matrix type sp.mat(B).I # computes matrix inverse of sp.mat(B) # isnan, isfinite, isinf are newly added functions to NumPy C = B # copy matrix B into C C[0, 1] = sp.nan # insert NaN value into 1st row, 2nd column element sp.isnan(C) # yields all 'False' elements except one element as True # looking at complex numbers a4 = sp.array([1 + 1j, 2, 5j]) # create complex array sp.iscomplexobj(a4) # determine whether a4 is complex (TRUE) sp.isreal(a4) # determines element by element which are REAL or COMPLEX sp.iscomplex(a4) # determination of COMPLEX elements type(a4) # outputs type and functional dependencies # concatenating matrices and arrays: a5 = sp.array([1, 2, 3]) a6 = sp.array([4, 5, 6]) sp.vstack((a5, a6)) # vertical array concatenation sp.hstack((a5, a6)) # horizontal array concat dstack((a5, a6)) # vertical array concat, transposed # view all variables that have been created thus far: sp.who() # python command, similar to MATLAB # importing and using matplotlib (plotting library from MATLAB) t = sp.linspace(0, 100) # create time array 't' y = sp.sin(2 * sp.pi * t) # create sinusoidal series y