J'ai récemment posé une question dans le même sens pour les matrices asymétriques-hermitiennes. Inspiré par le succès de cette question, et après m'être cogné la tête contre un mur pendant quelques heures, je regarde la matrice exponentielle de vraies matrices asymétriques. L'itinéraire pour trouver les valeurs propres et les vecteurs propres semble plutôt compliqué, et je crains de m'être perdu.
Contexte: Il y a quelque temps, j'ai posé cette question sur la physique théorique SE. Le résultat me permet d'exprimer les équations principales comme de vraies matrices asymétriques. Dans le cas indépendant du temps, l'équation principale est résolue en exponentiant cette matrice. Dans le cas dépendant du temps, il faudra une intégration. Pour l'instant, je ne m'intéresse qu'à l'indépendance dans le temps.
En regardant les différents sous - programmes , je pense que je devrait appeler ( ? Gehrd , ? Orghr , ? Hseqr ...) on ne sait pas si ce serait plus simple de jeter la matrice à partir real*8
de complex*16
et procéder aux versions complexes doubles de ces routines, ou rester avec real*8
et prendre le coup de doubler le nombre de mes tableaux et d'en faire une matrice complexe plus tard.
Alors, quelles routines dois-je appeler (et dans quel ordre), et dois-je utiliser les vraies versions doubles ou les versions doubles complexes? Vous trouverez ci-dessous une tentative de le faire avec de vraies versions doubles. Je suis devenu coincé à trouver les valeurs propres et les vecteurs propres de 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
la source
Pour s'appuyer sur ce que Jack a dit, l'approche standard qui semble être utilisée dans les logiciels (comme EXPOKIT, mentionnée dans votre question précédente) est la mise à l'échelle et la mise au carré suivie par l'approximation de Padé (méthodes 2 et 3) ou les méthodes du sous-espace de Krylov (méthode 20). En particulier, si vous regardez des intégrateurs exponentiels, vous voudrez considérer les méthodes du sous-espace Krylov et regarder des articles sur les intégrateurs exponentiels (certaines références sont mentionnées avec la méthode 20 dans l'article de Moler & van Loan).
Si vous êtes déterminé à utiliser des vecteurs propres, envisagez d'utiliser des systèmes triangulaires de vecteurs propres (méthode 15); puisque votre matrice peut être non diagonalisable, cette approche n'est peut-être pas la meilleure, mais c'est mieux que d'essayer de calculer directement les vecteurs propres et les valeurs propres (c.-à-d. la méthode 14).
La réduction à la forme de Hessenberg n'est pas une bonne idée (méthode 13).
Il ne me semble pas si vous seriez mieux servi avec une arithmétique réelle ou complexe, car l'arithmétique complexe de Fortran est rapide, mais peut déborder / sous-estimer (voir "Dans quelle mesure les compilateurs Fortran sont-ils vraiment meilleurs?" ).
Vous pouvez ignorer en toute sécurité les méthodes 5-7 (les méthodes basées sur un solveur ODE sont inefficaces), les méthodes 8-13 (coûteuses), la méthode 14 (le calcul des vecteurs propres de grandes matrices est difficile sans structure spéciale et sujet à des erreurs numériques dans des cas mal conditionnés) et la méthode 16 (le calcul de la décomposition de Jordan d'une matrice est numériquement instable). Les méthodes 17-19 sont plus difficiles à mettre en œuvre; en particulier, les méthodes 17 et 18 nécessiteraient davantage de lecture. La méthode 1 est une option de repli pour la mise à l'échelle et la mise au carré si les approximations Padé ne fonctionnent pas bien.
Edit # 1 : Sur la base des commentaires en réponse à la réponse de Jack, la diagonalisation de bloc semble être une option, auquel cas, quelque chose comme la méthode 18 (diagonalisation bloc-triangulaire) est une très bonne méthode à utiliser. J'ai hésité à le recommander au début car votre question ne précisait pas cette structure, mais si vous avez une transformation qui bloque la diagonalisation de votre matrice, cela enlève la majeure partie de la complexité de l'approche. Vous voudrez juste vous assurer que vous utilisez l'astuce de GW Stewart pour décomposer chaque matrice diagonale de bloc enBj
où est la moyenne des valeurs propres de la matrice diagonale du ème bloc. Cette décomposition rendra presque nilpotent, ce qui améliorera la précision de vos calculs exponentiels matriciels. Cette astuce est discutée à la page 26 de la version du document Moler & van Loan à laquelle Jack a lié. j E jγj j Ej
la source
J'ai un simple sous-programme Fortran qui calcule l'exposant d'une matrice arbitraire. Je l'ai vérifié par rapport à la commande Matlab et ça va. Il est basé sur la mise à l'échelle et la quadrature. Je l'ai écrit il y a quelques années.
J'aimerais avoir un autre sous-programme, comme ceux que je télécharge sur gams.nist.gov. Mais pas encore de chance.
la source