Matriks eksponensial dari matriks asimetris nyata dengan Fortran 95 dan LAPACK

10

Baru-baru ini saya mengajukan pertanyaan di sepanjang baris yang sama untuk matriks miring-Hermitian. Terinspirasi oleh keberhasilan pertanyaan itu, dan setelah membenturkan kepalaku ke dinding selama beberapa jam, aku melihat matriks eksponensial dari matriks asimetris yang nyata. Rute untuk menemukan nilai eigen dan vektor eigen tampaknya agak berbelit-belit, dan saya khawatir saya tersesat.

Latar Belakang: Beberapa waktu yang lalu saya menanyakan pertanyaan ini pada fisika teoretis SE. Hasilnya memungkinkan saya untuk frase persamaan induk sebagai matriks asimetris nyata. Dalam kasus waktu-independen, persamaan utama diselesaikan dengan eksponensial matriks ini. Dalam kasus yang bergantung pada waktu, itu akan membutuhkan integrasi. Saya hanya peduli dengan kebebasan waktu pada saat ini.

Setelah melihat berbagai subrutin saya pikir saya harus menelepon ( ? Gehrd , ? Orghr , ? Hseqr ...) tidak jelas apakah akan lebih sederhana untuk melemparkan matriks dari real*8ke complex*16dan dilanjutkan dengan versi ganda kompleks rutinitas ini, atau tetap dengan real*8dan menerima menggandakan jumlah array saya dan membuat matriks yang kompleks nanti.

Jadi, rutinitas mana yang harus saya panggil (dan dalam urutan apa), dan haruskah saya menggunakan versi ganda nyata atau versi ganda kompleks? Di bawah ini adalah upaya melakukan ini dengan versi ganda nyata. Saya menjadi macet menemukan nilai eigen dan vektor eigen dari L*t.

function time_indep_master(s,L,t)
  ! s is the length of a side of L, which is square.
  ! L is a real*8, asymmetric square matrix.
  ! t is a real*8 value corresponding to time.
  ! This function (will) compute expm(L*t).

  integer, intent(in)    :: s
  real*8,  intent(in)    :: L(s,s), t
  real*8                 :: tau(s-1), work(s), wr(s), wi(s), vl
  real*8, dimension(s,s) :: time_indep_master, A, H, vr
  integer                :: info, m, ifaill(2*s), ifailr(2*s)
  logical                :: sel(s)

  A = L*t
  sel = .true.

  call dgehrd(s,1,s,A,s,tau,work,s,info)
  H = A
  call dorghr(s,1,s,A,s,tau,work,s,info)
  call dhseqr('e','v',s,1,s,H,s,wr,wi,A,s,work,s,info)
  call dhsein('r','q','n',sel,H,s,wr,wi,vl,1,vr,s,2*s,m,work,ifaill,ifailr,info)

  ! Confused now...

end function
qubyte
sumber

Jawaban:

8

Pertama-tama saya akan berpikir sangat keras tentang apakah matriks benar-benar sewenang-wenang: Apakah ada transformasi yang akan menjadikannya Hermitian? Apakah fisika menjamin bahwa matriks harus dapat didiagonalisasi (dengan matriks vektor eigen yang dikondisikan secara wajar)?

Jika ternyata tidak ada simetri untuk dieksploitasi, maka Anda harus mulai dengan membaca Nineteen Dubious Cara untuk Menghitung Eksponensial Matriks , yang merupakan referensi standar (dan ditulis oleh penulis MATLAB dan rekan penulis G & vL) .

