~jrjohansson/qutip/master

« back to all changes in this revision

Viewing changes to qutip/sp_expm.py

  • Committer: Paul Nation
  • Date: 2011-04-21 04:46:56 UTC
  • Revision ID: git-v1:dd4c966b490aa468dfbd28cef66694df4bf235c8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#This file is part of QuTIP.
 
2
#
 
3
#    QuTIP is free software: you can redistribute it and/or modify
 
4
#    it under the terms of the GNU General Public License as published by
 
5
#    the Free Software Foundation, either version 3 of the License, or
 
6
#   (at your option) any later version.
 
7
#
 
8
#    QuTIP is distributed in the hope that it will be useful,
 
9
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
#    GNU General Public License for more details.
 
12
#
 
13
#    You should have received a copy of the GNU General Public License
 
14
#    along with QuTIP.  If not, see <http://www.gnu.org/licenses/>.
 
15
#
 
16
# Copyright (C) 2011, Paul D. Nation & Robert J. Johansson
 
17
#
 
18
###########################################################################
 
19
from scipy import *
 
20
from scipy.linalg import norm,solve
 
21
import scipy.sparse as sp
 
22
from qobj import *
 
23
 
 
24
def sp_expm(qo):
 
25
    #############################
 
26
    def pade(m):
 
27
        n=shape(A)[0]
 
28
        c=padecoeff(m)
 
29
        if m!=13:
 
30
            apows= [[] for jj in xrange(int(ceil((m+1)/2)))]
 
31
            apows[0]=sp.eye(n,n).tocsr()
 
32
            apows[1]=A*A
 
33
            for jj in xrange(2,int(ceil((m+1)/2))):
 
34
                apows[jj]=apows[jj-1]*apows[1]
 
35
            U=sp.lil_matrix(zeros((n,n))).tocsr(); V=sp.lil_matrix(zeros((n,n))).tocsr()
 
36
            for jj in xrange(m,0,-2):
 
37
                U=U+c[jj]*apows[jj/2]
 
38
            U=A*U
 
39
            for jj in xrange(m-1,-1,-2):
 
40
                V=V+c[jj]*apows[(jj+1)/2]
 
41
            F=solve((-U+V).todense(),(U+V).todense())
 
42
            return sp.lil_matrix(F).tocsr()
 
43
        elif m==13:
 
44
            A2=A*A
 
45
            A4=A2*A2
 
46
            A6=A2*A4
 
47
            U = A*(A6*(c[13]*A6+c[11]*A4+c[9]*A2)+c[7]*A6+c[5]*A4+c[3]*A2+c[1]*sp.eye(n,n).tocsr())
 
48
            V = A6*(c[12]*A6 + c[10]*A4 + c[8]*A2)+ c[6]*A6 + c[4]*A4 + c[2]*A2 + c[0]*sp.eye(n,n).tocsr()
 
49
            F=solve((-U+V).todense(),(U+V).todense()) 
 
50
            return sp.lil_matrix(F).tocsr()
 
51
    #################################
 
52
    A=qo.data #extract Qobj data (sparse matrix)
 
53
    m_vals=array([3,5,7,9,13])
 
54
    theta=array([0.01495585217958292,0.2539398330063230,0.9504178996162932,2.097847961257068,5.371920351148152],dtype=float)
 
55
    normA=norm(A.todense(),1)
 
56
    if normA<=theta[-1]:
 
57
        for ii in xrange(len(m_vals)):
 
58
            if normA<=theta[ii]:
 
59
                F=pade(m_vals[ii])
 
60
                break
 
61
    else:
 
62
        t,s=frexp(normA/theta[-1])
 
63
        s=s-(t==0.5)
 
64
        A=A/2.0**s
 
65
        F=pade(m_vals[-1])
 
66
        for i in xrange(s):
 
67
            F=F*F
 
68
    return qobj(F,dims=qo.dims,shape=qo.shape)
 
69
        
 
70
 
 
71
def padecoeff(m):
 
72
    if m==3:
 
73
        return array([120, 60, 12, 1])
 
74
    elif m==5:
 
75
        return array([30240, 15120, 3360, 420, 30, 1])
 
76
    elif m==7:
 
77
        return array([17297280, 8648640, 1995840, 277200, 25200, 1512, 56, 1])
 
78
    elif m==9:
 
79
        return array([17643225600, 8821612800, 2075673600, 302702400, 30270240,2162160, 110880, 3960, 90, 1])
 
80
    elif m==13:
 
81
        return array([64764752532480000, 32382376266240000, 7771770303897600,1187353796428800, 129060195264000, 10559470521600,670442572800, 33522128640, 1323241920,40840800, 960960, 16380, 182, 1])
 
82
 
 
83
 
 
84
 
 
85
 
 
86
 
 
87
 
 
88