! commentaire program Cyclo ! Déclaration de variables implicit none real(kind=8), dimension(:),allocatable::b,u real(8)::alpha,beta integer, parameter::l=13,n=2**(l+1)-1,m=2000 !integer, parameter::l=3,n=2**(l+1)-1,m=15 integer::i,j real(8) :: hx, hy, hyCarre ! Maillage real(kind=8), dimension(0:m+1) :: xg real(kind=8), dimension(0:n+1) :: yg ! Cpu time real(kind=8) :: debut, fin, dummy ! Initialisation du maillage et calcul du pas xg=0.0d0 yg=0.0d0 hx=1/dble(m+1) hy=1/dble(n+1) call cpu_time(dummy) ! création du maillage do i=0,m+1 xg(i)=dble(i)*hx enddo do i=0,n+1 yg(i)=dble(i)*hy enddo ! Allocation des vecteurs allocate(b(n*m)) allocate(u(n*m)) print *,'calcul de b' ! Calcul de b b=0 hyCarre=hy*hy do i=1,m do j=1,n b(i+m*(j-1))=(hyCarre)*get_rhs(xg(i),yg(j)) end do end do !calcul de beta et alpha alpha=hyCarre/(hx*hx) beta=2+2*alpha print *,'Reduction' !appel de la reduction cyclique call cpu_time(debut) call reduction(b,n*m,m,-alpha,beta) call cpu_time(fin) call solution(xg,yg,u,m,n) print *, sqrt(dot_product(b-u,b-u)) print *, (fin - debut), ' s' deallocate(b) deallocate(u) contains function get_rhs(x,y) implicit none real(8) :: x,y,get_rhs get_rhs=-2*x*(x-1)-2*y*(y-1) end function end program Cyclo subroutine solution(xg,yg,u,m,n) implicit none real(8), dimension(0:m+1) :: xg real(8), dimension(0:n+1) :: yg real(8), dimension(m*n) :: u integer :: i,j,m,n do i=1,m do j=1,n u(i+m*(j-1))=xg(i)*yg(j)*(xg(i)-1)*(yg(j)-1) enddo enddo end subroutine subroutine factoAk(k,b,m,moinsAlpha,beta) implicit none !argument de la fonction real(8),intent(in)::moinsAlpha,beta integer,intent(in)::k,m real(8),dimension(m),intent(inout)::b !variables locales integer::j,jmax real(8)::pidiv,lambda real(8),dimension(m)::z !calcul d'une constante d'optimisation de temps de calcul pidiv=2*atan(x=1.0d0)/2**k do j=1,2**k lambda = 2*cos((2*j-1)*pidiv) call tridiag(moinsAlpha,beta - lambda,m,b(1:m)) end do end subroutine subroutine reduction(b,taille,m,moinsAlpha,beta) implicit none !parametres real(8),intent(in)::moinsAlpha,beta integer,intent(in)::taille,m real(8),dimension(taille),intent(inout)::b !variables locales integer::n,l,k,i,j,inc,oldinc,imax,im,r,i1,i2,ie, ind1,ind2 real(8),dimension(:),allocatable::p,q real(8),dimension(:),allocatable::ptemp real(8)::unsura !variables locales integer::jmax real(8)::pidiv print*,'initialisation de la réduction' allocate(p(taille)) allocate(q(taille)) allocate(ptemp(m)) j = 1 jmax = 2**k pidiv=2*atan(x=1.0d0)/jmax !initialisation des variables locales n=taille/m l=log(x=n+1.0)/log(x=2.0)-1.0 imax=2**(l+1) q=0 p=b ptemp = 0 print*,'initialisation de p et q---------' !Premiere Boucle : initialisation de p et q do i=1,n call tridiag(moinsAlpha,beta,m,p((i-1)*m+1:i*m)) end do print*,'p apres initialisation---------' do i=1,n !print *,p((i-1)*m+1:i*m) enddo do i=1,2**l-1 i1=(2*i-1)*m+1 i2=2*i*m q(i1:i2)= b(i1-m:i2-m) + b(i1+m:i2+m) + 2*p(i1:i2) end do print*,'q apres initialisation ---------' do i=1,n !print *,q((i-1)*m+1:i*m) enddo !--- Deuxieme boucle : calcul de p et de q do k=2,l r=2**k do i=1,2**(l-k+1)-1 i1=(r*i-1)*m+1 i2=r*i*m ie=m*r/2 !print *,i1,',',i2,',',ie ptemp(1:m) = q(i1:i2)+p(i1-ie:i2-ie)+p(i1+ie:i2+ie) call factoAk(k-1,ptemp,m,moinsAlpha,beta) p(i1:i2) = p(i1:i2) + ptemp q(i1:i2) = 2*p(i1:i2)+q(i1-ie:i2-ie)+q(i1+ie:i2+ie) end do end do print*,'---------p apres reduction' do i=1,n !print *,p((i-1)*m+1:i*m) enddo print*,'---------q apres reduction' do i=1,n !print *,q((i-1)*m+1:i*m) enddo !on a plus besoin de b a partir d'ici b=0 ptemp = q((2**l-1)*m+1:(2**l)*m) call factoAk(l,ptemp,m,moinsAlpha,beta) b((2**l-1)*m+1:(2**l)*m)=p((2**l-1)*m+1:(2**l)*m)+ptemp print*,'---------y' ! print *, "y=", (2**l-1)*m+1, (2**l)*m print*,'---------x' ! print *, "x=", b((2**l-1)*m+1:2**l*m) do k=l-1,0,-1 r=2**k im=2**(l-k+1)-1 do i=1,im,2 i1=(r*i-1)*m+1 i2=r*i*m ie=m*r if(i == 1) then ptemp = b(i1+ie:i2+ie)+q(i1:i2) else if (i==im) then ptemp = b(i1-ie:i2-ie)+q(i1:i2) else ptemp = b(i1+ie:i2+ie)+b(i1-ie:i2-ie)+q(i1:i2) endif endif call factoAk(k,ptemp,m,moinsAlpha,beta) b(i1:i2)=p(i1:i2)+ptemp end do end do !print *, "x=", b((2**l-1)*m+1:2**l*m) end subroutine subroutine tridiag(diagValue,tridiagValue,m,b) implicit none real(8),intent(in)::diagValue, tridiagValue integer,intent(in)::m real(8),dimension(m),intent(inout)::b ! d, diag ! e, sous/sur-diag real(8)::r integer::i real(8),dimension(m)::e, d ! factorisation d = tridiagValue e = diagValue do i=2,m r = e(i-1) e(i-1) = dble(r / d(i-1)) d(i) = d(i) - r*e(i-1) !print *,'\t1\t{',d end do ! phase de substitution directe do i=2,m b(i) = b(i) - e(i-1)*b(i-1) !print *,'\t2\t{',b end do b(m) = b(m) / d(m) ! substitution inverse do i=m-1,1,-1 b(i) = b(i)/d(i)-e(i)*b(i+1) !print *,'\t3\t{',b end do end subroutine