DOUG 0.2

Distribution_struct.F90

Go to the documentation of this file.
00001 ! DOUG - Domain decomposition On Unstructured Grids
00002 ! Copyright (C) 1998-2006 Faculty of Computer Science, University of Tartu and
00003 ! Department of Mathematics, University of Bath
00004 !
00005 ! This library is free software; you can redistribute it and/or
00006 ! modify it under the terms of the GNU Lesser General Public
00007 ! License as published by the Free Software Foundation; either
00008 ! version 2.1 of the License, or (at your option) any later version.
00009 !
00010 ! This library is distributed in the hope that it will be useful,
00011 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 ! Lesser General Public License for more details.
00014 !
00015 ! You should have received a copy of the GNU Lesser General Public
00016 ! License along with this library; if not, write to the Free Software
00017 ! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 ! or contact the authors (University of Tartu, Faculty of Computer Science, Chair
00019 ! of Distributed Systems, Liivi 2, 50409 Tartu, Estonia, http://dougdevel.org,
00020 ! mailto:info(at)dougdevel.org)
00021 
00024 module Distribution_struct_mod
00025   use globals
00026   use Mesh_class
00027   use Distribution_base_mod
00028   use SpMtx_class
00029   use SpMtx_distribution_mod
00030 
00031   implicit none
00032   
00033 contains
00034 
00036   function Distribution_struct_NewInit(n,ol) result(D)
00037     type(Distribution) :: D
00038     integer,intent(in) :: n !< number of nodes along each axis, total n*n
00039     integer,intent(in) :: ol !< overlap to other process regions
00040 
00041     integer :: nrows !< number of sections along each axis
00042     integer,allocatable :: rowb(:) !< row bounds
00043     integer :: i,colblocks,irow,icol,ri,ci
00044     integer :: ri_s,ri_e,ci_s,ci_e,nnodes,nnz,mri
00045 
00046     if (sctls%verbose>=1) write(stream,*) "INFO: Build structured distribution"
00047 
00048     D = Distribution_New()
00049     call Mesh_Init(D%mesh, nell=n*n, ngf=n*n, nsd=-2, mfrelt=-3, nnode=n*n)
00050     D%mesh%parted  = .true.
00051     D%mesh%nparts  = numprocs
00052     
00053     ! number of rows
00054     nrows = ceiling(sqrt(real(numprocs)))
00055     
00056     ! row bounds, ie number of blocks in each row (index base 0)
00057     allocate(rowb(nrows+1))
00058     do i=1,nrows+1
00059       rowb(i) = (i-1)*numprocs/nrows
00060     end do
00061 
00062     ! load-balance the rows proportionally to the number of blocks in the row
00063     allocate(D%mesh%eptnmap(n*n))
00064     do i=1,numprocs
00065       irow = (i-1)*nrows/numprocs + 1
00066       colblocks = rowb(irow+1)-rowb(irow) 
00067       icol = (i-1)-rowb(irow) + 1
00068       if (sctls%verbose>=3) then
00069          write(stream,('(A,I0,A,I0,"-",I0,", ",I0,"-",I0)')) &
00070               "Block (process) ",i," rows and columns: ", &
00071               rowb(irow)*n/numprocs+1, rowb(irow+1)*n/numprocs, &
00072               (n*(icol-1)/colblocks)+1, n*icol/colblocks
00073       end if
00074 
00075       ! mark nodes of each block
00076       ri_s = rowb(irow)*n/numprocs+1
00077       ri_e = rowb(irow+1)*n/numprocs
00078       ci_s = (n*(icol-1)/colblocks)+1
00079       ci_e = n*icol/colblocks
00080       do ri = ri_s,ri_e
00081         do ci = ci_s,ci_e
00082           D%mesh%eptnmap((ri-1)*n+ci) = i
00083         end do
00084       end do
00085     end do
00086 
00087     ! generate local matrix with 2*ol expansion
00088     i = myrank+1
00089     irow = (i-1)*nrows/numprocs + 1
00090     colblocks = rowb(irow+1)-rowb(irow) 
00091     icol = (i-1)-rowb(irow) + 1
00092     ri_s = rowb(irow)*n/numprocs+1
00093     ri_e = rowb(irow+1)*n/numprocs
00094     ci_s = (n*(icol-1)/colblocks)+1
00095     ci_e = n*icol/colblocks
00096     ri_s = max(1,ri_s-max(1,2*ol))
00097     ri_e = min(n,ri_e+max(1,2*ol))
00098     ci_s = max(1,ci_s-max(1,2*ol))
00099     ci_e = min(n,ci_e+max(1,2*ol))
00100     nnodes = (ri_e-ri_s+1)*(ci_e-ci_s+1)
00101     nnz = 5*nnodes-2*((ri_e-ri_s+1)+(ci_e-ci_s+1))
00102     D%A = SpMtx_NewInit(nnz,nrows=n*n,ncols=n*n) ! specify nrows/ncols, otherwise arrange later fails
00103     nnz = 0
00104     do ri = ri_s,ri_e
00105       do ci = ci_s,ci_e
00106         mri = (ri-1)*n+ci ! matrix row index
00107         ! diagonal
00108         nnz = nnz+1
00109         D%A%indi(nnz) = mri
00110         D%A%indj(nnz) = mri
00111         D%A%val(nnz) = 4
00112         ! left
00113         if (ci>ci_s) then
00114           nnz = nnz+1
00115           D%A%indi(nnz) = mri
00116           D%A%indj(nnz) = mri-1
00117           D%A%val(nnz) = -1
00118         end if
00119         ! right
00120         if (ci<ci_e) then
00121           nnz = nnz+1
00122           D%A%indi(nnz) = mri
00123           D%A%indj(nnz) = mri+1
00124           D%A%val(nnz) = -1
00125         end if
00126         ! up
00127         if (ri>ri_s) then
00128           nnz = nnz+1
00129           D%A%indi(nnz) = mri
00130           D%A%indj(nnz) = mri-n
00131           D%A%val(nnz) = -1
00132         end if
00133         ! down
00134         if (ri<ri_e) then
00135           nnz = nnz+1
00136           D%A%indi(nnz) = mri
00137           D%A%indj(nnz) = mri+n
00138           D%A%val(nnz) = -1
00139         end if
00140       end do
00141     end do
00142 
00143     ! localize matrix
00144     allocate(D%rhs(n*n))
00145     D%rhs = -1
00146     call SpMtx_arrange(D%A, D_SpMtx_ARRNG_ROWS)
00147     call SpMtx_localize(D%A,D%A_ghost,D%rhs,D%mesh)
00148   end function Distribution_struct_NewInit
00149 end module Distribution_struct_mod