Example #1
0
void 
Mesh3DSubdomain::allocate_e_Nodes(double xMin, double xMax, 
				  double yMin, double yMax,
				  double zMin, double zMax,
				  std::map<int,int>& eNodes)
{
  Vertex *theVertex;
  double xCoord, yCoord, zCoord;
  Graph  & nodeGraph = this->myDomain->getNodeGraph();
  VertexIter  & theVertices = nodeGraph.getVertices();
  int count = 0;
  bool enode_found = false;
  while ((theVertex = theVertices() ) != 0) {
    int tag = theVertex->getRef();

    const Vector & coords = this->myDomain->getNode(tag)->getCrds();
    
    xCoord = coords(0);
    yCoord = coords(1);
    zCoord = coords(2);
    
    if ( ((xCoord == xMin) || (xCoord == xMax)) &&
	 (yCoord >= yMin) && (yCoord<=yMax) &&
	 (zCoord >= zMin) && (zCoord<=zMax)) 
      {
	enode_found = true;
      }

    if ( ((yCoord == yMin) || (yCoord == yMax)) &&
	 (xCoord >= xMin) && (xCoord<=xMax) &&
	 (zCoord >= zMin) && (zCoord<=zMax)) 
      {
	enode_found = true;
      }

    if ( ((zCoord == zMin)) && 
	 (((xCoord >= xMin) && (xCoord<=xMax)) &&
	  ((yCoord >= yMin) && (yCoord<=yMax)) ))
      {
	enode_found = true;
      }
    if ((zCoord == zMax) &&
	((xCoord == xMin) || (xCoord ==xMax)) &&
	((yCoord >= yMin) && (yCoord <= yMax)))
      { 
	enode_found = true;
      }
    if ((zCoord == zMax) &&
	((yCoord == yMin) || (yCoord==yMax)) &&
	((xCoord >= xMin) && (xCoord <= xMax)))
      {
	enode_found = true;
      }
    if (enode_found) {
      eNodes[tag] = count;
      count++;
      enode_found = false;
    }
  }
}
Example #2
0
File: Graph.cpp Project: lcpt/xc
//! @brief Returns the extreme (positive or negative) of the difference between vertices indexes.
int XC::Graph::getVertexDiffExtrema(void) const
  {
    int retval = 0;
  
    const Vertex *vertexPtr= nullptr;
    Graph *this_no_const= const_cast<Graph *>(this);
    VertexIter &theVertices = this_no_const->getVertices();
  
    while((vertexPtr = theVertices()) != 0)
      {
        int vertexNum = vertexPtr->getTag();
        const std::set<int> &theAdjacency= vertexPtr->getAdjacency();
        for(std::set<int>::const_iterator i= theAdjacency.begin(); i!= theAdjacency.end(); i++)
          {
            const int otherNum= *i;
            const int diff = vertexNum - otherNum;
            if(diff > 0)
              {
	        if(diff > retval)
	          retval = diff;
              }
            else 
	      if(diff < -retval)
	        retval = -diff;
          }
      }
    return retval;
  }
Example #3
0
void
Mesh3DSubdomain::allocateBoundaryLayerElements(double xMin, double xMax,
					       double yMin, double yMax,
					       double zMin, double zMax,
					       std::map<int,Element*>& elements,
					       std::map<int,Vector*>& storage,
					       std::map<int,int>& storage2)
{
  Vertex* theVertex;
//  int count =0;
//  bool ele_found = false;
  GeometricBrickDecorator* myHelper = new GeometricBrickDecorator();
  myHelper->setDomain(this->myDomain);
  Graph& eleGraph = this->myDomain->getElementGraph();
  VertexIter& theVertices = eleGraph.getVertices();
  while ((theVertex = theVertices() ) != 0) {
    int tag = theVertex->getRef();
    Element* ele = this->myDomain->getElement(tag);
    if ((ele->getClassTag() == ELE_TAG_EightNode_Brick_u_p) || (ele->getClassTag() == ELE_TAG_Brick) || (ele->getClassTag() == ELE_TAG_FLBrick) ) {
      myHelper->setBrick(ele);
      if ( myHelper->isBoundaryLayerEle(xMin, xMax, yMin, yMax, zMin, zMax) ) {
	Vector* ptr = new Vector(24);
	ptr->Zero();
	storage[tag] = ptr; 
	storage2[tag] = -1;
	elements[tag] = ele;
      }
    }
  }
  delete myHelper;
}
Example #4
0
File: Graph.cpp Project: lcpt/xc
//! @brief Returns the extremos del ancho de banda.
void XC::Graph::getBand(int &numSubD,int &numSuperD) const
  {
    numSubD = 0;
    numSuperD = 0;
    Vertex *vertexPtr;
    Graph *this_no_const= const_cast<Graph *>(this);
    VertexIter &theVertices= this_no_const->getVertices();
    
    while((vertexPtr = theVertices()) != 0)
      {
        const int vertexNum= vertexPtr->getTag();
        const std::set<int> &theAdjacency= vertexPtr->getAdjacency();
        for(std::set<int>::const_iterator i= theAdjacency.begin(); i!= theAdjacency.end(); i++)
          {
            const int otherNum= *i;
            const int diff= vertexNum - otherNum;
	    if(diff > 0)
              {
                if(diff > numSuperD)
                  numSuperD = diff;
	      }
            else 
              if(diff < numSubD)
	        numSubD = diff;
          }
      }
    numSubD*= -1;
  }
