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; } } }
//! @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; }
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; }
//! @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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }