jacob3
C JACOB3 SOURCE GOUNAND 25/10/23 21:15:05 12385
C======================================================================
C OBJET
C -----
C DIAGONALISATION D UNE MATRICE 3*3 SYMETRIQUE
C
C ENTREES
C -------
C A(3,3) = MATRICE SYMETRIQUE
C IDIMA = 2 OU 3 SI 2 ON NE S OCCUPE QUE DE A(2,2)
C SI 3 DE A(3,3)
C SORTIES
C -------
C D(3) = VALEURS PROPRES ORDONNEES D(1)>D(2)>D(3)
C
C X(3,3) = VECTEURS PROPRES ( X(IP,2) EST LE VECTEUR
C ASSOCIE A D(2) )
C
C===============================================================
IMPLICIT INTEGER(I-N)
IMPLICIT REAL*8 (A-H,O-Z)
-INC PPARAM
-INC CCOPTIO
-INC CCREEL
dimension a(3,3),d(3),x(3,3),s(3,3),as(3,3)
logical ldbg,lverif
dimension r(3,3),v(3)
*
* Verifications
lverif=.false.
* Impressions
ldbg=.false.
xpre=xzprec*10.D0
xpet=xpetit*10.D0
xprev=xzprec*10.D0
* xpre=xzprec*30.D0
* xpet=xpetit*30.D0
if (idima.ne.3) then
return
endif
*
* SCALING DE A
*
amax=0.d0
do i=1,idima
do j=1,idima
amax=max(amax,abs(a(j,i)))
enddo
enddo
* Matrice nulle
if (amax.lt.xpet) then
do i=1,idima
d(i)=0.D0
do j=1,idima
if (i.eq.j) then
x(j,i)=1.d0
else
x(j,i)=0.d0
endif
enddo
enddo
return
endif
C
amax1=1.D0/amax
do i=1,idima
do j=1,idima
as(j,i)=a(j,i)*amax1
enddo
enddo
*
* CALCUL DES INVARIANTS
*
* On applique la methode de Harari et Albocher IJNME'2023
* pour calculer les invariants et les valeurs propres
* Invariants J1=TRACE, J2, J3=DET
xj1=as(1,1)+as(2,2)+as(3,3)
do i=1,idima
do j=1,idima
if (i.eq.j) then
s(j,i)=as(j,i)-xj1/3
else
s(j,i)=as(j,i)
endif
enddo
enddo
if (ldbg) then
write(6,*) 'Matrice S='
do ii=1,idima
write (6,*) (S(ii,jj),jj=1,idima)
enddo
endif
* Dans la methode, on veut les invariants J2(S) et J3(S)
* où S est le deviateur de A (A = S + J1(A)/3 I)
* On a J1(S)=0 et lambda_A = lambda_S + J1(A)/3
*
* A et S ont les memes vecteurs propres
*
* On exprime les invariants de S de maniere stable en fonction des
* termes de A en particulier les differences diagonales
* En particulier J2 et J4 sont exprimes sous forme de sommes de
* carres donc positif. On peut donc en prendre les racines carrees
* sans fremir
d12=as(1,1)-as(2,2)
d23=as(2,2)-as(3,3)
d31=as(3,3)-as(1,1)
* Expression de J2(S)
xj2d=(d12**2+d23**2+d31**2)/6
xj2o=as(1,2)**2+as(2,3)**2+as(3,1)**2
xj2=xj2d+xj2o
* Expression du determinant J3(S)
xj3d=(d12-d31)*(d23-d12)*(d31-d23)/27
xj3m=(d12-d31)*as(2,3)**2+(d23-d12)*as(3,1)**2
$ +(d31-d23)*as(1,2)**2
xj3m=-xj3m/3
xj3o=2.d0*as(1,2)*as(2,3)*as(3,1)
xj3=xj3d+xj3m+xj3o
* Expression du discriminant Delta(S)=J4(S)=4 J2(S)^3 - 27 J3(S)^2
xj4x=d12*d23*d31
$ + as(1,2)**2*d12 + as(2,3)**2*d23 + as(1,3)**2*d31
xj4y1=as(2,3)*(2*as(2,3)**2 - as(1,3)**2 - as(1,2)**2 + 2*d12*d31)
$ +as(1,2)*as(1,3)*(d12-d31)
xj4y2=as(1,3)*(2*as(1,3)**2 - as(2,3)**2 - as(1,2)**2 + 2*d23*d12)
$ +as(1,2)*as(2,3)*(d23-d12)
xj4y3=as(1,2)*(2*as(1,2)**2 - as(2,3)**2 - as(1,3)**2 + 2*d31*d23)
$ +as(1,3)*as(2,3)*(d31-d23)
xj4z1=as(2,3)*(as(1,3)**2 - as(1,2)**2) + as(1,2)*as(1,3)*d23
xj4z2=as(1,3)*(as(1,2)**2 - as(2,3)**2) + as(2,3)*as(1,2)*d31
xj4z3=as(1,2)*(as(2,3)**2 - as(1,3)**2) + as(1,3)*as(2,3)*d12
*
xj4=xj4x**2+xj4y1**2+xj4y2**2+xj4y3**2
$ + 15* (xj4z1**2+xj4z2**2+xj4z3**2)
if (ldbg) then
* Impression des invariants de S
& - s(1,3)**2 - s(1,2)**2 - s(2,3)**2
c0=-2.d0*s(1,2)*s(1,3)*s(2,3) + s(1,1)*s(2,3)**2
& + s(2,2)*s(1,3)**2 + s(3,3)*s(1,2)**2
& - s(1,1)*s(2,2)*s(3,3)
xj2b=-c1
xj3b=-c0
xj4b=4*xj2b**3-27*xj3b**2
write(6,*) 'Invariants du deviateur S : new old abs(old-new)'
write(6,*) ' trace= ',xj1,xj1b,abs(xj1b-xj1)
write(6,*) ' J2= ',xj2,xj2b,abs(xj2b-xj2)
write(6,*) ' det= ',xj3,xj3b,abs(xj3b-xj3)
write(6,*) ' discr= ',xj4,xj4b,abs(xj4b-xj4)
endif
*
* CALCUL DES VALEURS PROPRES
*
sdet=sign(1.d0,xj3)
xsj4=sqrt(xj4)
xsj2=sqrt(xj2)
xdenom=2*xj2*xsj2+3*sqrt(3.d0)*sdet*xj3
ang=2.d0/3.d0*atan2(xsj4,xdenom)
xf1=xsj2*sdet
xf2=cos(ang)/sqrt(3.d0)
xf3=sin(ang)
* Si sdet=1 ds1 .GE. ds2 .GE. ds3
* Si sdet=-1 ds3 .GE. ds2 .GE. ds1
* dsi sont les valeurs propres de S
* dAi sont les valeurs propres de A
ds1=2*xf1*xf2
ds2=xf1*(xf3-xf2)
ds3=xf1*(-xf3-xf2)
xj13=xj1/3
das1=ds1+xj13
das2=ds2+xj13
das3=ds3+xj13
* Impression des valeurs propres de A par les methodes nouvelles et anciennes
if (ldbg) then
d(2)=das2
if (sdet.gt.0) then
d(1)=das1
d(3)=das3
else
d(3)=das1
d(1)=das3
endif
* Methode ancienne
& - as(1,3)**2 - as(1,2)**2 - as(2,3)**2
c0=-2.d0*as(1,2)*as(1,3)*as(2,3) + as(1,1)*as(2,3)**2
& + as(2,2)*as(1,3)**2 + as(3,3)*as(1,2)**2
& - as(1,1)*as(2,2)*as(3,3)
write(6,*) 'Som vp=',d1+d2+d3
write(6,*) 'Prod vp=',d1*d2*d3
if (d1.lt.d2) then
dd=d1
d1=d2
d2=dd
endif
if (d1.lt.d3) then
dd=d1
d1=d3
d3=dd
endif
if (d2.lt.d3) then
dd=d2
d2=d3
d3=dd
endif
db1=d1
db2=d2
db3=d3
write(6,*) 'Val. propres de A scalee : new old abs(old-new)'
write(6,*) ' vp1= ',d(1),db1,abs(db1-d(1))
write(6,*) ' vp2= ',d(2),db2,abs(db2-d(2))
write(6,*) ' vp3= ',d(3),db3,abs(db3-d(3))
endif
*
* Faire le calcul des vecteurs propres avec S plutôt qu'avec A
* (moins d'erreur de cancellation)
* On utilise la méthode de deflation de Scherzinger et Dohrmann
* CMAME'08 car sinon, on n'a pas reussi a avoir une bonne
* orthogonalite des vecteurs propres lorsque les valeurs propres
* sont proches
*
d(2)=ds2
* Si sdet est positif, d(1) est la valeur propre la plus isolee
* Si sdet est negatif, d(3) est la valeur propre la plus isolee
* On recherche d'abord le vecteur propre associe a cette valeur
* propre
if (sdet.gt.0) then
igr=1
else
igr=3
endif
* igr vaut 1 ou 3 quand ipe vaut 3 ou 1
ipe=4-igr
d(igr)=ds1
d(ipe)=ds3
if (ldbg) then
write(6,*) 'Val. propres de S'
write(6,*) ' vp1= ',d(1)
write(6,*) ' vp2= ',d(2)
write(6,*) ' vp3= ',d(3)
endif
*
* CALCUL DES VECTEURS PROPRES
*
* Raccourci lorsque les trois valeurs propres sont egales
* Dans ce cas S=0 et J2(S)=0
*
xsca=max(xpre,xpet)
if (ldbg) then
write(6,*) 'xpre,xpet,xsca,xsj2=',xpre,xpet,xsca,xsj2
endif
*
if (xsj2.lt.xsca) then
if (ldbg) write(6,*) '3 valeurs propres egales detectees'
do i=1,idima
do j=1,idima
if (i.eq.j) then
x(j,i)=1.d0
else
x(j,i)=0.d0
endif
enddo
enddo
goto 1000
endif
*
* Faire le calcul des vecteurs propres avec S plutôt qu'avec A
* (moins d'erreur de cancellation)
* On utilise la méthode de deflation de Scherzinger et Dohrmann
* CMAME'08 car sinon, on n'a pas reussi a avoir une bonne
* orthogonalite des vecteurs propres lorsque les valeurs propres
* sont proches
*
* RECHERCHE DU 1er VECTEUR PROPRE associe a la valeur propre isolee
* d(igr)
*
call vectp2(s,d,igr,x)
if (lverif) then
* Verif
call vmorth(x,idima,3,xpre,r)
if (ierr.ne.0) then
write(6,*) '!!! X non orthonormale'
if (ldbg) then
write(6,*) 'Matrice des VPs X='
do ii=1,idima
write (6,*) (X(ii,jj),jj=1,idima)
enddo
write(6,*) 'Matrice des Pscals R='
do ii=1,idima
write (6,*) (R(ii,jj),jj=1,idima)
enddo
endif
goto 9999
endif
* vp(igr) est-il bien le vp associe a la valeur propre d(igr)
call vvectp(s,idima,3,d(igr),x(1,igr),xprev,v)
if (ierr.ne.0) then
write(6,*) '!!! vp(igr) nest pas vecteur propre '
if (ldbg) then
write(6,*) ' v= (S - D(igr)) x(j,igr) ='
write(6,*) (v(jj),jj=1,idima)
endif
goto 9999
endif
endif
*
* FIN DE RECHERCHE DU 1er VECTEUR PROPRE
*
*
* Raccourci lorsque les deux autres valeurs propres sont egales
* Dans ce cas le discriminant est nul J4(S)=0
* Le developpement limite de lambda_2 et lambda_3 en J4 tendant vers
* 0 est :
* lambda_2,3 \propto sqrt(J2) ( 1 + sqrt(J4) / (J2^3/2) )
*
xsca=max((xsj2**3)*xpre,xpet)
if (ldbg) then
write(6,*) 'xsj2,xsj23,xpre,xsca,xsj4=',xsj2,xsj2**3,xpre,xsca
$ ,xsj4
endif
if (xsj4.lt.xsca) then
if (ldbg) write(6,*) '2 valeurs propres egales detectees'
* La matrice X contient une base donc on peut quitter prematurement
goto 1000
endif
*
* RECHERCHE des 2emes et 3emes VECTEURS PROPRES
* les valeurs propres sont normalement numeriquement distinctes
*
* Recherche un vecteur propre x(j,2) associe à la valeur propre
* simple d(2) d'une matrice 3x3 S
*
* L'image de S-d(2)I est de dimension 2 car d(2) est valeur
* propre simple. On cherche uniquement la partie de l'image
* orthogonale à vp(igr).
* Pour ce faire, on prend la plus grande des images des deux
* vecteurs de la base X différents de vp(igr). Ces deux images sont
* colinéaires car à la fois orthogonales à vp(igr) et vp(2) : w1
*
* On choisit ensuite : vp(2) = w1 \pvec vp(1)
* puis : vp(3) = vp(1) \pvec vp(2)
*
*
call vectp3(s,d,igr,x)
*
* Verif
if (lverif) then
* Orthonormalite des vps
call vmorth(x,idima,3,xpre,r)
if (ierr.ne.0) then
write(6,*) '!!! X non orthonormale'
if (ldbg) then
write(6,*) 'Matrice des VPs X='
do ii=1,idima
write (6,*) (X(ii,jj),jj=1,idima)
enddo
write(6,*) 'Matrice des Pscals R='
do ii=1,idima
write (6,*) (R(ii,jj),jj=1,idima)
enddo
endif
goto 9999
endif
do i=1,idima
* vp(i) est-il bien le vp associe a la valeur propre d(i)
call vvectp(s,idima,3,d(i),x(1,i),xprev,v)
if (ierr.ne.0) then
write(6,*) '!!! vp(i) nest pas vecteur propre i=',i
if (ldbg) then
write(6,*) ' v= (S - D(i)) x(j,i) ='
write(6,*) (v(jj),jj=1,idima)
endif
goto 9999
endif
enddo
endif
*
if (.false.) then
* Methode ancienne
dmaxa=max(abs(d(1)),abs(d(2)),abs(d(3)))
deps=max(dmaxa*xpre,xpetit*10.d0)
if (abs(d(1)-d(2)).le.deps) then
* valeur propre double
if (abs(d(2)-d(3)).le.deps) then
* valeur propre triple
if (ldbg) write(6,*) 'JACOB3 Valeur propre triple'
else
if (ldbg) write(6,*) 'JACOB3 Valeur propre double 1'
x(1,3)=x(2,1)*x(3,2)-x(3,1)*x(2,2)
x(2,3)=x(3,1)*x(1,2)-x(1,1)*x(3,2)
x(3,3)=x(1,1)*x(2,2)-x(2,1)*x(1,2)
*old call vectp(a,d(3),x(1,3),1)
endif
else
if (abs(d(2)-d(3)).le.deps) then
if (ldbg) write(6,*) 'JACOB3 Valeur propre double 2'
* valeur propre double
x(1,1)=x(2,2)*x(3,3)-x(3,2)*x(2,3)
x(2,1)=x(3,2)*x(1,3)-x(1,2)*x(3,3)
x(3,1)=x(1,2)*x(2,3)-x(2,2)*x(1,3)
*old call vectp(a,d(1),x(1,1),1)
else
* cas normal
if (ldbg) write(6,*) 'JACOB3 Cas normal'
endif
endif
endif
*
* On remet dans D les valeurs propres de A a la place de celles de S
*
1000 continue
d(2)=das2*amax
if (sdet.gt.0) then
d(1)=das1*amax
d(3)=das3*amax
else
d(3)=das1*amax
d(1)=das3*amax
endif
return
*
* Error handling
*
9999 CONTINUE
MOTERR(1:8)='JACOB3'
return
end
					© Cast3M 2003 - Tous droits réservés.
					Mentions légales