Jack Poulson
sumber
1
2×24×4
1
Saya suka jawaban ini; kasing yang tidak simetris memiliki cukup jebakan sehingga layak dipertimbangkan jika mungkin ada rumusan masalah Anda yang mengarah ke matriks simetris, bukan yang tidak simetris.
JM
@ MarkS.Everitt: Sepertinya Anda hampir sampai di sana ... seberapa besar matriksnya? ~ 36 x 36 lagi?
Jack Poulson
16×1636×36
2
@ MarkS.Everitt: Jadi masalah Anda sekarang efektif hanya bagaimana cara eksponensial matriks 4x4. Ini cukup kecil untuk analisis asimptotik menjadi tidak relevan, sehingga jawabannya akan sepenuhnya bergantung pada nilai-nilai. Saya tidak bisa mengatakannya lagi kecuali Anda menerjemahkan postingan fisika Anda yang terhubung ke aljabar linear (apa itu superoperator?!?).
Jack Poulson
7

Untuk membangun apa yang dikatakan Jack, pendekatan standar yang tampaknya digunakan dalam perangkat lunak (seperti EXPOKIT, yang disebutkan dalam pertanyaan Anda sebelumnya) adalah penskalaan dan kuadrat diikuti oleh pendekatan Padé (Metode 2 dan 3) atau metode ruang bagian Krylov (Metode 20). Secara khusus, jika Anda melihat integrator eksponensial, Anda akan ingin mempertimbangkan metode ruang bagian Krylov, dan melihat makalah tentang integrator eksponensial (beberapa referensi disebutkan bersama dengan Metode 20 dalam makalah Moler & van Loan).

Jika Anda benar-benar ingin menggunakan vektor eigen, pertimbangkan untuk menggunakan sistem segitiga vektor eigen (Metode 15); karena matriks Anda mungkin tidak dapat dinonagonisasi, pendekatan ini mungkin bukan yang terbaik, tetapi lebih baik daripada mencoba untuk menghitung vektor eigen dan nilai eigen secara langsung (yaitu, Metode 14).

Pengurangan ke bentuk Hessenberg bukan ide yang baik (Metode 13).

Tidak jelas bagi saya apakah Anda akan lebih baik dilayani dengan aritmatika nyata atau kompleks, karena aritmatika kompleks Fortran cepat, tetapi mungkin meluap / underflow (lihat "Seberapa jauh sebenarnya kompiler Fortran?" ).

Anda dapat dengan aman mengabaikan Metode 5-7 (metode berbasis solver ODE tidak efisien), Metode 8-13 (mahal), Metode 14 (menghitung vektor eigen dari matriks besar sulit tanpa struktur khusus dan rentan terhadap kesalahan numerik dalam kasus yang dikondisikan dengan buruk) , dan Metode 16 (menghitung dekomposisi Jordan dari sebuah matriks secara numerik tidak stabil). Metode 17-19 lebih sulit untuk diterapkan; khususnya, Metode 17 dan 18 akan membutuhkan lebih banyak bacaan. Metode 1 adalah opsi mundur untuk penskalaan dan kuadrat jika pendekatan Padé tidak berfungsi dengan baik.

Bj

Bj=γjI+Ej,

γjjEj

Geoff Oxberry
sumber
1
O(n2)O(n3)
Tidak diragukan mereka tahu apa yang mereka lakukan; Saya tidak khawatir tentang implementasi LAPACK. Saya lebih terkejut tentang perilaku kompiler Fortran.
Geoff Oxberry
2
Ya, kompiler mungkin lebih merupakan masalah daripada LAPACK yang ditulis dengan baik. Dapat membingungkan untuk menemukan bahwa program Anda gagal hanya karena implementasi untuk nilai absolut dan divisi yang digunakan oleh kompiler rusak ...
JM
-1

Saya memiliki subrutin Fortran sederhana yang menghitung eksponen dari matriks arbitrer. Saya memeriksanya melawan perintah Matlab dan itu baik-baik saja. Ini didasarkan pada penskalaan dan kuadrat. Saya menulisnya beberapa tahun yang lalu.

Saya ingin sirip subroutine lain, seperti yang saya unduh dari gams.nist.gov. Tapi belum berhasil.

freejack
sumber