ITM Grid Service Library: Fortran 90

src/service/itm_grid_simplex_dict.f90

Go to the documentation of this file.
00001 module itm_grid_simplex_dict
00002 
00003   !> A dictionary module for simplexes
00004 
00005   use itm_types , ITM_R8 => R8
00006   use itm_assert
00007   use itm_combinations
00008 
00009   use itm_grid_common
00010   use itm_grid_object
00011   use itm_grid_access
00012   use itm_grid_subgrid
00013 
00014   implicit none
00015 
00016   ! A dictionary structure mapping from a node to the simplexes this node is part of.
00017   ! A simplex is stored for the node that is part of the simplex and has the smallest index.
00018   type SimplexDict
00019       ! Dimension of the simplexes in this dictionary. 0 = nodes, 1 = edges, 2 = triangles, 3 = tetraeder
00020       ! Every dim-simplex then has dim+1 nodes
00021       integer :: dim
00022       ! Store for every node the simplexes this node is part of as ordered lists of nodes, with
00023       ! the node itself omitted. For each node, the simplexes are stored in no particular order.
00024       ! Dims: 1=node index, 2=local simplex index, 3=indices of other nodes in simplex, ordered
00025       ! Size: 1:#nodes, 2:#max simpl./node, 3:dim-1
00026       integer, allocatable :: sxDict(:,:,:)
00027       ! Global index of the simplices. If simplex slot j for node i is unused, sxInd(i,j) = GRID_UNDEFINED
00028       ! Dims: 1=node index, 2=local simplex index
00029       ! Size: 1:#nodes, 2:#max simpl./node
00030       integer, allocatable :: sxInd(:,:)      
00031       ! Number of simplexes stored for node i
00032       integer, allocatable :: sxNum(:)
00033   end type SimplexDict
00034 
00035   type simplexDictIterator
00036       integer :: iNode, iSim
00037   end type simplexDictIterator
00038 
00039 contains
00040   
00041   subroutine createSimplexDict( dict, dim, nNodes, nMaxParents )
00042     type(SimplexDict), intent(out) :: dict
00043     integer, intent(in) :: dim, nNodes, nMaxParents
00044     
00045     ! internal
00046     dict%dim = dim
00047     allocate(dict%sxDict(nNodes, nMaxParents, dim))
00048     allocate(dict%sxInd(nNodes, nMaxParents))
00049     allocate(dict%sxNum(nNodes))
00050     dict%sxDict = GRID_UNDEFINED
00051     dict%sxInd = GRID_UNDEFINED
00052     dict%sxNum = GRID_UNDEFINED
00053   end subroutine createSimplexDict
00054 
00055   integer function countSimplexes( dict )
00056     type(SimplexDict), intent(in) :: dict
00057     
00058     countSimplexes = sum(dict%sxNum)
00059   end function countSimplexes
00060 
00061   function sortSimplex(simplex)
00062     use m_inssor
00063     integer, intent(in) :: simplex(:)
00064     integer :: sortSimplex(size(simplex))
00065 
00066     sortSimplex = simplex
00067     call inssor(sortSimplex)      
00068   end function sortSimplex
00069 
00070   subroutine insertSimplex( dict, simplex )
00071     type(SimplexDict), intent(inout) :: dict
00072     integer, intent(in) :: simplex(:)
00073 
00074     ! internal
00075     integer :: index, node
00076 
00077     call assert(size(simplex) == dict%dim + 1)
00078 
00079     if (size(simplex) == 1) then
00080         dict%sxNum(simplex(1)) = 1
00081         return
00082     end if
00083 
00084     index = simplexIndex( dict, simplex )
00085 
00086     if ( index == GRID_UNDEFINED ) then
00087         ! Store in dictionary for lowest node
00088         node = simplex(1)
00089         ! We have one more simplex for that node
00090         dict%sxNum(node) = dict%sxNum(node) + 1
00091         if ( dict%sxNum(node) > size(dict%sxDict, 2)) &
00092             & stop "insertSimplex: dictionary overflow"
00093 
00094         ! Put new simplex in dictionary (omitting redundant first node)
00095         dict%sxDict( node, dict%sxNum(node), 1:dict%dim) = simplex(2:dict%dim + 1)
00096         ! Set global index for new simplex
00097         dict%sxInd( node, dict%sxNum(node) ) = dict%sxInd( node, dict%sxNum(node) ) + 1
00098         ! Increase global indices of all simplexes further up the array
00099         dict%sxInd( node, dict%sxNum(node)+1:size(dict%sxInd,2) ) = dict%sxInd( node, dict%sxNum(node)+1:size(dict%sxNum,1) ) + 1
00100         dict%sxInd( node + 1:size(dict%sxInd, 1), :) = dict%sxInd( node + 1:size(dict%sxInd, 1), :) + 1
00101     end if
00102 
00103   end subroutine insertSimplex
00104 
00105   subroutine resetIterator( iterator )
00106     type(SimplexDictIterator), intent(inout) :: iterator
00107 
00108     iterator%iNode = 1
00109     iterator%iSim = 0        
00110   end subroutine resetIterator
00111   
00112   subroutine nextSimplex( dict, iter, simplex )
00113     type(SimplexDict), intent(in) :: dict
00114     type(SimplexDictIterator), intent(inout) :: iter
00115     integer, dimension(dict%dim + 1), intent(out) :: simplex
00116        
00117     ! internal
00118     integer :: inode, isim
00119 
00120     inode = iter%inode
00121     isim = iter%isim
00122 
00123     ! increase index
00124     do
00125         isim = isim + 1
00126         if (isim > dict%sxNum(inode)) then
00127             inode = inode + 1
00128             isim = 0
00129         else
00130             simplex(1) = inode
00131             simplex(2:dict%dim + 1) = dict%sxDict(inode, isim, :)
00132             exit
00133         end if
00134         if (inode > size(dict%sxNum)) then
00135             simplex = GRID_UNDEFINED
00136             inode = size(dict%sxNum)
00137             exit
00138         end if
00139     end do
00140     
00141     iter%inode = inode
00142     iter%isim = isim
00143   end subroutine nextSimplex
00144 
00145   logical function simplexUndefined(simplex)
00146     integer, intent(in) :: simplex(:)
00147 
00148     simplexUndefined = (simplex(1) == GRID_UNDEFINED)
00149   end function simplexUndefined
00150  
00151   !> Get global index of given sorted simplex
00152   integer function simplexIndex( dict, simplex )
00153     type(SimplexDict), intent(in) :: dict
00154     integer, intent(in) :: simplex(:)
00155     !logical, intent(in), optional :: sorted
00156     
00157     ! internal
00158     integer :: s
00159 
00160     ! Special case for 0-simplex
00161     if (size(simplex) == 1) then
00162         simplexIndex = simplex(1)
00163         return
00164     end if
00165 
00166     do s = 1, dict%sxNum(simplex(1))
00167         if ( all( simplex(2:dict%dim+1) == dict%sxDict(simplex(1), s, 1:dict%dim)) ) then
00168             simplexIndex = dict%sxInd(simplex(1), s)
00169             return
00170         end if
00171     end do
00172 
00173     simplexIndex = GRID_UNDEFINED
00174   end function simplexIndex
00175 
00176 
00177   function listChildren(simplex) result( children )
00178     integer, intent(in) :: simplex(:)
00179     integer :: children(size(simplex), max(size(simplex)-1, 1))
00180     
00181     ! internal
00182     integer :: i, n
00183 
00184     n = size(simplex)
00185     
00186     ! Special case: 1-dimensional simplex has only itself as child
00187     if (n==1) then
00188         children(1,1) = simplex(1)
00189         return
00190     end if
00191 
00192     ! leave out node -iChild
00193     do i = 1, n
00194         if (i /= n) children(i,1:n-i) = simplex(1:n-i)
00195         if (i /= 1) children(i,n-i+1:n-1) = simplex(n-i+2:n)
00196     end do
00197 
00198   end function listChildren    
00199   
00200 end module itm_grid_simplex_dict
 All Classes Namespaces Files Functions Variables