source: branches/iLoveclim/SOURCES/courbures.f90 @ 244

Last change on this file since 244 was 187, checked in by aquiquet, 6 years ago

Grisli-iloveclim branch merged to trunk at revision 185

File size: 6.9 KB
Line 
1!> \file courbures.f90
2!! Implementation du subroutine courbure
3!<
4
5!> SUBROUTINE: courbure
6!! \author ...
7!! \date ...
8!! @note Subroutine qui permet de trouver la surface de type
9!! @note A_2D(x,y)=ax2+by2+cxy+dx+ey+f 
10!! @note passant au plus pres (moindre carre) des 9 points d'une sous grille
11!! @note Ensuite, calcule les diverses courbures, la pente et son azimuth
12!! @note Le pas de la grille est 1     
13!! @note Fait appel a sgelsy  de Lapack qui minimise || A * X -B ||
14!>
15subroutine courbure(nx,ny,dy,A_2D,A_new,pente_A,teta_A,crx,cry,crxy)
16
17implicit none
18
19integer mnode,ncoef,npts
20
21! entree routine
22
23integer,intent(in) :: nx,ny         !< dimensions des matrices 
24real,intent(in)    :: dy            !< maille physique
25real,dimension(nx,ny),intent(in) :: A_2D  !< la surface dont on cherche la courbure
26
27! sortie routine
28real,dimension(nx,ny),intent(out):: A_new      !< altitude finale du point
29real,dimension(nx,ny),intent(out):: pente_A    !< pente_A (amplitude)
30real,dimension(nx,ny),intent(out):: teta_A     !< direction de la pente
31real,dimension(nx,ny),intent(out):: crx        !< courbure dans la direction de la pente 
32real,dimension(nx,ny),intent(out):: cry        !< courbure dans la direction transversale
33real,dimension(nx,ny),intent(out):: crxy       !< courbure croisee
34
35
36! variables locales
37parameter(mnode=9)          !< nombre de points de la sous-grille
38parameter (ncoef=6)         !< nombre de coefficients de A_2D
39parameter (npts=60000)      !< nombre de points a traiter (nx*ny)
40
41real :: dx_ls                               !< pas de la grille dans le moindre carre
42integer :: i,j,k,pp,iz,jz,iz1,jz1         !< compteurs
43real :: x,y                                 !< coordonnees dans la sous-grille
44real :: aaa                                 !< pour le calcul de l'azimut
45
46
47! specifiques pour appel a sgelsy
48real :: Blin(mnode,npts)            !< en input c'est B(mnoeud,npts)
49                                    !< en output c'est X(ncoef,npts)
50real :: A(mnode,ncoef)              !< matrice A
51real :: rcond                       !< pour appel a sgelsy  ~ max(A)/min(A)
52integer :: rank                     !< pour sgelsy (output) -> rang de R11
53integer :: lwork                    !< taille du tableau de travail
54parameter(lwork = 200000)           !< voir sgelsy
55real,dimension(lwork) :: work       !< tableau de travail
56integer,dimension(ncoef):: jpvt     !< vecteur entier
57integer :: info                     !< retour des info
58integer :: mm,nn,npp,lw
59       
60
61mm=mnode                            ! pour ne pas passer des
62nn=ncoef                            ! constantes aux routines
63npp=npts                           
64lw=lwork                       
65
66dx_ls=1                             ! pas utilise dans le moindre carre
67
68
69
70
71!      remplissage de la matrice A (la meme pour tous les points)
72
73k=0
74do j=-1,1            !                                   7   8   9
75   do i=-1,1         ! balaye les i puis les j           4   5   6
76      k=k+1          ! k varie de 1 a 9                  1   2   3
77      x=i*dx_ls
78      y=j*dx_ls
79     
80      A(k,1)=x*x
81      A(k,2)=y*y
82      A(k,3)=x*y
83      A(k,4)=x
84      A(k,5)=y
85      A(k,6)=1
86   end do
87end do
88
89rcond=1.e-30
90
91
92!     boucle sur les points
93pp=0
94ij_loop: do j=1,ny
95pp_loop:   do i=1,nx
96      pp=pp+1            ! pp varie de 1 a nx*ny
97     
98
99!       Construction de la sous-grille centree sur i,j
100      k=0
101      do jz=j-1,j+1
102         do iz=i-1,i+1
103            iz1=max(1,iz)      ! pour éviter les débordements du tableau A_2D
104            iz1=min(nx,iz1)
105            jz1=max(1,jz)
106            jz1=min(ny,jz1)
107
108            k=k+1              ! k varie de 1 a 9
109
110            Blin(k,pp)=A_2D(iz1,jz1)
111         end do
112      end do
113
114   end do pp_loop
115end do ij_loop 
116
117!____________________________________________________________________
118!
119!  appel a la subroutine sgelsy
120!____________________________________________________________________
121
122call sgelsy(mm,nn,npp,a,mm,blin,mm,jpvt,rcond,rank,work,lw,info)
123
124 
125!       Maintenant les coefficients sont dans Blin(1:6,pp)
126!        Blin(1,pp)= a    coeff de x2
127!        Blin(2,pp)= b    coeff de y2
128!        Blin(3,pp)= c    coeff de xy
129!        Blin(4,pp)= d    coeff de x
130!        Blin(5,pp)= e    coeff de y
131!        Blin(6,pp)= f    terme constant
132
133pp=0
134grille_loop: do j=1,ny
135   do i=1,nx
136      pp=pp+1
137      A_new(i,j)=Blin(6,pp)                                    ! f
138      pente_A(i,j)=Blin(4,pp)*Blin(4,pp)+Blin(5,pp)*Blin(5,pp) ! d2+e2
139     
140
141
142pente_sup0:  if ((pente_A(i,j).gt.1.e-5)   &
143                .and.(i.ne.1).and.(i.ne.nx).and.(j.ne.1).and.(j.ne.ny))  then
144
145! pente
146         pente_A(i,j)=(pente_A(i,j)**0.5)                    ! attention ce calcul etait avant fait
147                                                             ! apres le calcul de courbure.
148                                                             ! Par comparaison avec Frederique, c'etait un bug.
149
150
151! courbx
152         crx(i,j)=blin(1,pp)*blin(4,pp)*blin(4,pp)     &     ! ad2
153               +  blin(2,pp)*blin(5,pp)*blin(5,pp)     &     ! be2
154               +  blin(3,pp)*blin(4,pp)*blin(5,pp)           ! cde
155
156         crx(i,j)=2.*crx(i,j)/pente_A(i,j)/dy/dy             ! dy2 pour
157                                                             ! passage en dim reelle
158
159! courby
160         cry(i,j)=blin(1,pp)*blin(5,pp)*blin(5,pp)     &     ! ae2
161               +  blin(2,pp)*blin(4,pp)*blin(4,pp)     &     ! bd2
162               -  blin(3,pp)*blin(4,pp)*blin(5,pp)           ! -cde
163               
164         cry(i,j)=2.*cry(i,j)/pente_A(i,j)/dy/dy             ! dy2 pour
165                                                             ! passage en dim reelle
166
167! courbxy
168         crxy(i,j)=2.*blin(1,pp)*blin(4,pp)*blin(5,pp)  &    ! 2ade
169                -  2.*blin(2,pp)*blin(4,pp)*blin(5,pp)  &    ! -2bed
170                -  blin(3,pp)*blin(4,pp)*blin(4,pp)     &    ! -cd2
171                -  blin(3,pp)*blin(5,pp)*blin(5,pp)          ! -ce2
172               
173         crxy(i,j)=crxy(i,j)/pente_A(i,j)/dy/dy              ! dy2 pour
174                                                             ! passage en dim reelle
175
176
177
178! direction de la pente
179         aaa=blin(5,pp)/pente_A(i,j)                         ! pente y / pente
180
181         if ((aaa.gt.-1.).and.(aaa.lt.1.)) then
182            teta_A(i,j)=asin(aaa)*180./3.14159
183         else if (aaa.ge.1.) then
184            teta_A(i,j)=90.
185         else if (aaa.le.-1.) then
186            teta_A(i,j)=-90.
187         endif
188
189         if (blin(4,pp).lt.0.) then
190            teta_A(i,j)=180.-teta_A(i,j)
191         endif
192         
193      else            ! pente nulle
194         crx(i,j)=0.
195         cry(i,j)=0.
196         crxy(i,j)=0.
197         pente_A(i,j)=0.
198         teta_A(i,j)=0.
199       
200      endif pente_sup0 !  Fin du test sur la pente
201
202! pente
203      pente_A(i,j)=pente_A(i,j)/dy     ! pour passage en dimension reelle
204
205   end do
206end do grille_loop                     !   fin de la boucle sur les points de grille
207   
208 
209return 
210end subroutine courbure
Note: See TracBrowser for help on using the repository browser.