📄 rcm.f90
字号:
do lbegin = lvlend + 1 lvlend = iccsze level_num = level_num + 1 level_row(level_num) = lbegin!! Generate the next level by finding all the masked neighbors of nodes! in the current level.! do i = lbegin, lvlend node = level(i) jstrt = adj_row(node) jstop = adj_row(node+1)-1 do j = jstrt, jstop nbr = adj(j) if ( mask(nbr) /= 0 ) then iccsze = iccsze + 1 level(iccsze) = nbr mask(nbr) = 0 end if end do end do!! Compute the current level width (the number of nodes encountered.)! If it is positive, generate the next level.! lvsize = iccsze - lvlend if ( lvsize <= 0 ) then exit end if end do level_row(level_num+1) = lvlend + 1!! Reset MASK to 1 for the nodes in the level structure.! mask(level(1:iccsze)) = 1 returnend subroutine level_set subroutine perm_inverse ( n, perm, perm_inv )!*******************************************************************************!!! PERM_INVERSE produces the inverse of a given permutation.!! Modified:!! 28 October 2003!! Author:!! John Burkardt!! Parameters:!! Input, integer N, the number of items permuted.!! Input, integer PERM(N), a permutation.!! Output, integer PERM_INV(N), the inverse permutation.! implicit none integer n integer i integer perm(n) integer perm_inv(n) do i = 1, n perm_inv(perm(i)) = i end do returnend subroutine perm_inverse subroutine rcm ( root, adj_num, adj_row, adj, mask, perm, iccsze, node_num )!*******************************************************************************!!! RCM renumbers a connected component by the reverse Cuthill McKee algorithm.!! Discussion:!! The connected component is specified by a node ROOT and a mask.! The numbering starts at the root node.!! An outline of the algorithm is as follows:!! X(1) = ROOT.!! for ( I = 1 to N-1)! Find all unlabeled neighbors of X(I),! assign them the next available labels, in order of increasing degree.!! When done, reverse the ordering.!! Reference:!! Alan George and J W Liu,! Computer Solution of Large Sparse Positive Definite Systems,! Prentice Hall, 1981.!! Parameters:!! Input, integer ROOT, the node that defines the connected component.! It is used as the starting point for the RCM ordering.!! Input, integer ADJ_NUM, the number of adjacency entries.!! Input, integer ADJ_ROW(NODE_NUM+1). Information about row I is stored! in entries ADJ_ROW(I) through ADJ_ROW(I+1)-1 of ADJ.!! Input, integer ADJ(ADJ_NUM), the adjacency structure.! For each row, it contains the column indices of the nonzero entries.!! Input/output, integer MASK(NODE_NUM), a mask for the nodes. Only ! those nodes with nonzero input mask values are considered by the ! routine. The nodes numbered by RCM will have their mask values ! set to zero.!! Output, integer PERM(NODE_NUM), the RCM ordering.!! Output, integer ICCSZE, the size of the connected component! that has been numbered.!! Input, integer NODE_NUM, the number of nodes.!! Local parameters:!! Workspace, integer DEG(NODE_NUM), a temporary vector used to hold ! the degree of the nodes in the section graph specified by mask and root.! implicit none integer adj_num integer node_num integer adj(adj_num) integer adj_row(node_num+1) integer deg(node_num) integer fnbr integer i integer iccsze integer j integer jstop integer jstrt integer k integer l integer lbegin integer lnbr integer lperm integer lvlend integer mask(node_num) integer nbr integer node integer perm(node_num) integer root!! Find the degrees of the nodes in the component specified by MASK and ROOT.! call degree ( root, adj_num, adj_row, adj, mask, deg, iccsze, perm, node_num ) mask(root) = 0 if ( iccsze <= 1 ) then return end if lvlend = 0 lnbr = 1!! LBEGIN and LVLEND point to the beginning and! the end of the current level respectively.! do while ( lvlend < lnbr ) lbegin = lvlend + 1 lvlend = lnbr do i = lbegin, lvlend!! For each node in the current level...! node = perm(i) jstrt = adj_row(node) jstop = adj_row(node+1) - 1!! Find the unnumbered neighbors of NODE.!! FNBR and LNBR point to the first and last neighbors! of the current node in PERM.! fnbr = lnbr + 1 do j = jstrt, jstop nbr = adj(j) if ( mask(nbr) /= 0 ) then lnbr = lnbr + 1 mask(nbr) = 0 perm(lnbr) = nbr end if end do!! If no neighbors, skip to next node in this level.! if ( lnbr <= fnbr ) then cycle end if!! Sort the neighbors of NODE in increasing order by degree.! Linear insertion is used.! k = fnbr do while ( k < lnbr ) l = k k = k + 1 nbr = perm(k) do while ( fnbr < l ) lperm = perm(l) if ( deg(lperm) <= deg(nbr) ) then exit end if perm(l+1) = lperm l = l-1 end do perm(l+1) = nbr end do end do end do!! We now have the Cuthill-McKee ordering. Reverse it.! call ivec_reverse ( iccsze, perm ) returnend subroutine rcm subroutine root_find ( root, adj_num, adj_row, adj, mask, level_num, & level_row, level, node_num )!*******************************************************************************!!! ROOT_FIND finds a pseudo-peripheral node.!! Discussion:!! The diameter of a graph is the maximum distance (number of edges)! between any two nodes of the graph.!! The eccentricity of a node is the maximum distance between that! node and any other node of the graph.!! A peripheral node is a node whose eccentricity equals the! diameter of the graph.!! A pseudo-peripheral node is an approximation to a peripheral node;! it may be a peripheral node, but all we know is that we tried our! best.!! The routine is given a graph, and seeks pseudo-peripheral nodes,! using a modified version of the scheme of Gibbs, Poole and! Stockmeyer. It determines such a node for the section subgraph! specified by MASK and ROOT.!! The routine also determines the level structure associated with! the given pseudo-peripheral node; that is, how far each node! is from the pseudo-peripheral node. The level structure is! returned as a list of nodes LS, and pointers to the beginning! of the list of nodes that are at a distance of 0, 1, 2, ...,! NODE_NUM-1 from the pseudo-peripheral node.!! Modified:!! 28 October 2003!! Reference:!! Alan George and J W Liu,! Computer Solution of Large Sparse Positive Definite Systems,! Prentice Hall, 1981.!! Gibbs, Poole, Stockmeyer,! An Algorithm for Reducing the Bandwidth and Profile of a Sparse Matrix,! SIAM Journal on Numerical Analysis,! Volume 13, pages 236-250, 1976.!! Gibbs,! Algorithm 509: A Hybrid Profile Reduction Algorithm,! ACM Transactions on Mathematical Software,! Volume 2, pages 378-387, 1976.!! Parameters:!! Input/output, integer ROOT. On input, ROOT is a node in the! the component of the graph for which a pseudo-peripheral node is! sought. On output, ROOT is the pseudo-peripheral node obtained.!! Input, integer ADJ_NUM, the number of adjacency entries.!! Input, integer ADJ_ROW(NODE_NUM+1). Information about row I is stored! in entries ADJ_ROW(I) through ADJ_ROW(I+1)-1 of ADJ.!! Input, integer ADJ(ADJ_NUM), the adjacency structure.! For each row, it contains the column indices of the nonzero entries.!! Input, integer MASK(NODE_NUM), specifies a section subgraph. Nodes ! for which MASK is zero are ignored by FNROOT.!! Output, integer LEVEL_NUM, is the number of levels in the level structure! rooted at the node ROOT.!! Output, integer LEVEL_ROW(NODE_NUM+1), integer LEVEL(NODE_NUM), the ! level structure array pair containing the level structure found.!! Input, integer NODE_NUM, the number of nodes.! implicit none integer adj_num integer node_num integer adj(adj_num) integer adj_row(node_num+1) integer iccsze integer j integer jstrt integer k integer kstop integer kstrt integer level(node_num) integer level_num integer level_num2 integer level_row(node_num+1) integer mask(node_num) integer mindeg integer nabor integer ndeg integer node integer root!! Determine the level structure rooted at ROOT.! call level_set ( root, adj_num, adj_row, adj, mask, level_num, & level_row, level, node_num )!! Count the number of nodes in this level structure.! iccsze = level_row(level_num+1) - 1!! Extreme case:! A complete graph has a level set of only a single level.! Every node is equally good (or bad).! if ( level_num == 1 ) then return end if!! Extreme case:! A "line graph" 0--0--0--0--0 has every node in its only level.! By chance, we've stumbled on the ideal root.! if ( level_num == iccsze ) then return end if!! Pick any node from the last level that has minimum degree! as the starting point to generate a new level set.! do mindeg = iccsze jstrt = level_row(level_num) root = level(jstrt) if ( jstrt < iccsze ) then do j = jstrt, iccsze node = level(j) ndeg = 0 kstrt = adj_row(node) kstop = adj_row(node+1)-1 do k = kstrt, kstop nabor = adj(k) if ( 0 < mask(nabor) ) then ndeg = ndeg+1 end if end do if ( ndeg < mindeg ) then root = node mindeg = ndeg end if end do end if!! Generate the rooted level structure associated with this node.! call level_set ( root, adj_num, adj_row, adj, mask, level_num2, & level_row, level, node_num )!! If the number of levels did not increase, accept the new ROOT.! if ( level_num2 <= level_num ) then exit end if level_num = level_num2!! In the unlikely case that ROOT is one endpoint of a line graph,! we can exit now.! if ( iccsze <= level_num ) then exit end if end do returnend subroutine root_find end module rcmlib
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -