/*
 $Id: connect.cc,v 1.2 1996/10/04 15:06:25 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

#include "connect.h"

#include "int.h"
#include "triang.h"
#include "elements.h"

#include "cmdpars.h"
extern CmdPars Cmd;

//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


		// regular routines for full pattern


ConnectionPattern:: ConnectionPattern(MESH& mesh, const Element& element, 
				      const Interface& interface, int noOfNodes)

	: connVec(noOfNodes), allocator(noOfNodes)
{
    PATCH* elem;

    setConnectionVector();

    Vector<int> nodes(element.NoOfNodes());

    mesh.resetElemIter();
    while ((elem = mesh.elemIterAll()))
    {
	interface.getGlobalNodes(elem, nodes);  
	insert(nodes);
    }    

    if (Cmd.isTrue("printConnectionPattern")) print();
}
//-------------------------------------------------------------------------

ConnectionPattern:: ConnectionPattern(int lowNode, int highNode)

	: connVec(lowNode,highNode), allocator(highNode-lowNode+10)
{ 
    setConnectionVector();
}
//-------------------------------------------------------------------------

void ConnectionPattern:: setConnectionVector()
{
    int i, low, high;

    low  = connVec.low();
    high = connVec.high();

    sListVec = new SList<NeighbourNode>[high-low+1];
    assert(sListVec);
    FORALL(connVec,i) connVec[i] = &sListVec[i-low];
}
//-------------------------------------------------------------------------

ConnectionPattern:: ~ConnectionPattern()  { delete sListVec; }

//-------------------------------------------------------------------------

void ConnectionPattern:: print()
{
    int i;
    cout << "\nConnectionPattern: \n";
    FORALL (connVec,i) 
    {
	cout << i << ":  ";
	connVec[i]->print();
	cout << "\n";
    }
}
//-------------------------------------------------------------------------

void ConnectionPattern:: print(Vector<int>& keep)
{
    int i;

    cout << "\nCompressed ConnectionPattern: \n";

    Vector<int> index(connVec.l,connVec.h);
    NeighbourNode* np;
    
    int newNo = 0;
    FORALL(keep,i)  if (keep[i])  index[++newNo] = i;

    FORALL (connVec,i)
    {
	cout << "(" << i << ") " << index[i] << ":  ";
	for (np=connVec[i]->first; np; np=np->next) 
	cout << " " << index[np->neighbour];
	cout << "\n";
    }
}
//-------------------------------------------------------------------------

int ConnectionPattern:: size() const { return connVec.size(); }
int ConnectionPattern:: l()    const { return connVec.l; }
int ConnectionPattern:: h()    const { return connVec.h; }

int ConnectionPattern:: noOfElements(int row) const
				{ return connVec[row]->noOfElements; }

NeighbourNode* ConnectionPattern:: first(int row) const
				{ return connVec[row]->first; }

//-------------------------------------------------------------------------


void ConnectionPattern:: insert(Vector<int>& node) 
{
    int i, j;
    NeighbourNode testNode;
    
    for (i=1; i<=node.h; ++i)
    {
	if (node[i] == 0) continue;

	for (j=1; j<=node.h; ++j) 
	{
	    if (node[j] == 0) continue;
	    if (node[j] >= node[i]) continue;  // only lower triangle desired
	    
	    testNode.neighbour = node[j];

	    if (!connVec[node[i]]->inList(&testNode))  
	    {
		NeighbourNode* newNode = allocator.Get();   // new NeighbourNode;
		newNode->neighbour = node[j];

		connVec[node[i]]->insert(newNode);
	    }
	}
    }
}
//-------------------------------------------------------------------------


int ConnectionPattern:: bandwidth() const
{
    int i, bwRow;
    NeighbourNode* nnp;

    int bw = 0;

    FORALL(connVec,i) 
      for (nnp=connVec[i]->first; nnp; nnp=nnp->next) 
      {
	  bwRow = i - nnp->neighbour;		// i > neighbour is ensured
	  if (bwRow > bw) bw = bwRow;
      }
    
    return bw;
}
