******************************************************************************* * Sample driver for AZTEC package. The software is tested by setting up a * * system of equations and a right hand side and then solving the system of * * equations using AZTECs iterative solvers. * * * * This program create an MSR matrix corresponding to a 7pt discrete * * approximation to the 3D Poisson operator on an n x n x n square. * * n must be <= 50. * ******************************************************************************* program main include 'mpif.h' include 'az_aztecf.h' integer n common /global/ n C C integer i,j,IAM,NPROCS,ierr,nz,K,in,ik,nz1,nzz,no integer proc_config(0:AZ_PROC_SIZE), options(0:AZ_OPTIONS_SIZE) double precision params(0:AZ_PARAMS_SIZE) double precision status(0:AZ_STATUS_SIZE) double precision s,time,total integer N_update,ierror,recb(0:63),disp(0:63) CHARACTER*8 met(0:4) integer, dimension(:), allocatable:: data_org, update integer, dimension(:), allocatable:: external, update_index integer, dimension(:), allocatable:: extern_index, bindx real(KIND=8), dimension(:), allocatable:: b,x,tmp,val CALL MPI_Init(ierror) C met(0) = 'cg' met(1) = 'gmres' met(2) = 'cgs' met(3) = 'tfqmr' met(4) = 'bicgstab' C C get number of processors and the name of this processor C call AZ_processor_info(proc_config) IAM = proc_config(AZ_node) NPROCS = proc_config (AZ_N_procs) C if (IAM.eq.0) then write(6,1) 1 format(' '// $ ' Victor N. Datsyuk'/ $ ' High Performance Computers Department'/ $ ' Rostov State University'/ $ ' Rostov-on-Don, phone 28-54-66'// $ ' email: root@rsusu1.rnd.runnet.ru'/ $ ' Internet: http://rsusu1.rnd.runnet.ru'/) write(6,2) 2 format(' '/ $ ' Aztec example driver'// $ ' This program create an MSR matrix corresponding to'/ $ ' a 7pt discrete approximation to the 3D Poisson operator'/ $ ' on an n x n x n square and solve it various methods.'/ $ ' n must be <= 50.'//) open(10, FILE='size.dat', FORM='FORMATTED') read(10,*) n endif c call AZ_broadcast(n,4,proc_config,AZ_PACK) c call AZ_broadcast(NULL,0,proc_config,AZ_SEND) c call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr) nz = n*n*n nzz = nz/NPROCS + 1 allocate( data_org(0:nzz) ) allocate( update(0:nzz) ) allocate( external(0:nzz) ) allocate( update_index(0:nzz) ) allocate( extern_index(0:nzz) ) allocate( bindx(0:nzz*7) ) allocate( b(0:nzz) ) allocate( x(0:nz) ) allocate( tmp(0:nzz) ) allocate( val(0:nzz*7) ) total = 0.0 DO 777 K = 0,4 if(k.eq.1) goto 777 time = MPI_Wtime() C C Define paritioning:matrix rows in ascending order assigned C to this node C call AZ_read_update(N_update,update,proc_config,nz,1,0) C C create the matrix: each processor creates only rows C appearing in update[] (using global col. numbers). C bindx(0) = N_update+1 do 250 i = 0, N_update-1 call add_row_7pt(update(i),i,val,bindx) 250 continue c c create the right hand side of the system under rule: c b(i) = sum(A(i,j)*j), asuming that x(i) = i ; c do 341 i = 0, N_update-1 in = bindx(i) ik = bindx(i+1) - 1 s = val(i)*(update(i)+1) c s = val(i) do 342 j = in,ik s = s + val(j)*(bindx(j)+1) c s = s + val(j) 342 continue tmp(i) = s 341 continue c C convert matrix to a local distributed matrix */ C call AZ_transform(proc_config,external,bindx,val,update, $ update_index,extern_index,data_org, $ N_update,NULL,NULL,NULL,NULL,AZ_MSR_MATRIX) C C initialize AZTEC options C call AZ_defaults(options, params) options(AZ_solver) = K c options(AZ_precond) = AZ_dom_decomp c options(AZ_subdomain_solve) = AZ_ilut options(4) = 1 options(AZ_output) = AZ_none options(AZ_max_iter) = 2000 params(AZ_tol) = 1.d-12 if (IAM.eq.0) then write(6,780) 780 format (16x,11(2H**)) write (6,*) ' Method solve is =',met(k) write(6,780) write (6,*) ' Dimension matrices =',nz, +' NPROCS = ', NPROCS endif C C Set rhs (delta function at grid center) and initialize guess C do 350 i = 0, N_update-1 x(update_index(i)) = 0.0 b(update_index(i)) = tmp(i) 350 continue C C solve the system of equations using b as the right hand side C call AZ_solve(x,b, options, params, NULL,bindx,NULL,NULL, $ NULL,val, data_org, status, proc_config) c DO 415 I = 0,N_update - 1 415 tmp(i) = x(update_index(i)) c c gather all parts of solve on all processors c CALL MPI_ALLgather(N_update,1,MPI_INTEGER,recb,1, *MPI_INTEGER,MPI_COMM_WORLD,ierror) CALL MPI_BARRIER(MPI_COMM_WORLD,ierror) DISP(0) = 0 DO 404 I = 1,NPROCS-1 404 DISP(I) = DISP(I-1) + RECB(I-1) CALL MPI_ALLgatherv(tmp,N_update,MPI_DOUBLE_PRECISION,x,recb, *disp,MPI_DOUBLE_PRECISION,MPI_COMM_WORLD,ierror) CALL MPI_BARRIER(MPI_COMM_WORLD,ierror) nz1 = nz-1 if (IAM.eq.0) then do 348 i = 0,nz1,nz1 s = x(i) write (6,956) i,s 348 continue 956 format (2x,'i=',I12,2x,'x(i)=',F18.8) endif time = MPI_Wtime() - time total = total + time if(iam.eq.0) write(*,435) time 435 FORMAT(2x,'TIME CALCULATION (SEC.) = ',F12.4) CALL FLUSH(6) 777 continue if(iam.eq.0) write(*,436) total 436 FORMAT(/,2x,' TOTAL TIME CALCULATION (SEC.) = ',F12.4) CALL MPI_FINALIZE(IERROR) stop end C********************************************************************* C********************************************************************* C subroutine add_row_7pt(row,location,val,bindx) C integer row,location,bindx(0:*) double precision val(0:*) integer n,n3 common /global/ n C C C Parameters: C row == global row number of the new row to be added. C location == local row where diagonal of the new row will be stored. C val,bindx == (see user's guide). On output, val[] and bindx[] C are appended such that the new row has been added. C integer k C C check neighbors in each direction and add nonzero if neighbor exits C n3 = n*n*n - 1 k = bindx(location) bindx(k) = row + 1 if (bindx(k).le.n3) then val(k) = -1. k = k + 1 endif bindx(k) = row - 1 if (bindx(k) .ge. 0) then val(k) = -1. k = k + 1 endif bindx(k) = row + n if (bindx(k).le.n3) then val(k) = -1. k = k + 1 endif bindx(k) = row - n if (bindx(k).ge. 0) then val(k) = -1. k = k + 1 endif bindx(k) = row + n*n if (bindx(k) .le. n3) then val(k) = -1. k = k + 1 endif bindx(k) = row - n*n if (bindx(k) .ge. 0) then val(k) = -1. k = k + 1 endif bindx(location+1) = k val(location) = 6.0 return end