function [ ml, mu, m ] =  bandwidth_var ( element_order, element_num, ...
  element_node, node_num, var_node, var_num, var )

%*****************************************************************************80
%
%% bandwidth_var() determines the bandwidth for finite element variables.
%
%  Discussion:
%
%    We assume that, attached to each node in the finite element mesh
%    there are a (possibly zero) number of finite element variables.
%    We wish to determine the bandwidth necessary to store the stiffness
%    matrix associated with these variables.
%
%    An entry K(I,J) of the stiffness matrix must be zero unless the
%    variables I and J correspond to nodes N(I) and N(J) which are
%    common to some element.
%
%    In order to determine the bandwidth of the stiffness matrix, we
%    essentially seek a nonzero entry K(I,J) for which abs ( I - J )
%    is maximized.
%
%    The bandwidth M is defined in terms of the lower and upper bandwidths:
%
%      M = ML + 1 + MU
%
%    where
%
%      ML = maximum distance from any diagonal entry to a nonzero
%      entry in the same row, but earlier column,
%
%      MU = maximum distance from any diagonal entry to a nonzero
%      entry in the same row, but later column.
%
%    We assume the finite element variable adjacency relationship is
%    symmetric, so we are guaranteed that ML = MU.
%
%    Note that the user is free to number the variables in any way
%    whatsoever, and to associate variables to nodes in any way,
%    so that some nodes have no variables, some have one, and some
%    have several.
%
%    The storage of the indices of the variables is fairly simple.
%    In VAR, simply list all the variables associated with node 1,
%    then all those associated with node 2, and so on.  Then set up
%    the pointer array VAR_NODE so that we can jump to the section of
%    VAR where the list begins for any particular node.
%
%    The routine does not check that each variable is only associated
%    with a single node.  This would normally be the case in a finite
%    element setting.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    03 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    integer ELEMENT_ORDER, the order of the elements.
%
%    integer ELEMENT_NUM, the number of elements.
%
%    integer ELEMENT_NODE(ELEMENT_ORDER,ELEMENT_NUM);
%    ELEMENT_NODE(I,J) is the global index of local node I in element J.
%
%    integer NODE_NUM, the number of nodes.
%
%    integer VAR_NODE(NODE_NUM+1), used to find the variables
%    associated with a given node, which are in VAR in locations
%    VAR_NODE(NODE) to VAR_NODE(NODE+1)-1.  Note that the last entry of
%    this array points to the location just after the last location in VAR.
%
%    integer VAR_NUM, the number of variables.
%
%    integer VAR(VAR_NUM), the indexes of the variables, which
%    are presumably (but not necessarily) 1, 2, 3, ..., VAR_NUM.
%
%  Output:
%
%    integer ML, MU, the lower and upper bandwidths of the matrix.
%
%    integer M, the bandwidth of the matrix.
%
  ml = 0;
  mu = 0;

  for element = 1 : element_num

    for node_local_i = 1 : element_order
      node_global_i = element_node(node_local_i,element);

      for var_local_i = var_node(node_global_i) : var_node(node_global_i+1)-1
        var_global_i = var(var_local_i);

        for node_local_j = 1 : element_order
          node_global_j = element_node(node_local_j,element);

          for var_local_j = var_node(node_global_j) : var_node(node_global_j+1)-1
            var_global_j = var(var_local_j);

            mu = max ( mu, var_global_j - var_global_i );
            ml = max ( ml, var_global_i - var_global_j );

          end
        end
      end
    end
  end

  m = ml + 1 + mu;

  return
end
