copyright (C) 2001 MSC-RPN COMM %%%MC2%%% ***s/r adipc2_3d *subroutine adipc2_3d (g,h,s,czz,c2,dge,c5,nlim,nx,ny,nz,niter) 2,3 implicit none * integer nlim,nx,ny,nz,niter real*8 g(nx,ny,nz), h(nx,ny,nz), dge, c2, c5, $ czz(1-(niter-1):nx+(niter-1),1-(niter-1):ny+(niter-1),nz,3) real s(1-(niter-1):nx+(niter-1),1-(niter-1):ny+(niter-1)) * *AUTHOR Andre Robert. Sep 1987 * *REVISION * Evhen Yakimiw May 1988 * - version nested * M. Tanguay May 1989 * - gal-chen sans montagnes * Yves Chartier/Michel Desgagne Oct/Nov 1992 * - implicit none * - structural documentation * - working vectors memory allocation * - in lining * Michel Giguere/Michel Desgagne Dec 1992 * - solution now stable for small dt * Guy Bergeron Sept. 1994 * - version 2D dans le plan XZ * - automatisation du solveur * Michel Desgagne Feb 2001 * - Transpose strategy for DM version * *OBJECT * Effectue une iteration avec une variante tridimensionnelle * du scheme adi (Peaceman-Rachford) utilise frequemment pour * resoudre l'equation de poisson en deux dimensions. * * Seules les valeurs a l'exterieur a la zone frontiere sont evaluees * (c.f. figure 3.2.3). Les valeurs des variables situees sur des * points contenuent dans la zone de pilotage sont entierement dictees * par le modele pilote. * *FILES * *ARGUMENTS * NAMES I/O TYPE A/S DESCRIPTION * * g O R A valeur de qp a (t+dt) * h I R A (-(A2/RT*)(dz/dt1)**2) * s I R A Sbarxy*C1*(dz/dx)**2 * dz I R S distance entre deux niveaux du modele * dt I R S (dt) modifie 0.5*(1+grepsi)*frtss * dge I R S coeff. d'iteration de la methode ADI * nx I I S dimension de la grille selon X * ny I I S dimension de la grille selon Y * nz I I S dimension de la grille selon Z * *IMPLICIT #include "lcldim.cdk"
#include "nbcpu.cdk"
#include "yomdyn.cdk"
#include "yomdyn1.cdk"
#include "transpose.cdk"
#include "partopo.cdk"
include 'mpif.h'
* ** integer i,j,k,kp1,km1,offj,iter,rpn_comm_topo,err real*8 dgel,dgex,con,conx,conz,one,two,four, $ q(minx:maxx,miny:maxy,nz), $ w1(gni,gnj),sg(gni,gnj),r(nh_maxx,nh_maxy,nz), $ g1(nh_maxy,t1maxk,gni+npex),ax(nh_maxy,t1maxk,gni+npex), $ bx(nh_maxy,t1maxk,gni+npex),cx(nh_maxy,t1maxk,gni+npex), $ g2(t1maxk ,t2maxx,gnj+npey),ay(t1maxk ,t2maxx,gnj+npex), $ by(t1maxk ,t2maxx,gnj+npex),cy(t1maxk ,t2maxx,gnj+npex), $ az(nh_maxx,nh_maxy,nz),bz(nh_maxx,nh_maxy,nz), $ cz(nh_maxx,nh_maxy,nz) parameter (one = 1.0d0, two = 2.0d0, four = 4.0d0) * *---------------------------------------------------------------------- * !$omp single conx = one / ( dble(grdx) * dble(grdx) ) * * Globalizing s into sg * do j=1,gnj do i=1,gni w1(i,j) = 0. end do end do do j=1,ldnj offj = gc_ld(3,myproc)-1 do i=1,ldni w1(gc_ld(1,myproc)+i-1,offj+j) = s(i,j)*conx end do end do if (numproc.gt.1) then call MPI_ALLREDUCE (w1,sg,gni*gnj,MPI_DOUBLE_PRECISION,MPI_SUM, $ MPI_COMM_WORLD,err) else do j=1,gnj do i=1,gni sg(i,j) = w1(i,j) end do end do endif * dgel=dge * * g is pushed into q for halo exchange purposes * do k = 1, nz do j = 1, ny do i = 1, nx q(i,j,k) = g(i,j,k) end do end do end do * * Establishing ax and cx and filling out borders of bx * do j = 1, ldnj-north do i = 1, gni-1 ax(j,1,i) = sg(i,gc_ld(3,myproc)+j-1) cx(j,1,i) = sg(i,gc_ld(3,myproc)+j-1) end do ax(j,1,gni-1) = 0.0 cx(j,1,1 ) = 0.0 end do do i = 1, gni-1 do j = ldnj-north+1, nh_maxy ax(j,1,i) = 0. bx(j,1,i) = 1. cx(j,1,i) = 0. end do do k = 2, t1maxk do j = 1, nh_maxy ax(j,k,i) = ax(j,1,i) cx(j,k,i) = cx(j,1,i) end do end do end do * * Establishing ay and cy and filling out borders of by * do i = 1, t2n-teast do j = 1, gnj-1 ay(1,i,j) = sg(t2n0+i-1,j) cy(1,i,j) = sg(t2n0+i-1,j) end do ay(1,i,gnj-1) = 0.0 cy(1,i, 1) = 0.0 end do do j = 1, gnj-1 do i = t2n-teast+1, t2maxx ay(1,i,j) = 0. by(1,i,j) = 1. cy(1,i,j) = 0. end do do k = 2, t1maxk do i = 1, t2maxx ay(k,i,j) = ay(1,i,j) cy(k,i,j) = cy(1,i,j) end do end do end do * * Establishing az and cz and filling out borders of bz * do k = 1, nz do j = 1, ldnj-north do i = 1, ldni-east az(i,j,k) = czz(i,j,k,3) cz(i,j,k) = czz(i,j,k,1) end do end do do j = ldnj-north+1, nh_maxy do i = 1, ldni-east az(i,j,k) = 0. bz(i,j,k) = 1. cz(i,j,k) = 0. end do end do do i = ldni-east+1, nh_maxx do j = 1, nh_maxy az(i,j,k) = 0. bz(i,j,k) = 1. cz(i,j,k) = 0. end do end do end do * * Perform nlim iterations * do 100 iter = 1, nlim * dgel = dgel*c5**two dgex = dgel-c2 con = (two*dgel-c2)*dgex * do k = 1, nz if (west.gt.0) then do j = 1, ldnj-north q(0,j,k) = q(1,j,k) end do endif if (east.gt.0) then do j = 1, ldnj-north q(ldni,j,k) = q(ldni-1,j,k) end do endif if (south.gt.0) then do i = 1, ldni-east q(i,0,k) = q(i,1,k) end do endif if (north.gt.0) then do i = 1, ldni-east q(i,ldnj,k) = q(i,ldnj-1,k) end do endif end do * call rpn_comm_xch_halon (q,minx,maxx,miny,maxy,ldni,ldnj, $ nz,hx,hy,period_x,period_y,ldni,0,2) * do k = 1, nz conz = conx if(k.eq.gnk) conz = 0. kp1 = min( nz,k+1 ) km1 = max( k-1, 1 ) do j = 1, ldnj-north do i = 1, ldni-east r(i,j,k) = conz * s(i,j) * $ ( q(i+1,j ,k) + q(i-1,j ,k) + $ q(i ,j+1,k) + q(i ,j-1,k) - four*q(i,j,k) ) + $ czz(i,j,k,1) * q(i,j,km1) + $ czz(i,j,k,2) * q(i,j,k ) + $ czz(i,j,k,3) * q(i,j,kp1) - h(i,j,k) end do end do end do * * Solving 3-diag matrix in x direction * call rpn_comm_transpose ( r,1,nh_maxx,gni,nh_maxy,1,t1maxk,nz, $ g1, 1, 2 ) do j=ldnj-north+1,nh_maxy do k=1,t1n do i=1,gni-1 g1(j,k,i) = 0. end do end do end do * do i = 1, gni-1 do j = 1, ldnj-north bx(j,1,i) = dgex +ax(j,1,i) +cx(j,1,i) end do end do do i = 2, gni-1 do j = 1, ldnj-north bx(j,1,i) = bx(j,1,i)-cx(j,1,i)*ax(j,1,i-1)/bx(j,1,i-1) end do end do do k = 2, t1maxk do j = 1, nh_maxy do i = 1, gni-1 bx(j,k,i) = bx(j,1,i) end do end do end do * call tridiag
(g1,ax,bx,cx,nh_maxy*t1maxk,nh_maxy*t1n,gni) * * Solving 3-diag matrix in y direction * call rpn_comm_transpose ( g1,1,nh_maxy,gnj,t1maxk,1,t2maxx,Gni, $ g2, 2, 2 ) do k=t1n+1,t1maxk do i=1,t2n-teast do j=1,gnj-1 g2(k,i,j) = 0. end do end do end do * do j = 1, gnj-1 do i = 1, t2n-teast by(1,i,j) = dgex +ay(1,i,j) +cy(1,i,j) end do end do do j = 2, gnj-1 do i = 1, t2n-teast by(1,i,j) = by(1,i,j) - cy(1,i,j)*ay(1,i,j-1)/by(1,i,j-1) end do end do do k = 2, t1maxk do i = 1, t2maxx do j = 1, gnj-1 by(k,i,j) = by(1,i,j) end do end do end do * call tridiag
(g2,ay,by,cy,t1maxk*t2maxx,t1maxk*(t2n-teast),gnj) * call rpn_comm_transpose (g1,1,nh_maxy,gnj,t1maxk ,1,t2maxx,Gni, $ g2, -2, 2 ) call rpn_comm_transpose (r ,1,nh_maxx,gni,nh_maxy,1,t1maxk,nz, $ g1, -1, 2 ) * * Solving 3-diag matrix in z direction * do k = 1, nz do j = 1, ldnj-north do i = ldni-east+1,nh_maxx r(i,j,k) = 0. end do end do end do do k = 1, nz do j = 1, ldnj-north do i = 1, ldni-east bz(i,j,k) = -czz(i,j,k,2) + dgel end do end do end do do k = 2, nz do j = 1, ldnj-north do i = 1, ldni-east bz(i,j,k)= bz(i,j,k)-cz(i,j,k)*az(i,j,k-1)/bz(i,j,k-1) end do end do end do * call tridiag
(r,az,bz,cz,nh_maxx*nh_maxy,nh_maxx*(ldnj-north), $ nz+1) * do k = 1, nz do j = 1, ldnj-north do i = 1, ldni-east q(i,j,k) = q(i,j,k) + con*r(i,j,k) end do end do end do * 100 continue * do k = 1, nz do j = 1, ny do i = 1, nx g(i,j,k) = q(i,j,k) end do end do end do * !$omp end single *---------------------------------------------------------------------- return end *
subroutine tridiag (g,a,b,c,ns,n,gn) 3 implicit none * integer ns,n,gn real*8 g(ns,*),a(ns,*),b(ns,*),c(ns,*) * integer i,j * do i=2,gn-1 do j=1,n g(j,i) = g(j,i) + c(j,i) * g(j,i-1)/b(j,i-1) end do end do do j=1,n g(j,gn-1) = g(j,gn-1)/b(j,gn-1) end do do i=gn-2,1,-1 do j=1,n g(j,i) = (g(j,i) + a(j,i) * g(j,i+1))/b(j,i) end do end do * return end