Example #5
0
void Optimize::computeEF(const int i, const Ipopt::Number *x, double *e, double *f)
{
    const double *p = prevVertices(i, x);
    const double *c = theVertices(i, x);
    const double *n = nextVertices(i, x);
    sub(c, p, e);
    sub(n, c, f);
}
int
SwapHeavierToLighterNeighbours::balance(Graph &theWeightedGraph)
{
    // check to see a domain partitioner has been set
    DomainPartitioner *thePartitioner = this->getDomainPartitioner();
    if (thePartitioner == 0) {
	opserr << "SwapHeavierToLighterNeighbours::balance";
	opserr << "- No DomainPartitioner has been set\n"; 
	return -1;
    }

    int res = 0;

    for (int ii=0; ii<numReleases; ii++) {
	VertexIter &theVertices = theWeightedGraph.getVertices();
	Vertex *vertexPtr;
	while ((vertexPtr = theVertices()) != 0) {
	    int vertexTag = vertexPtr->getTag();
	    double vertexLoad = vertexPtr->getWeight();
	    const ID &adjacency = vertexPtr->getAdjacency();
	    int size = adjacency.Size();
	    for (int j=0; j<size; j++) {
		int otherVertexTag = adjacency(j);
		Vertex *otherVertexPtr 
		    = theWeightedGraph.getVertexPtr(otherVertexTag);
		double otherVertexLoad = otherVertexPtr->getWeight();
		
		if (vertexLoad > otherVertexLoad && otherVertexLoad != 0) 
		    if (vertexLoad/otherVertexLoad > factorGreater) {
			res = thePartitioner->
			    swapBoundary(vertexTag,otherVertexTag);
			if (res < 0) {
			    opserr << "WARNING SwapHeavierToLighterNeighbours";
			    opserr << "::balance - DomainPartitioner returned ";
			    opserr << res << endln;
			    return res;
			}
		    }
		
		if (vertexLoad != 0 && otherVertexLoad == 0)  {
		    res = thePartitioner->
			swapBoundary(vertexTag,otherVertexTag); 
		    if (res < 0) {
			opserr << "WARNING SwapHeavierToLighterNeighbours";
			opserr << "::balance - DomainPartitioner returned ";
			opserr << res << endln;
			return res;
		    }
		}
	    }		
	}
    }


    return res;

}
Example #7
0
int
ShedHeaviest::balance(Graph &theWeightedGraph)
{
    // check to see a domain partitioner has been set
    DomainPartitioner *thePartitioner = this->getDomainPartitioner();
    if (thePartitioner == 0) {
	opserr << "ShedHeaviest::balance - No DomainPartitioner has been set\n";
	return -1;
    }

    // determine the max loaded partition
    VertexIter &theVertices = theWeightedGraph.getVertices();
    Vertex *vertexPtr = theVertices();
    int maxPartition = vertexPtr->getTag();
    double maxLoad = vertexPtr->getWeight();
    while ((vertexPtr = theVertices()) != 0)
	if (vertexPtr->getWeight() > maxLoad) {
	    maxLoad = vertexPtr->getWeight();
	    maxPartition = vertexPtr->getTag();
	}
    
    // release the boundary numReleases times
    int res = 0;
    for (int j=0; j<numReleases; j++) {
	res = thePartitioner->
	    releaseBoundary(maxPartition,theWeightedGraph,
			    true,factorGreater);  
	
	if (res < 0) {
	    opserr << "WARNING ShedHeaviest::balance() ";
	    opserr << " - DomainPartitioner::releaseBoundary returned ";
	    opserr << res << endln;
	    j = numReleases;
	}
    }
    
    return res;
}
Example #8
0
int 
SkylineSPD::setSize(Graph &theGraph)
{
    int oldSize = size;
    int result = 0;
    size = theGraph.getNumVertex();

    // check we have enough space in iDiagLoc and iLastCol
    // if not delete old and create new
    if (size > Bsize) { 
      if (iDiagLoc != 0) delete [] iDiagLoc;
      if (RowTop != 0) delete [] RowTop;
      if (topRowPtr != 0) delete [] topRowPtr;
      if (invD != 0) delete [] invD;
      // if (topRowPtr != 0) free((void *)topRowPtr);
      
      iDiagLoc = new int[size];
      RowTop = new int[size];
      invD = new double[size]; 
      //      topRowPtr = new double *[size] ;
      topRowPtr = (double **)malloc(size *sizeof(double *));


      if (iDiagLoc == 0 || RowTop == 0 || topRowPtr == 0 || invD == 0) {
	opserr << "WARNING SkylineSPD::setSize() : ";
	opserr << " - ran out of memory for iDiagLoc\n";
	size = 0; Asize = 0;
	result = -1;
      }
    }
    
    // zero out iDiagLoc 
    for (int i=0; i<size; i++) {
      iDiagLoc[i] = 0;
    }
    
    // now we go through the vertices to find the height of each col and
    // width of each row from the connectivity information.
    
    Vertex *vertexPtr;
    VertexIter &theVertices = theGraph.getVertices();
    
    while ((vertexPtr = theVertices()) != 0) {
      int vertexNum = vertexPtr->getTag();
      const ID &theAdjacency = vertexPtr->getAdjacency();
      int iiDiagLoc = iDiagLoc[vertexNum];
      int *iiDiagLocPtr = &(iDiagLoc[vertexNum]);
      
      for (int i=0; i<theAdjacency.Size(); i++) {
	int otherNum = theAdjacency(i);
	int diff = vertexNum-otherNum;
	if (diff > 0) {
	  if (iiDiagLoc < diff) {
	    iiDiagLoc = diff;
	    *iiDiagLocPtr = diff;
	  }
	} 
      }
    }
    
    
    // now go through iDiagLoc, adding 1 for the diagonal element
    // and then adding previous entry to give current location.
    if (iDiagLoc != 0)
      iDiagLoc[0] = 1; // NOTE FORTRAN ARRAY LOCATION
    
    for (int j=1; j<size; j++)
      iDiagLoc[j] = iDiagLoc[j] + 1 + iDiagLoc[j-1];
    
    if (iDiagLoc != 0)       
      profileSize = iDiagLoc[size-1];
    
    // check if we need more space to hold A
    // if so then go get it
    if (profileSize > Asize) { 
      
      // delete old space
      if (A != 0)
	delete [] A;
      
      // get new space
      A = new double[profileSize];
      
      if (A == 0) {
	opserr << "SkylineSPD::SkylineSPD :";
	opserr << " ran out of memory for A (size,Profile) (";
	opserr << size <<", " << profileSize << ") \n";
	size = 0;  Asize = 0;  profileSize = 0;
	result = -1;
      }
      else 
	Asize = profileSize;
    }
    
    // zero the matrix
    for (int k=0; k<profileSize; k++)
      A[k] = 0;
    
    isAfactored = false;
    isAcondensed = false;    
    
    if (size > Bsize) { // we have to get another space for A
      
      // delete the old
      if (B != 0) delete [] B;
      if (X != 0) delete [] X;
      
      // create the new	
      B = new double[size];
      X = new double[size];
      
      if (B == 0 || X == 0 ) {
	opserr << "SkylineSPD::SkylineSPD :";
	opserr << " ran out of memory for vectors (size) (";
	opserr << size << ") \n";
	size = 0; Bsize = 0;
	result = -1;
      }
    }
    
    // zero the vectors
    for (int l=0; l<size; l++) {
      B[l] = 0;
      X[l] = 0;
    }
    
    if (size != oldSize) {
      
      if (vectX != 0)
	delete vectX;
      if (vectB != 0)
	delete vectB;
      
      vectX = new Vector(X,size);
      vectB = new Vector(B,size);
      
      if (size > Bsize)
	Bsize = size;
    }
    
    RowTop[0] = 0;
    topRowPtr[0] = A;
    for (int j=1; j<size; j++) {
      int icolsz = iDiagLoc[j] - iDiagLoc[j-1];
      RowTop[j] = j - icolsz +  1;
      topRowPtr[j] = &A[iDiagLoc[j-1]]; // FORTRAN array indexing in iDiagLoc
    }
    
    return result;
}
Example #9
0
int 
ShadowPetscSOE::setSize(Graph &theGraph)
{
  int n = theGraph.getNumVertex();
  int size = n;
  int N = n;

  // fist itearte through the vertices of the graph to get nnz,
  // the number of non-zeros.
  Vertex *theVertex;
  int NNZ = 0;
  VertexIter &theVertices = theGraph.getVertices();
  while ((theVertex = theVertices()) != 0) {
    const ID &theAdjacency = theVertex->getAdjacency();
    NNZ += theAdjacency.Size() +1; // the +1 is for the diag entry
  }

  // we determine the number of non-zeros & number of nonzero's
  // in each row of A
  // create two integer arrays. One containing the column indices for each
  // entry in A stored in order by row and column number. 
  // The other a pointer into this array for each row.
  int *rowStartA = new int[size];  // start locations of rows in colA
  int *colA = new int[NNZ]; // column locations, stored row-wise

  // fill in rowStartA and colA
  if (size != 0) {
    rowStartA[0] = 0;
    int startLoc = 0;
    int lastLoc = 0;
    for (int a=0; a<size; a++) {

      theVertex = theGraph.getVertexPtr(a);
      if (theVertex == 0) {
	opserr << "WARNING:SparseGenLinSOE::setSize :";
	opserr << " vertex " << a << " not in graph! - size set to 0\n";
	size = 0;
	return -1;
      }

      colA[lastLoc++] = theVertex->getTag(); // place diag in first
      const ID &theAdjacency = theVertex->getAdjacency();
      int idSize = theAdjacency.Size();
	
      // now we have to place the entries in the ID into order in colA
      for (int i=0; i<idSize; i++) {

	int row = theAdjacency(i);
	bool foundPlace = false;
	// find a place in colA for current col
	for (int j=startLoc; j<lastLoc; j++)
	  if (colA[j] > row) { 
	    // move the entries already there one further on
	    // and place col in current location
	    for (int k=lastLoc; k>j; k--)
	      colA[k] = colA[k-1];
	    colA[j] = row;
	    foundPlace = true;
	      j = lastLoc;
	  }
	if (foundPlace == false) // put in at the end
	  colA[lastLoc] = row;

	lastLoc++;
      }
      rowStartA[a+1] = lastLoc;;	    
      startLoc = lastLoc;
    }
  }

  // now for each of the SOE's we determine how to invoke setSizeParallel()
  sendData[0] = 2;
  MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);

  int dnz = 0;
  int onz = 0;
  int numRowsTyp = N/blockSize/numProcessors;
  numRowsTyp *= blockSize;
  int numRowsLast = numRowsTyp + (N - numProcessors*numRowsTyp); // lastProc extra rows
  int *dnnz = new int[numRowsLast];
  int *onnz = new int[numRowsLast];

  // first determine start and end rows of diag block
  int numRows = numRowsLast;
  int endRow = N-1;
  int startRow = endRow-numRows +1; 
  
  int result = 0;
  // we have to go last to first
  for (int i=numProcessors-1; i>=0; i--) {

    // for each processor determine onnz and dnnz info in colA[]
    for (int j=0; j<numRows; j++) {
      dnnz[j] = 0; 
      onnz[j] = 0;
      int rowStart = rowStartA[startRow+j];
      int nextRowStart = rowStartA[startRow+j+1];
      for (int k=rowStart; k<nextRowStart; k++) {
	int col = colA[k];
	if (col < startRow || col > endRow)
	  onnz[j] += 1;
	else
	  dnnz[j] += 1;
      }
    }

    // now send the data
    if (i != 0) {  // remote object
      sendData[0] = 2;
      sendData[1] = numRows;
      sendData[2] = n;
      
      int tag = 100;
      MPI_Send(sendBuffer, 3, MPI_INT, i, tag, PETSC_COMM_WORLD);

      tag = 101;
      void *buffer = (void *)dnnz;
      MPI_Send(buffer, numRows, MPI_INT, i, tag, PETSC_COMM_WORLD);

      tag = 102;
      buffer = (void *)onnz;
      MPI_Send(buffer, numRows, MPI_INT, i, tag, PETSC_COMM_WORLD);
    }      

    // increment startRow, endRow and numRows if necessary
    endRow = startRow-1;
    numRows = numRowsTyp;
    startRow = endRow-numRows +1; 
  }

  // we broadcast again before we start setSizeParallel()
  // this is because Petsc all processes need to call setup at same
  // time .. if don't we hang
  MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);  
  result = theSOE.setSizeParallel(numRows, n, dnz, dnnz, onz, onnz);

  // free up trhe memory used
  /*
  delete [] colA;
  delete [] rowStartA;
  delete [] onnz;
  delete [] dnnz;
  */

  return result;
}
Example #10
0
int XC::ParallelNumberer::numberDOF(int lastDOF)
  {
    int result = 0;

    // get a pointer to the model & check its not null
    AnalysisModel *theModel = this->getAnalysisModelPtr();
    Domain *theDomain = 0;
    if(theModel) theDomain = theModel->getDomainPtr();
  
    if(theModel == 0 || theDomain == 0)
      {
        std::cerr << "WARNING XC::ParallelNumberer::numberDOF(int) -";
        std::cerr << " - no AnalysisModel.\n";
        return -1;
      }
  
    if(lastDOF != -1)
      {
        std::cerr << "WARNING XC::ParallelNumberer::numberDOF(int lastDOF):";
        std::cerr << " does not use the lastDOF as requested\n";
      }

    Graph &theGraph= theModel->getDOFGroupGraph();

    // if subdomain, collect graph, send it off, get 
    // ID back containing dof tags & start id numbers.
    if(processID != 0)
      {
        CommParameters cp(0,*theChannels[0]);
        const int numVertex = theGraph.getNumVertex();

        /*
        static XC::ID test(2); test(0) = processID; test(1) = 25;
        theChannel->recvID(0, 0, test);
        */

        cp.sendMovable(theGraph,DistributedObj::getDbTagData(),CommMetaData(1));

        // recv iD
        ID theID(2*numVertex);
        cp.receiveID(theID,DistributedObj::getDbTagData(),CommMetaData(2));

        // set vertex numbering based on ID received
        for(int i=0; i<numVertex; i ++)
          {
            const int vertexTag= theID(i);
            int startID= theID(i+numVertex);
            //Vertex *vertexPtr = theGraph.getVertexPtr(vertexTag);
            const int dofTag= vertexTag;
            DOF_Group *dofPtr= theModel->getDOF_GroupPtr(dofTag);
            if(!dofPtr)
              {
                std::cerr << "WARNING ParallelNumberer::numberDOF - ";
                std::cerr << "DOF_Group " << dofTag << "not in XC::AnalysisModel!\n";
                result= -4;
              }
            else
              {
                const ID &theDOFID= dofPtr->getID();
                //std::cerr << "P: " << processID << " dofTag: " << dofTag << " " << "start: " << startID << " " << theDOFID;
                const int idSize= theDOFID.Size();
                for(int j=0; j<idSize; j++)
                  if(theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++);
              }
            //const ID &theDOFID= dofPtr->getID();
          }
        cp.sendID(theID,DistributedObj::getDbTagData(),CommMetaData(2));
      } 
    else
      {
        // if XC::main domain, collect graphs from all subdomains,
        // merge into 1, number this one, send to subdomains the
        // id containing dof tags & start id's.

        // for P0 domain determine original vertex and ref tags
        const int numVertex= theGraph.getNumVertex(); 
        const int numVertexP0= numVertex;

        ID vertexTags(numVertex);
        ID vertexRefs(numVertex);
        Vertex *vertexPtr;
        int loc= 0;
        VertexIter &theVertices= theGraph.getVertices();
        while((vertexPtr= theVertices()) != 0)
          {
            vertexTags[loc]= vertexPtr->getTag();
            vertexRefs[loc]= vertexPtr->getRef();
            loc++;
          }
    
        const int numChannels= theChannels.size();
	std::vector<ID> theSubdomainIDs(numChannels);
        FEM_ObjectBroker theBroker;

        // for each subdomain we receive graph, create an XC::ID (to store
        // subdomain graph to merged graph vertex mapping and the final
        // subdoain graph vertex to startDOF mapping) and finally merge the
        // subdomain graph

        for(int j=0; j<numChannels; j++)
          {
            CommParameters cp(0,*theChannels[j]);
            Graph theSubGraph;

            /*
            static XC::ID test(2); test(0)= processID; test(1)= 25;
            theChannel->sendID(0, 0, test);
            */
            cp.receiveMovable(theSubGraph,DistributedObj::getDbTagData(),CommMetaData(3));
            theSubdomainIDs[j]= ID(theSubGraph.getNumVertex()*2);
            this->mergeSubGraph(theGraph, theSubGraph, vertexTags, vertexRefs, theSubdomainIDs[j]);
          }
    
        // we use graph numberer if one was provided in constructor,
        // otherwise we number based on subdomains (all in subdomain 1 numbered first, 
        // then  those in 2 not in 1 and so on till done.
        //    GraphNumberer *theNumberer= this->getGraphNumbererPtr();

        ID theOrderedRefs(theGraph.getNumVertex());

        if(theNumberer)
          {
            // use the supplied graph numberer to number the merged graph
            theOrderedRefs= theNumberer->number(theGraph, lastDOF);     
          }
        else
          {
            // assign numbers based on the subdomains

            int loc= 0;
            for(int l=0; l<numChannels; l++)
              {
                const ID &theSubdomain= theSubdomainIDs[l];
                int numVertexSubdomain= theSubdomain.Size()/2;

                for(int i=0; i<numVertexSubdomain; i++)
                  {
                    const int vertexTagMerged= theSubdomain(i+numVertexSubdomain);
                    //  int refTag= vertexRefs[vertexTags.getLocation(vertexTagMerged)];
                    if(theOrderedRefs.getLocation(vertexTagMerged) == -1)
                      theOrderedRefs[loc++]= vertexTagMerged;
                  }
              }

            // now order those not yet ordered in p0
            for(int j=0; j<numVertexP0; j++)
              {
                int refTagP0= vertexTags[j];
                if(theOrderedRefs.getLocation(refTagP0) == -1)
                  theOrderedRefs[loc++]= refTagP0;
              }        
          }
    int count= 0;
    for(int i=0; i<theOrderedRefs.Size(); i++)
      {
        int vertexTag= theOrderedRefs(i);
        //      int vertexTag= vertexTags[vertexRefs.getLocation(tag)];
        Vertex *vertexPtr= theGraph.getVertexPtr(vertexTag);
        int numDOF= vertexPtr->getColor();
        vertexPtr->setTmp(count);
        count += numDOF;
      }

    // number own dof's
    for(int i=0; i<numVertexP0; i++  ) {
      int vertexTag= vertexTags(i);
      Vertex *vertexPtr= theGraph.getVertexPtr(vertexTag);

      int startID= vertexPtr->getTmp();
      int dofTag= vertexTag;
      DOF_Group *dofPtr;        
      dofPtr= theModel->getDOF_GroupPtr(dofTag);
      if(dofPtr == 0) {
        std::cerr << "WARNING XC::ParallelNumberer::numberDOF - ";
        std::cerr << "DOF_Group (P0) " << dofTag << "not in XC::AnalysisModel!\n";
        result= -4;
      } else {
        const ID &theDOFID= dofPtr->getID();
        int idSize= theDOFID.Size();
        for(int j=0; j<idSize; j++)
          if(theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++);
      }
    }

    // now given the ordered refs we determine the mapping for each subdomain
    // and send the id with the information back to the subdomain, which it uses to order
    // it's own graph
    for(int k=0; k<numChannels; k++)
     {
        CommParameters cp(0,*theChannels[k]);
        ID &theSubdomain= theSubdomainIDs[k];
        int numVertexSubdomain= theSubdomain.Size()/2;

        for(int i=0; i<numVertexSubdomain; i++)
          {
            int vertexTagMerged= theSubdomain[numVertexSubdomain+i];
            Vertex *vertexPtr= theGraph.getVertexPtr(vertexTagMerged);
            int startDOF= vertexPtr->getTmp();
            theSubdomain[i+numVertexSubdomain]= startDOF;
          }
        cp.sendID(theSubdomain,DistributedObj::getDbTagData(),CommMetaData(4));
        cp.receiveID(theSubdomain,DistributedObj::getDbTagData(),CommMetaData(4));
      }      
  }

  // iterate through the XC::FE_Element getting them to set their IDs
  FE_EleIter &theEle= theModel->getFEs();
  FE_Element *elePtr;
  while ((elePtr= theEle()) != 0)
    elePtr->setID();
  
  return result;
}
Example #11
0
int XC::ParallelNumberer::numberDOF(ID &lastDOFs)
{

  int result= 0;
  
  // get a pointer to the model & check its not null
  AnalysisModel *theModel= this->getAnalysisModelPtr();
  Domain *theDomain= 0;
  if(theModel != 0) theDomain= theModel->getDomainPtr();
  
  if(theModel == 0 || theDomain == 0) {
    std::cerr << "WARNING ParallelNumberer::numberDOF(int) -";
    std::cerr << " - no AnalysisModel.\n";
    return -1;
  }
  
  Graph &theGraph= theModel->getDOFGroupGraph();
  
  // if subdomain, collect graph, send it off, get 
  // ID back containing dof tags & start id numbers.
    if(processID != 0)
      {
        CommParameters cp(0,*theChannels[0]);
        int numVertex= theGraph.getNumVertex();
        cp.sendMovable(theGraph,DistributedObj::getDbTagData(),CommMetaData(5));
        ID theID(2*numVertex);
        cp.receiveID(theID,DistributedObj::getDbTagData(),CommMetaData(6));
    for(int i=0; i<numVertex; i += 2) {
      int dofTag= theID(i);
      int startID= theID(i+1);
      DOF_Group *dofPtr;        
      dofPtr= theModel->getDOF_GroupPtr(dofTag);
      if(dofPtr == 0) {
        std::cerr << "WARNING XC::ParallelNumberer::numberDOF - ";
        std::cerr << "DOF_Group " << dofTag << "not in XC::AnalysisModel!\n";
        result= -4;
      } else {
        const ID &theID= dofPtr->getID();
        int idSize= theID.Size();
        for(int j=0; j<idSize; j++)
          if(theID(j) == -2) dofPtr->setID(j, startID++);
      }
    }
  } 
  
  // if XC::main domain, collect graphs from all subdomains,
  // merge into 1, number this one, send to subdomains the
  // id containing dof tags & start id's.
  else {
    
    // determine original vertex and ref tags
    int numVertex= theGraph.getNumVertex();
    ID vertexTags(numVertex);
    ID vertexRefs(numVertex);
    Vertex *vertexPtr;
    int loc= 0;
    VertexIter &theVertices= theGraph.getVertices();
    while ((vertexPtr= theVertices()) != 0) {
      vertexTags[loc]= vertexPtr->getTag();
      vertexRefs[loc]= vertexPtr->getRef();
      loc++;
    }
    
    const int numChannels= theChannels.size();
    std::vector<ID> theSubdomainIDs(numChannels);
    FEM_ObjectBroker theBroker;

    // merge all subdomain graphs
    for(int j=0; j<numChannels; j++)
      {
        CommParameters cp(0,*theChannels[j]);
        Graph theSubGraph;
        cp. receiveMovable(theSubGraph,DistributedObj::getDbTagData(),CommMetaData(6));
        theSubdomainIDs[j]= ID(theSubGraph.getNumVertex()*2);
        this->mergeSubGraph(theGraph, theSubGraph, vertexTags, vertexRefs, theSubdomainIDs[j]);
      }

    // number the merged graph
    //    result=  this->XC::DOF_Numberer::number(theGraph);

    // send results of numbered back to subdomains
    for(int k=0; k<numChannels; k++)
      {
        Channel *theChannel= theChannels[k];
        // this->determineSubIDs
        theChannel->sendID(0, 0, theSubdomainIDs[k]);
      }      
    }

  return result;
}
Example #12
0
/* Based on the graph (the entries in A), set up the pair (rowStartA, colA).
 * It is the same as the pair (ADJNCY, XADJ).
 * Then perform the symbolic factorization by calling symFactorization().
 */
int XC::SymSparseLinSOE::setSize(Graph &theGraph)
  {
    int result = 0;
    size= checkSize(theGraph);

    // first iterarte through the vertices of the graph to get nnz
    Vertex *theVertex;
    int newNNZ = 0;
    VertexIter &theVertices = theGraph.getVertices();
    while((theVertex = theVertices()) != 0)
      {
        const std::set<int> &theAdjacency = theVertex->getAdjacency();
	newNNZ += theAdjacency.size(); 
      }
    nnz = newNNZ;
 
    colA= ID(newNNZ);	
    if(colA.isEmpty())
      {
        std::cerr << "WARNING SymSparseLinSOE::setSize :";
	std::cerr << " ran out of memory for colA with nnz = ";
      	std::cerr << newNNZ << " \n";
       	size = 0; nnz = 0;
       	result =  -1;
      } 
	
    factored = false;
    
    if(size > B.Size())
      {
	inic(size);
	rowStartA= ID(size+1); 
      }

    // fill in rowStartA and colA
    if(size != 0)
      {
        rowStartA(0) = 0;
        int startLoc = 0;
	int lastLoc = 0;

	for (int a=0; a<size; a++) {
	   theVertex = theGraph.getVertexPtr(a);
	   if(theVertex == 0) {
	        std::cerr << "WARNING:XC::SymSparseLinSOE::setSize :";
	        std::cerr << " vertex " << a << " not in graph! - size set to 0\n";
	        size = 0;
	        return -1;
	   }

	   const std::set<int> &theAdjacency = theVertex->getAdjacency();
	
	// now we have to place the entries in the ID into order in colA
           for(std::set<int>::const_iterator i=theAdjacency.begin(); i!=theAdjacency.end(); i++)
  	     {
	      const int row= *i;
	      bool foundPlace = false;
	 
	      for (int j=startLoc; j<lastLoc; j++)
		if(colA(j) > row) { 
	      // move the entries already there one further on
	      // and place col in current location
	              for (int k=lastLoc; k>j; k--)
			colA(k)= colA(k-1);
                      colA(j) = row;
		      foundPlace = true;
    	              j = lastLoc;
		  }
		  
	      if(foundPlace == false) // put in at the end
		colA(lastLoc) = row;

	      lastLoc++;
	   }
	   rowStartA(a+1)= lastLoc;	    
	   startLoc = lastLoc;
	}
    }
    
    // call "C" function to form elimination tree and to do the symbolic factorization.
    nblks = symFactorization(rowStartA.getDataPtr(), colA.getDataPtr(), size, this->LSPARSE,
			     &xblk, &invp, &rowblks, &begblk, &first, &penv, &diag);

    return result;
}
Example #13
0
int
DomainPartitioner::partition(int numParts, bool usingMain, int mainPartitionTag, int specialElementTag)
{

  usingMainDomain = usingMain;
  mainPartition = mainPartitionTag;

  // first we ensure the partitioned domain has numpart subdomains
  // with tags 1 through numparts
  for (int i=1; i<=numParts; i++) {
    if (i != mainPartition) {
      Subdomain *subdomainPtr = myDomain->getSubdomainPtr(i);
      if (subdomainPtr == 0) {
	opserr << "DomainPartitioner::partition - No Subdomain: ";
	opserr << i << " exists\n";
	return -1;
      }
    }
  }

  // we get the ele graph from the domain and partition it
  //    Graph &theEleGraph = myDomain->getElementGraph();
  //    theElementGraph = new Graph(myDomain->getElementGraph());

  theElementGraph = &(myDomain->getElementGraph());

  int theError = thePartitioner.partition(*theElementGraph, numParts);

  if (theError < 0) {
    opserr << "DomainPartitioner::partition";
    opserr << " - the graph partioner failed to partition the ";
    opserr << "element graph\n";
    return -10+theError;
  }

  /* print graph */
  //  opserr << "DomainPartitioner::partition - eleGraph: \n";
  //  theElementGraph->Print(opserr, 4);
  
  VertexIter &theVertices1 = theElementGraph->getVertices();
  Vertex *vertexPtr = 0;
  bool moreThanOne = false;
  
  vertexPtr = theVertices1();
  int vertexOnePartition  = 0;
  if (vertexPtr != 0)
    vertexOnePartition  = vertexPtr->getColor();  
  while ((moreThanOne == false) && ((vertexPtr = theVertices1()) != 0)) {
    int partition = vertexPtr->getColor();
    if (partition != vertexOnePartition ) {
      moreThanOne = true;
    }
  }

  if (moreThanOne == false) {
    opserr <<"DomainPartitioner::partition - too few elements for model to be partitioned\n";
    return -1;
  }

  int specialElementColor = 1;
  if (specialElementTag != 0) {
    bool found = false;
    VertexIter &theVerticesSpecial = theElementGraph->getVertices();
    while ((found == false) && ((vertexPtr = theVerticesSpecial()) != 0)) {
      int eleTag = vertexPtr->getRef();
      if (eleTag == specialElementTag) {
	found = true;
	int vertexColor = vertexPtr->getColor();
	if (vertexColor != 1)
	  //	  specialElementColor = vertexColor;
	  vertexPtr->setColor(1);
      }
    }
  }
  
      
  // we create empty graphs for the numParts subdomains,
  // in the graphs we place the vertices for the elements on the boundaries
  
  // we do not invoke the destructor on the individual graphs as 
  // this would invoke the destructor on the individual vertices

  if (theBoundaryElements != 0)
    delete [] theBoundaryElements;
  
  theBoundaryElements = new Graph * [numParts];
  if (theBoundaryElements == 0) {
    opserr << "DomainPartitioner::partition(int numParts)";
    opserr << " - ran out of memory\n";
    numPartitions = 0;  
    return -1;
  }

  for (int l=0; l<numParts; l++) {
    theBoundaryElements[l] = new Graph(2048); // graphs can grow larger; just an estimate
    
    if (theBoundaryElements[l] == 0) {
      opserr << "DomainPartitioner::partition(int numParts)";
      opserr << " - ran out of memory\n";
      numPartitions = 0;
      return -1;
    }
  }
  
  numPartitions = numParts;

  //  opserr << "DomainPartitioner::partition() - nodes \n";  
  
  // we now create a MapOfTaggedObjectStorage to store the NodeLocations
  // and create a new NodeLocation for each node; adding it to the map object

  theNodeLocations = new MapOfTaggedObjects();
  if (theNodeLocations == 0) {
    opserr << "DomainPartitioner::partition(int numParts)";
    opserr << " - ran out of memory creating MapOfTaggedObjectStorage for node locations\n";
    numPartitions = 0;
    return -1;
  }

  NodeIter &theNodes = myDomain->getNodes();
  Node *nodePtr;
  while ((nodePtr = theNodes()) != 0) {
    NodeLocations *theNodeLocation = new NodeLocations(nodePtr->getTag());
    if (theNodeLocation == 0) {
      opserr << "DomainPartitioner::partition(int numParts)";
      opserr << " - ran out of memory creating NodeLocation for node: " << nodePtr->getTag() << endln;
      numPartitions = 0;
      return -1;
    }
    if (theNodeLocations->addComponent(theNodeLocation) == false) {
      opserr << "DomainPartitioner::partition(int numParts)";
      opserr << " - failed to add NodeLocation to Map for Node: " << nodePtr->getTag() << endln;
      numPartitions = 0;
      return -1;
    }
  }

  //
  // we now iterate through the vertices of the element graph
  // to see if the vertex is a boundary vertex or not - if it is
  // we add to the appropriate graph created above. We also set the
  // value the color variable of each of the external nodes connected 
  // to the element to a value which will indicate that that node will
  // have to be added to the subdomain.
  //
  
  VertexIter &theVertexIter = theElementGraph->getVertices();
  while ((vertexPtr = theVertexIter()) != 0) {
    int eleTag = vertexPtr->getRef();
    int vertexColor = vertexPtr->getColor();
    
    const ID &adjacency = vertexPtr->getAdjacency();
    int size = adjacency.Size();
    for (int i=0; i<size; i++) {
      Vertex *otherVertex = theElementGraph->getVertexPtr(adjacency(i));
      if (otherVertex->getColor() != vertexColor) {
	theBoundaryElements[vertexColor-1]->addVertex(vertexPtr,false);
	i = size;
      }
    }
    
    Element *elePtr = myDomain->getElement(eleTag);
    const ID &nodes = elePtr->getExternalNodes();
    size = nodes.Size();
    for (int j=0; j<size; j++) {
      int nodeTag = nodes(j);
      TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
      if (theTaggedObject == 0) {
	opserr << "DomainPartitioner::partition(int numParts)";
	opserr << " - failed to find NodeLocation in Map for Node: " << nodePtr->getTag() << " -- A BUG!!\n";
	numPartitions = 0;
	return -1;	
      }
      NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
      theNodeLocation->addPartition(vertexColor);
    }
  }

  // now go through the MP_Constraints and ensure the retained node is in every 
  // partition the constrained node is in
  MP_ConstraintIter &theMPs = myDomain->getMPs();
  MP_Constraint *mpPtr;
  while ((mpPtr = theMPs()) != 0) {
    int retained = mpPtr->getNodeRetained();
    int constrained = mpPtr->getNodeConstrained();
    
    TaggedObject *theRetainedObject = theNodeLocations->getComponentPtr(retained);      
    TaggedObject *theConstrainedObject = theNodeLocations->getComponentPtr(constrained);
    
    if (theRetainedObject == 0 || theConstrainedObject == 0) {
      opserr << "DomainPartitioner::partition(int numParts)";
      if (theRetainedObject == 0)
	opserr << " - failed to find NodeLocation in Map for Node: " << retained << " -- A BUG!!\n";
      if (theConstrainedObject == 0)
	opserr << " - failed to find NodeLocation in Map for Node: " << constrained << " -- A BUG!!\n";
      numPartitions = 0;
      return -1;	
    }
    
    NodeLocations *theRetainedLocation = (NodeLocations *)theRetainedObject;
    NodeLocations *theConstrainedLocation = (NodeLocations *)theConstrainedObject;
    ID &theConstrainedNodesPartitions = theConstrainedLocation->nodePartitions;
    int numPartitions = theConstrainedNodesPartitions.Size();
    for (int i=0; i<numPartitions; i++) {
      theRetainedLocation->addPartition(theConstrainedNodesPartitions(i));
    }
  }

  // we now add the nodes, 
  TaggedObjectIter &theNodeLocationIter = theNodeLocations->getComponents();
  TaggedObject *theNodeObject;

  while ((theNodeObject = theNodeLocationIter()) != 0) {
    NodeLocations *theNodeLocation = (NodeLocations *)theNodeObject;

    int nodeTag = theNodeLocation->getTag();
    ID &nodePartitions = theNodeLocation->nodePartitions;
    int numPartitions = theNodeLocation->numPartitions;

    for (int i=0; i<numPartitions; i++) {
      int partition = nodePartitions(i);	  
      if (partition != mainPartition) {      
	Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
	if (numPartitions == 1) {
	  Node *nodePtr = myDomain->removeNode(nodeTag);
	  theSubdomain->addNode(nodePtr);
	} else {
	  Node *nodePtr = myDomain->getNode(nodeTag);
	  theSubdomain->addExternalNode(nodePtr);	  
	}
      }
    }
  }

  // we now move the elements 
  VertexIter &theVertices = theElementGraph->getVertices();
  while ((vertexPtr = theVertices()) != 0) {
    // move the element
    int partition = vertexPtr->getColor();
    if (partition != mainPartition) {          
      int eleTag = vertexPtr->getRef();

      //      opserr << "removing ele: " << eleTag << endln;
      
      Element *elePtr = myDomain->removeElement(eleTag);  
      //      opserr << *elePtr;

      if (elePtr != 0) {
	//	opserr << "adding ele - start\n";
	Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);  
	theSubdomain->addElement(elePtr);

	//	opserr << "adding ele - done\n";
      } else {
	opserr << "DomainPartitioner::partioner - element GONE! - eleTag " << eleTag << endln;
      }
    } 
  }

  // now we go through the load patterns and move NodalLoad
  // 1) make sure each subdomain has a copy of the partitioneddomains load patterns.
  // 2) move nodal loads
  // 3) move SP_Constraints
  
  LoadPatternIter &theLoadPatterns = myDomain->getLoadPatterns();
  LoadPattern *theLoadPattern;
  while ((theLoadPattern = theLoadPatterns()) != 0) {
    int loadPatternTag = theLoadPattern->getTag();

    
    // check that each subdomain has a loadPattern with a similar tag and class tag
    for (int i=1; i<=numParts; i++) {
      if (i != mainPartition) {
	Subdomain *theSubdomain = myDomain->getSubdomainPtr(i);
	LoadPattern *loadPatternCopy = theSubdomain->getLoadPattern(loadPatternTag);
	if (loadPatternCopy == 0) {
	  LoadPattern *newLoadPattern = theLoadPattern->getCopy();
	  if (newLoadPattern == 0) {
	    opserr << "DomaiPartitioner::partition - out of memory creating LoadPatterns\n";
 	    return -1;
	  }
	  theSubdomain->addLoadPattern(newLoadPattern);
	}
      }
    }

    // now remove any nodal loads that correspond to internal nodes in a subdomain
    // and add them to the appropriate loadpattern in the subdomain
    
    NodalLoadIter &theNodalLoads = theLoadPattern->getNodalLoads();
    NodalLoad *theNodalLoad;
    while ((theNodalLoad = theNodalLoads()) != 0) {
      int nodeTag = theNodalLoad->getNodeTag();

      TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
      if (theTaggedObject == 0) {
	opserr << "DomainPartitioner::partition(int numParts)";
	opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
	numPartitions = 0;
	return -1;	
      }
    
      NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
      ID &nodePartitions = theNodeLocation->nodePartitions;
      int numPartitions = theNodeLocation->numPartitions;
      for (int i=0; i<numPartitions; i++) {
	int partition = nodePartitions(i);	  
	if (partition != mainPartition) {      
	  if (numPartitions == 1) {
	    Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);
	    theLoadPattern->removeNodalLoad(theNodalLoad->getTag());
	    if ((theSubdomain->addNodalLoad(theNodalLoad, loadPatternTag)) != true)
	      opserr << "DomainPartitioner::partition() - failed to add Nodal Load\n";
	  }
	}
      }      
    }

  
    SP_ConstraintIter &theSPs = theLoadPattern->getSPs();
    SP_Constraint *spPtr;
    while ((spPtr = theSPs()) != 0) {
      int nodeTag = spPtr->getNodeTag();
      
      TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
      if (theTaggedObject == 0) {
	opserr << "DomainPartitioner::partition(int numParts)";
	opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
	numPartitions = 0;
	return -1;	
      }
      
      NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
      ID &nodePartitions = theNodeLocation->nodePartitions;
      int numPartitions = theNodeLocation->numPartitions;
      for (int i=0; i<numPartitions; i++) {
	int partition = nodePartitions(i);	  
	if (partition != mainPartition) {      
	  Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
	  if (numPartitions == 1) 
	    theLoadPattern->removeSP_Constraint(spPtr->getTag());
	  int res = theSubdomain->addSP_Constraint(spPtr, loadPatternTag);
	  if (res < 0)
	    opserr << "DomainPartitioner::partition() - failed to add SP Constraint\n";
	}
      }    
    }  

    ElementalLoadIter &theLoads = theLoadPattern->getElementalLoads();
    ElementalLoad *theLoad;
    while ((theLoad = theLoads()) != 0) {
      int loadEleTag = theLoad->getElementTag();

      SubdomainIter &theSubdomains = myDomain->getSubdomains();
      Subdomain *theSub;
      bool added = false;
      while (((theSub = theSubdomains()) != 0) && (added == false)) {
	bool res = theSub->hasElement(loadEleTag);
	if (res == true) {
	  theLoadPattern->removeElementalLoad(theLoad->getTag());
	  theSub->addElementalLoad(theLoad, loadPatternTag);
	  if (res < 0)
	    opserr << "DomainPartitioner::partition() - failed to add ElementalLoad\n";
	  added = true;
	}
      }   
    }
  }

  // add the single point constraints, 
  
  SP_ConstraintIter &theDomainSP = myDomain->getSPs();
  SP_Constraint *spPtr;
  while ((spPtr = theDomainSP()) != 0) {
    int nodeTag = spPtr->getNodeTag();

    TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
    if (theTaggedObject == 0) {
      opserr << "DomainPartitioner::partition(int numParts)";
      opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
      numPartitions = 0;
      return -1;	
    }
    
    NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
    ID &nodePartitions = theNodeLocation->nodePartitions;
    int numPartitions = theNodeLocation->numPartitions;
    for (int i=0; i<numPartitions; i++) {
      int partition = nodePartitions(i);	  

      if (partition != mainPartition) {      
	Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
	if (numPartitions == 1) {
	  myDomain->removeSP_Constraint(spPtr->getTag());
	}
	int res = theSubdomain->addSP_Constraint(spPtr);
	if (res < 0)
	  opserr << "DomainPartitioner::partition() - failed to add SP Constraint\n";
      }
    }    
  }  

  // move MP_Constraints - add an MP_Constraint to every partition a constrained node is in
  MP_ConstraintIter &moreMPs = myDomain->getMPs();
  while ((mpPtr = moreMPs()) != 0) {
    int constrained = mpPtr->getNodeConstrained();
    TaggedObject *theConstrainedObject = theNodeLocations->getComponentPtr(constrained);
    NodeLocations *theConstrainedLocation = (NodeLocations *)theConstrainedObject;
    ID &theConstrainedNodesPartitions = theConstrainedLocation->nodePartitions;
    int numPartitions = theConstrainedLocation->numPartitions;
    for (int i=0; i<numPartitions; i++) {
      int partition = theConstrainedNodesPartitions(i);
      if (partition != mainPartition) {
	Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);
	if (numPartitions == 1) 
	  myDomain->removeMP_Constraint(mpPtr->getTag());
	int res = theSubdomain->addMP_Constraint(mpPtr);
	if (res < 0)
	  opserr << "DomainPartitioner::partition() - failed to add MP Constraint\n";
      }
    }
  }

  // now we go through all the subdomains and tell them to update
  // their analysis for the new layouts
  
  SubdomainIter &theSubDomains = myDomain->getSubdomains();
  Subdomain *theSubDomain;
  while ((theSubDomain = theSubDomains()) != 0) 
    theSubDomain->domainChange();
  
  // we invoke change on the PartitionedDomain
  myDomain->domainChange();

  myDomain->clearElementGraph();
    
  // we are done
  partitionFlag = true;

  return 0;
}
Example #14
0
int 
SparseGenRowLinSOE::setSize(Graph &theGraph)
{

    int result = 0;
    int oldSize = size;
    size = theGraph.getNumVertex();

    // fist itearte through the vertices of the graph to get nnz
    Vertex *theVertex;
    int newNNZ = 0;
    VertexIter &theVertices = theGraph.getVertices();
    while ((theVertex = theVertices()) != 0) {
	const ID &theAdjacency = theVertex->getAdjacency();
	newNNZ += theAdjacency.Size() +1; // the +1 is for the diag entry
    }
    nnz = newNNZ;

    if (newNNZ > Asize) { // we have to get more space for A and colA
	if (A != 0) 
	    delete [] A;
	if (colA != 0)
	    delete [] colA;
	
	A = new double[newNNZ];
	colA = new int[newNNZ];
	
        if (A == 0 || colA == 0) {
            opserr << "WARNING SparseGenRowLinSOE::SparseGenRowLinSOE :";
	    opserr << " ran out of memory for A and colA with nnz = ";
	    opserr << newNNZ << " \n";
	    size = 0; Asize = 0; nnz = 0;
	    result =  -1;
        } 
	
	Asize = newNNZ;
    }

    // zero the matrix
    for (int i=0; i<Asize; i++)
	A[i] = 0;
	
    factored = false;
    
    if (size > Bsize) { // we have to get space for the vectors
	
	// delete the old	
	if (B != 0) delete [] B;
	if (X != 0) delete [] X;
	if (rowStartA != 0) delete [] rowStartA;

	// create the new
	B = new double[size];
	X = new double[size];
	rowStartA = new int[size+1]; 
	
        if (B == 0 || X == 0 || rowStartA == 0) {
            opserr << "WARNING SparseGenRowLinSOE::SparseGenRowLinSOE :";
	    opserr << " ran out of memory for vectors (size) (";
	    opserr << size << ") \n";
	    size = 0; Bsize = 0;
	    result =  -1;
        }
	else
	    Bsize = size;
    }

    // zero the vectors
    for (int j=0; j<size; j++) {
	B[j] = 0;
	X[j] = 0;
    }
    
    // create new Vectors objects
    if (size != oldSize) {
	if (vectX != 0)
	    delete vectX;

	if (vectB != 0)
	    delete vectB;
	
	vectX = new Vector(X,size);
	vectB = new Vector(B,size);	
    }

    // fill in rowStartA and colA
    if (size != 0) {
      rowStartA[0] = 0;
      int startLoc = 0;
      int lastLoc = 0;
      for (int a=0; a<size; a++) {

	theVertex = theGraph.getVertexPtr(a);
	if (theVertex == 0) {
	  opserr << "WARNING:SparseGenRowLinSOE::setSize :";
	  opserr << " vertex " << a << " not in graph! - size set to 0\n";
	  size = 0;
	  return -1;
	}

	colA[lastLoc++] = theVertex->getTag(); // place diag in first
	const ID &theAdjacency = theVertex->getAdjacency();
	int idSize = theAdjacency.Size();
	
	// now we have to place the entries in the ID into order in colA
	for (int i=0; i<idSize; i++) {

	  int row = theAdjacency(i);
	  bool foundPlace = false;
	  // find a place in colA for current col
	  for (int j=startLoc; j<lastLoc; j++)
	    if (colA[j] > row) { 
	      // move the entries already there one further on
	      // and place col in current location
	      for (int k=lastLoc; k>j; k--)
		
		colA[k] = colA[k-1];
	      colA[j] = row;
	      foundPlace = true;
	      j = lastLoc;
	    }
	  if (foundPlace == false) // put in at the end
	    colA[lastLoc] = row;

	  lastLoc++;
	}
	rowStartA[a+1] = lastLoc;;	    
	startLoc = lastLoc;
      }
    }

    // invoke setSize() on the Solver   
     LinearSOESolver *the_Solver = this->getSolver();
    int solverOK = the_Solver->setSize();
    if (solverOK < 0) {
	opserr << "WARNING:SparseGenRowLinSOE::setSize :";
	opserr << " solver failed setSize()\n";
	return solverOK;
    }    
    return result;
}
Example #15
0
int 
BandGenLinSOE::setSize(Graph &theGraph)
{
    int result = 0;
    int oldSize = size;
    size = theGraph.getNumVertex();
    
    /*
     * determine the number of superdiagonals and subdiagonals
     */
    
    numSubD = 0;
    numSuperD = 0;

    Vertex *vertexPtr;
    VertexIter &theVertices = theGraph.getVertices();
    
    while ((vertexPtr = theVertices()) != 0) {
	int vertexNum = vertexPtr->getTag();
	const ID &theAdjacency = vertexPtr->getAdjacency();
	for (int i=0; i<theAdjacency.Size(); i++) {
	    int otherNum = theAdjacency(i);
	    int diff = vertexNum - otherNum;
	    if (diff > 0) {
		if (diff > numSuperD)
		    numSuperD = diff;
	    } else 
		if (diff < numSubD)
		    numSubD = diff;
	}
    }
    numSubD *= -1;

    int newSize = size * (2*numSubD + numSuperD +1);
    if (newSize > Asize) { // we have to get another space for A

	if (A != 0) 
	    delete [] A;

	A = new double[newSize];
	
        if (A == 0) {
            opserr << "WARNING BandGenLinSOE::BandGenLinSOE :";
	    opserr << " ran out of memory for A (size,super,sub) (";
	    opserr << size <<", " << numSuperD << ", " << numSubD << ") \n";
	    Asize = 0; size = 0; numSubD = 0; numSuperD = 0;
	    result= -1;
        }
	else  
	    Asize = newSize;
    }

    // zero the matrix
    for (int i=0; i<Asize; i++)
	A[i] = 0;
	
    factored = false;
    
    if (size > Bsize) { // we have to get space for the vectors
	
	// delete the old	
	if (B != 0) delete [] B;
	if (X != 0) delete [] X;

	// create the new
	B = new double[size];
	X = new double[size];
	
        if (B == 0 || X == 0) {
            opserr << "WARNING BandGenLinSOE::BandGenLinSOE :";
	    opserr << " ran out of memory for vectors (size) (";
	    opserr << size << ") \n";
	    Bsize = 0; size = 0; numSubD = 0; numSuperD = 0;
	    result = -1;
        }
	else 
	    Bsize = size;
    }

    // zero the vectors
    for (int j=0; j<size; j++) {
	B[j] = 0;
	X[j] = 0;
    }

    // get new Vector objects if size has changes
    if (oldSize != size) {
	if (vectX != 0) 
	    delete vectX;

	if (vectB != 0) 
	    delete vectB;
		
	vectX = new Vector(X,size);
	vectB = new Vector(B,size);
    }
    
    // invoke setSize() on the Solver
    LinearSOESolver *theSolvr = this->getSolver();
    int solverOK = theSolvr->setSize();
    if (solverOK < 0) {
	opserr << "WARNING:BandGenLinSOE::setSize :";
	opserr << " solver failed setSize()\n";
	return solverOK;
    }    

    return result;    
}
Example #16
0
int 
SymArpackSOE::setSize(Graph &theGraph)
{
    int result = 0;
    int oldSize = size;
    size = theGraph.getNumVertex();

    // fist itearte through the vertices of the graph to get nnz
    Vertex *theVertex;
    int newNNZ = 0;
    VertexIter &theVertices = theGraph.getVertices();
    while ((theVertex = theVertices()) != 0) {
        const ID &theAdjacency = theVertex->getAdjacency();
	newNNZ += theAdjacency.Size(); 
    }
    nnz = newNNZ;

    if (colA != 0)
      delete [] colA;

    colA = new int[newNNZ];	
    if (colA == 0) {
	opserr << "WARNING SymArpackSOE::SymArpackSOE :";
	opserr << " ran out of memory for colA with nnz = ";
      	opserr << newNNZ << " \n";
       	size = 0; nnz = 0;
       	result =  -1;
    } 
	
    factored = false;

    if (rowStartA != 0) 
      delete [] rowStartA;
    rowStartA = new int[size+1]; 
    if (rowStartA == 0) {
        opserr << "SymArpackSOE::ran out of memory for rowStartA." << endln;
        result = -1;
    }

    // fill in rowStartA and colA
    if (size != 0) {
        rowStartA[0] = 0;
        int startLoc = 0;
	int lastLoc = 0;

	for (int a=0; a<size; a++) {
	   theVertex = theGraph.getVertexPtr(a);
	   if (theVertex == 0) {
	        opserr << "WARNING:SymArpackSOE::setSize :";
	        opserr << " vertex " << a << " not in graph! - size set to 0\n";
	        size = 0;
	        return -1;
	   }

	   const ID &theAdjacency = theVertex->getAdjacency();
	   int idSize = theAdjacency.Size();
	
	// now we have to place the entries in the ID into order in colA
	   for (int i=0; i<idSize; i++) {
	      int row = theAdjacency(i);
	      bool foundPlace = false;
	 
	      for (int j=startLoc; j<lastLoc; j++)
	          if (colA[j] > row) { 
	      // move the entries already there one further on
	      // and place col in current location
	              for (int k=lastLoc; k>j; k--)
		          colA[k] = colA[k-1];
                      colA[j] = row;
		      foundPlace = true;
    	              j = lastLoc;
		  }
		  
	      if (foundPlace == false) // put in at the end
	      	   colA[lastLoc] = row;

	      lastLoc++;
	   }
	   rowStartA[a+1] = lastLoc;;	    
	   startLoc = lastLoc;
	}
    }

    // begin to choose different ordering schema.
    //   cout << "Enter DOF Numberer Type: \n";
    //   cout << "[1] Minimum Degree, [2] Nested Dissection, [3] RCM: ";
    int LSPARSE = 1;
    //   cin >> LSPARSE;

// call "C" function to form elimination tree and do the symbolic factorization.
//    nblks = symFactorization(rowStartA, colA, size, LSPARSE);
    nblks = symFactorization(rowStartA, colA, size, LSPARSE,
			     &xblk, &invp, &rowblks, &begblk, &first, &penv, &diag);

    // invoke setSize() on the Solver
    EigenSolver *theSolvr = this->getSolver();
    int solverOK = theSolvr->setSize();
    if (solverOK < 0) {
	opserr << "WARNING:BandArpackSOE::setSize :";
	opserr << " solver failed setSize()\n";
	return solverOK;
    } 


    return result;
}
int 
DistributedSparseGenColLinSOE::setSize(Graph &theGraph)
{
  int result = 0;
  int oldSize = size;
  int maxNumSubVertex = 0;

  // if subprocess, collect graph, send it off, 
  // vector back containing size of system, etc.
  if (processID != 0) {
    Channel *theChannel = theChannels[0];
    theGraph.sendSelf(0, *theChannel);
    
    static ID data(2);
    theChannel->recvID(0, 0, data);
    size = data(0);
    nnz = data(1);

    ID *subMap = new ID(theGraph.getNumVertex());
    localCol[0] = subMap;
    Vertex *vertex;
    VertexIter &theSubVertices = theGraph.getVertices();
    int cnt = 0;
    while((vertex = theSubVertices()) != 0) 
      (*subMap)(cnt++) = vertex->getTag();

    theChannel->sendID(0, 0, *subMap);

    if (nnz > Asize) { // we have to get more space for A and rowA
      if (rowA != 0)
	delete [] rowA;
      
      rowA = new int[nnz];
	
      if (rowA == 0) {
	opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
	opserr << " ran out of memory for A and rowA with nnz = ";
	opserr << nnz << " \n";
	size = 0; Asize = 0; nnz = 0;
	result =  -1;
      } 
    }

    if (size > Bsize) { // we have to get space for the vectors
	
      if (colStartA != 0) 
	delete [] colStartA;
      colStartA = new int[size+1]; 
      
      if (colStartA == 0) {
	opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
	opserr << " ran out of memory for vectors (size) (";
	opserr << size << ") \n";
	size = 0; Bsize = 0;
	result =  -1;
      }    
    }

    ID rowAdata(rowA, nnz);
    ID colStartAdata(colStartA, size+1);
    theChannel->recvID(0, 0, rowAdata);
    theChannel->recvID(0, 0, colStartAdata);
  } 
  
  // if main domain, collect graphs from all subdomains,
  // merge into 1, number this one, send to subdomains the
  // id containing dof tags & start id's.
  else {

    // from each distributed soe recv it's graph
    // and merge them into master graph
    FEM_ObjectBroker theBroker;
    for (int j=0; j<numChannels; j++) {
      Channel *theChannel = theChannels[j];
      Graph theSubGraph;
      theSubGraph.recvSelf(0, *theChannel, theBroker);
      theGraph.merge(theSubGraph);

      int numSubVertex = theSubGraph.getNumVertex();
      ID *subMap = new ID(numSubVertex);
      localCol[j] = subMap;
      if (numSubVertex > maxNumSubVertex)
	maxNumSubVertex = numSubVertex;
    }

    size = theGraph.getNumVertex();
  
    //
    // determine the number of non-zeros
    //

    Vertex *theVertex;
    VertexIter &theVertices = theGraph.getVertices();
    nnz = 0;
    while ((theVertex = theVertices()) != 0) {
	const ID &theAdjacency = theVertex->getAdjacency();
	nnz += theAdjacency.Size() +1; // the +1 is for the diag entry
    }

    static ID data(2);
    data(0) = size;
    data(1) = nnz;

    // to each distributed soe send the size data
    // and merge them into master graph

    for (int j=0; j<numChannels; j++) {
      Channel *theChannel = theChannels[j];
      theChannel->sendID(0, 0, data);

      ID *subMap = localCol[j];
      theChannel->recvID(0, 0, *subMap);
    }    

    if (nnz > Asize) { // we have to get more space for A and rowA
      if (rowA != 0)
	delete [] rowA;

      if (workArea != 0) 
	delete [] workArea;

      rowA = new int[nnz];
      workArea = new double[nnz];

      sizeWork = nnz;
	
      if (rowA == 0 || workArea == 0) {
	opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
	opserr << " ran out of memory for A and rowA with nnz = ";
	opserr << nnz << " \n";
	size = 0; Asize = 0; nnz = 0;
	result =  -1;
      } 
    }

    if (size > Bsize) { // we have to get space for the vectors
	
      if (colStartA != 0) 
	delete [] colStartA;
      colStartA = new int[size+1]; 
      
      if (colStartA == 0) {
	opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
	opserr << " ran out of memory for vectors (size) (";
	opserr << size << ") \n";
	size = 0; Bsize = 0;
	result =  -1;
      }    
    }

    // fill in colStartA and rowA
    if (size != 0) {
      colStartA[0] = 0;
      int startLoc = 0;
      int lastLoc = 0;
      for (int a=0; a<size; a++) {
	
	theVertex = theGraph.getVertexPtr(a);
	if (theVertex == 0) {
	  opserr << "WARNING:SparseGenColLinSOE::setSize :";
	  opserr << " vertex " << a << " not in graph! - size set to 0\n";
	  size = 0;
	  return -1;
	}
	
	rowA[lastLoc++] = theVertex->getTag(); // place diag in first
	const ID &theAdjacency = theVertex->getAdjacency();
	int idSize = theAdjacency.Size();
	
	// now we have to place the entries in the ID into order in rowA
	for (int i=0; i<idSize; i++) {
	  
	  int row = theAdjacency(i);
	  bool foundPlace = false;
	  // find a place in rowA for current col
	  for (int j=startLoc; j<lastLoc; j++)
	    if (rowA[j] > row) { 
	      // move the entries already there one further on
	      // and place col in current location
	      for (int k=lastLoc; k>j; k--)
		
		rowA[k] = rowA[k-1];
	      rowA[j] = row;
	      foundPlace = true;
	      j = lastLoc;
	    }
	  if (foundPlace == false) // put in at the end
	    rowA[lastLoc] = row;
	  
	  lastLoc++;
	}
	colStartA[a+1] = lastLoc;;	    
	startLoc = lastLoc;
      }
    }


    ID rowAdata(rowA, nnz);
    ID colStartAdata(colStartA, size+1);

    for (int j=0; j<numChannels; j++) {
      Channel *theChannel = theChannels[j];
      theChannel->sendID(0, 0, rowAdata);
      theChannel->sendID(0, 0, colStartAdata);
    }
  }

  if (nnz > Asize) { // we have to get more space for A and rowA
    if (A != 0) 
      delete [] A;
    
    A = new double[nnz];
    
    if (A == 0 || rowA == 0) {
      opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
      opserr << " ran out of memory for A and rowA with nnz = ";
      opserr << nnz << " \n";
      size = 0; Asize = 0; nnz = 0;
      result =  -1;
    } 
    
    Asize = nnz;
  }
  
  // zero the matrix
  for (int i=0; i<Asize; i++)
    A[i] = 0;

  factored = false;

  if (size > Bsize) { // we have to get space for the vectors
    
    // delete the old	
    if (B != 0) delete [] B;
    if (X != 0) delete [] X;
    if (myB != 0) delete [] myB;
    
    // create the new
    B = new double[size];
    X = new double[size];
    myB = new double[size];
    
    if (B == 0 || X == 0 || colStartA == 0 || myB == 0) {
      opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
      opserr << " ran out of memory for vectors (size) (";
      opserr << size << ") \n";
      size = 0; Bsize = 0;
      result =  -1;
    }
    else
      Bsize = size;
  }

  // zero the vectors
  for (int j=0; j<size; j++) {
    B[j] = 0;
    X[j] = 0;
    myB[j] = 0;
  }

  // create new Vectors objects
  if (size != oldSize) {
    if (vectX != 0)
      delete vectX;
    
    if (vectB != 0)
      delete vectB;
    
    vectX = new Vector(X,size);
    vectB = new Vector(B,size);	
    myVectB = new Vector(myB, size);
  }

  LinearSOESolver *theSolvr = this->getSolver();
  int solverOK = theSolvr->setSize();
  if (solverOK < 0) {
    opserr << "WARNING:DistributedSparseGenColLinSOE::setSize :";
    opserr << " solver failed setSize()\n";
    return solverOK;
  }    

  return result;    
}
Example #18
0
int 
MumpsParallelSOE::setSize(Graph &theGraph)
{
  int result = 0;
  int oldSize = size;
  int maxNumSubVertex = 0;
  
  // fist itearte through the vertices of the graph to get nnzLoc and n
  int maxVertexTag = -1;
  Vertex *theVertex;
  int newNNZ = 0;
  size = theGraph.getNumVertex();
  int mySize = size;
  //opserr << "MumpsParallelSOE: size : " << size << endln;

  VertexIter &theVertices = theGraph.getVertices();
  while ((theVertex = theVertices()) != 0) {
    int vertexTag = theVertex->getTag();
    if (vertexTag > maxVertexTag)
      maxVertexTag = vertexTag;
    const ID &theAdjacency = theVertex->getAdjacency();
    newNNZ += theAdjacency.Size() +1; // the +1 is for the diag entry
  }

  if (matType !=  0) {

    // symmetric - allows us to reduce nnz by almost half
    newNNZ -= size;
    newNNZ /= 2;
    newNNZ += size;
  }

  nnz = newNNZ;

  if (processID != 0) {

    //
    // if subprocess, send local max vertexTag (n)
    // recv ax n from P0
    //
    static ID data(1);

    data(0) = maxVertexTag;
    Channel *theChannel = theChannels[0];
    theChannel->sendID(0, 0, data);
    theChannel->recvID(0, 0, data);
    
    size = data(0);

  } else {

    //
    // from each distributed soe recv it's max n and compare; return max n to all
    //

    static ID data(1);
    FEM_ObjectBroker theBroker;
    for (int j=0; j<numChannels; j++) {
      Channel *theChannel = theChannels[j];
      theChannel->recvID(0, 0, data);
      if (data(0) > maxVertexTag)
	maxVertexTag = data(0);
    }

    data(0) = maxVertexTag;

    for (int j=0; j<numChannels; j++) {
      Channel *theChannel = theChannels[j];
      theChannel->sendID(0, 0, data);
    }
    size = maxVertexTag;
  }

  size+=1; // vertices numbered 0 through n-1

  if (nnz > Asize) { // we have to get more space for A and rowA and colA

    if (A != 0) delete [] A;
    if (rowA != 0) delete [] rowA;
    if (colA != 0) delete [] colA;

    A = new double[nnz];    
    rowA = new int[nnz];
    colA = new int[nnz];
      
    for (int i=0; i<nnz; i++) {
      A[i]=0;
      rowA[i]=0;
      colA[i]=0;
    }

    if (rowA == 0 || A == 0 || colA == 0) {
      opserr << "WARNING SparseGenColLinSOE::SparseGenColLinSOE :";
      opserr << " ran out of memory for A and rowA with nnz = ";
      opserr << nnz << " \n";
      size = 0; Asize = 0; nnz = 0;
	result =  -1;
    } 
    Asize = nnz;
  }

  
  if (size > Bsize) { // we have to get space for the vectors

    if (B != 0) delete [] B;
    if (X != 0) delete [] X;    
    if (myB != 0) delete [] myB;
    if (workArea != 0) delete [] workArea;
    if (colStartA != 0)  delete [] colStartA;

    // create the new
    B = new double[size];
    X = new double[size];
    myB = new double[size];
    workArea = new double[size];
    colStartA = new int[size+1]; 
    
    if (B == 0 || X == 0 || colStartA == 0 || workArea == 0 || myB == 0) {
      opserr << "WARNING MumpsSOE::MumpsSOE :";
      opserr << " ran out of memory for vectors (size) (";
      opserr << size << ") \n";
      size = 0; Bsize = 0;
      result =  -1;
    }
    else
      Bsize = size;

  }
  
  // zero the vectors
  for (int j=0; j<size; j++) {
    B[j] = 0;
    X[j] = 0;
    myB[j] = 0;
  }

  // create new Vectors objects
  if (size != oldSize) {
    if (vectX != 0) delete vectX;
    if (vectB != 0) delete vectB;
    if (myVectB != 0) delete myVectB;
    
    vectX = new Vector(X,size);
    vectB = new Vector(B,size);	
    myVectB = new Vector(myB, size);
  }

  // fill in colStartA and rowA
  if (size != 0) {
    colStartA[0] = 0;
    int startLoc = 0;
    int lastLoc = 0;
    for (int a=0; a<size; a++) {
      
      theVertex = theGraph.getVertexPtr(a);
      if (theVertex != 0) {
	
	int vertexTag = theVertex->getTag();
	rowA[lastLoc++] = vertexTag; // place diag in first
	const ID &theAdjacency = theVertex->getAdjacency();
	int idSize = theAdjacency.Size();
	
	// now we have to place the entries in the ID into order in rowA
	
	if (matType != 0) {
	  
	  // symmetric
	  for (int i=0; i<idSize; i++) {
	    int row = theAdjacency(i);
	    if (row > vertexTag) {
	      bool foundPlace = false;
	      // find a place in rowA for current col
	      for (int j=startLoc; j<lastLoc; j++)
		if (rowA[j] > row) { 
		  // move the entries already there one further on
		  // and place col in current location
		  for (int k=lastLoc; k>j; k--)
		    rowA[k] = rowA[k-1];
		  rowA[j] = row;
		  foundPlace = true;
		  j = lastLoc;
		}
	      
	      if (foundPlace == false) // put in at the end
		rowA[lastLoc] = row;
	      lastLoc++;
	    }
	  }
	  
	} else {

	  // unsymmetric	  
	  for (int i=0; i<idSize; i++) {
	    int row = theAdjacency(i);
	    bool foundPlace = false;
	    // find a place in rowA for current col
	    for (int j=startLoc; j<lastLoc; j++)
	      if (rowA[j] > row) { 
		// move the entries already there one further on
		// and place col in current location
		for (int k=lastLoc; k>j; k--)
		  rowA[k] = rowA[k-1];
		rowA[j] = row;
		foundPlace = true;
		j = lastLoc;
	      }
	    if (foundPlace == false) // put in at the end
	      rowA[lastLoc] = row;
	    
	    lastLoc++;
	  }
	}
      }
      colStartA[a+1] = lastLoc;
      startLoc = lastLoc;
    }
  }

  // fill in colA
  int count = 0;
  for (int i=0; i<size; i++) {
    for (int k=colStartA[i]; k<colStartA[i+1]; k++)
      colA[count++] = i;
  }

  LinearSOESolver *theSolvr = this->getSolver();

  int solverOK = theSolvr->setSize();
  if (solverOK < 0) {
    opserr << "WARNING:MumpsParallelSOE::setSize :";
    opserr << " solver failed setSize()\n";
    return solverOK;
  }    

  return result;    
}