DomainPartitioner.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.7 $
00022 // $Date: 2006/01/10 18:17:25 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/domain/partitioner/DomainPartitioner.cpp,v $
00024                                                                         
00025 // Written: fmk 
00026 // Created: Fri Sep 20 15:27:47: 1996
00027 // Revision: A
00028 //
00029 // Description: This file contains the class definition for DomainPartitioner.
00030 // A DomainPartitioner is an object used to partition a PartitionedDomain.
00031 //
00032 // What: "@(#) DomainPartitioner.C, revA"
00033 
00034 #include <DomainPartitioner.h>
00035  
00036 #include <stdlib.h>
00037 #include <GraphPartitioner.h>
00038 #include <PartitionedDomain.h>
00039 #include <Subdomain.h>
00040 #include <SubdomainIter.h>
00041 #include <Node.h>
00042 #include <Element.h>
00043 #include <SP_Constraint.h>
00044 #include <MP_Constraint.h>
00045 #include <NodeIter.h>
00046 #include <ElementIter.h>
00047 #include <MP_ConstraintIter.h>
00048 #include <SP_ConstraintIter.h>
00049 #include <Vertex.h>
00050 #include <VertexIter.h>
00051 #include <Graph.h>
00052 #include <Vector.h>
00053 #include <NodalLoad.h>
00054 #include <ElementalLoad.h>
00055 #include <NodalLoadIter.h>
00056 #include <ElementalLoadIter.h>
00057 #include <LoadBalancer.h>
00058 #include <LoadPatternIter.h>
00059 #include <LoadPattern.h>
00060  
00061 #include <Timer.h>
00062 
00063 #include <MapOfTaggedObjects.h>
00064 
00065 class NodeLocations: public TaggedObject
00066 {
00067 public:
00068   NodeLocations(int tag);
00069   void Print(OPS_Stream &s, int flag =0);  
00070   int addPartition(int partition);
00071   ID nodePartitions;
00072   int numPartitions;
00073 };
00074 
00075 
00076 
00077 NodeLocations::NodeLocations(int tag)
00078 :TaggedObject(tag), 
00079  nodePartitions(0,1), 
00080  numPartitions(0)
00081 {
00082 
00083 }
00084 
00085 void 
00086 NodeLocations::Print(OPS_Stream &s, int flag)
00087 {
00088   s << "NodeLocations tag: " << this->getTag() << " partitions: " << nodePartitions;
00089 }
00090 
00091 int
00092 NodeLocations::addPartition(int partition)
00093 {
00094   if (nodePartitions.insert(partition) != 1)
00095     numPartitions++;
00096   return 0;
00097 }
00098 
00099 DomainPartitioner::DomainPartitioner(GraphPartitioner &theGraphPartitioner)
00100 :myDomain(0),thePartitioner(theGraphPartitioner),theBalancer(0),
00101  theElementGraph(0), theBoundaryElements(0), 
00102  theNodeLocations(0),elementPlace(0), numPartitions(0), partitionFlag(false), usingMainDomain(false)
00103 {
00104 
00105 }    
00106 
00107 DomainPartitioner::DomainPartitioner(GraphPartitioner &theGraphPartitioner,
00108                                      LoadBalancer &theLoadBalancer)
00109 :myDomain(0),thePartitioner(theGraphPartitioner),theBalancer(&theLoadBalancer),
00110  theElementGraph(0), theBoundaryElements(0),
00111  theNodeLocations(0),elementPlace(0), numPartitions(0), partitionFlag(false), usingMainDomain(false)
00112 {
00113     // set the links the loadBalancer needs
00114     theLoadBalancer.setLinks(*this);
00115 }    
00116 
00117 
00118 DomainPartitioner::~DomainPartitioner()
00119 {
00120   if (theBoundaryElements != 0) {
00121     for (int i=0; i<numPartitions; i++)
00122       if (theBoundaryElements[i] != 0)
00123         delete theBoundaryElements[i];
00124     delete []theBoundaryElements;
00125   }
00126 }
00127 
00128 void 
00129 DomainPartitioner::setPartitionedDomain(PartitionedDomain &theDomain)
00130 {
00131     myDomain = &theDomain;
00132 }
00133 
00134 int
00135 DomainPartitioner::partition(int numParts, bool usingMain, int mainPartitionTag)
00136 {
00137   usingMainDomain = usingMain;
00138   mainPartition = mainPartitionTag;
00139 
00140   // first we ensure the partitioned domain has numpart subdomains
00141   // with tags 1 through numparts
00142   for (int i=1; i<=numParts; i++) {
00143     if (i != mainPartition) {
00144       Subdomain *subdomainPtr = myDomain->getSubdomainPtr(i);
00145       if (subdomainPtr == 0) {
00146         opserr << "DomainPartitioner::partition - No Subdomain: ";
00147         opserr << i << " exists\n";
00148         return -1;
00149       }
00150     }
00151   }
00152 
00153   // we get the ele graph from the domain and partition it
00154   //    Graph &theEleGraph = myDomain->getElementGraph();
00155   //    theElementGraph = new Graph(myDomain->getElementGraph());
00156   theElementGraph = &(myDomain->getElementGraph());
00157   
00158   int theError = thePartitioner.partition(*theElementGraph, numParts);
00159   if (theError < 0) {
00160     opserr << "DomainPartitioner::partition";
00161     opserr << " - the graph partioner failed to partition the ";
00162     opserr << "element graph\n";
00163     return -10+theError;
00164   }
00165 
00166   // we create empty graphs for the numParts subdomains,
00167   // in the graphs we place the vertices for the elements on the boundaries
00168   
00169   // we do not invoke the destructor on the individual graphs as 
00170   // this would invoke the destructor on the individual vertices
00171   
00172   if (theBoundaryElements != 0)
00173     delete [] theBoundaryElements;
00174   
00175   theBoundaryElements = new Graph * [numParts];
00176   if (theBoundaryElements == 0) {
00177     opserr << "DomainPartitioner::partition(int numParts)";
00178     opserr << " - ran out of memory\n";
00179     numPartitions = 0;  
00180     return -1;
00181   }
00182   
00183   for (int l=0; l<numParts; l++) {
00184     theBoundaryElements[l] = new Graph(2048); // graphs can grow larger; just an estimate
00185     
00186     if (theBoundaryElements[l] == 0) {
00187       opserr << "DomainPartitioner::partition(int numParts)";
00188       opserr << " - ran out of memory\n";
00189       numPartitions = 0;
00190       return -1;
00191     }
00192   }
00193   
00194   numPartitions = numParts;
00195   
00196   // we now create a MapOfTaggedObjectStorage to store the NodeLocations
00197   // and create a new NodeLocation for each node; adding it to the map object
00198 
00199   theNodeLocations = new MapOfTaggedObjects();
00200   if (theNodeLocations == 0) {
00201     opserr << "DomainPartitioner::partition(int numParts)";
00202     opserr << " - ran out of memory creating MapOfTaggedObjectStorage for node locations\n";
00203     numPartitions = 0;
00204     return -1;
00205   }
00206 
00207   NodeIter &theNodes = myDomain->getNodes();
00208   Node *nodePtr;
00209   while ((nodePtr = theNodes()) != 0) {
00210     NodeLocations *theNodeLocation = new NodeLocations(nodePtr->getTag());
00211     if (theNodeLocation == 0) {
00212       opserr << "DomainPartitioner::partition(int numParts)";
00213       opserr << " - ran out of memory creating NodeLocation for node: " << nodePtr->getTag() << endln;
00214       numPartitions = 0;
00215       return -1;
00216     }
00217     if (theNodeLocations->addComponent(theNodeLocation) == false) {
00218       opserr << "DomainPartitioner::partition(int numParts)";
00219       opserr << " - failed to add NodeLocation to Map for Node: " << nodePtr->getTag() << endln;
00220       numPartitions = 0;
00221       return -1;
00222     }
00223   }
00224 
00225   //
00226   // we now iterate through the vertices of the element graph
00227   // to see if the vertex is a boundary vertex or not - if it is
00228   // we add to the appropriate graph created above. We also set the
00229   // value the color variable of each of the external nodes connected 
00230   // to the element to a value which will indicate that that node will
00231   // have to be added to the subdomain.
00232   //
00233   
00234   VertexIter &theVertexIter = theElementGraph->getVertices();
00235   Vertex *vertexPtr;
00236   while ((vertexPtr = theVertexIter()) != 0) {
00237     int eleTag = vertexPtr->getRef();
00238     int vertexColor = vertexPtr->getColor();
00239     
00240     const ID &adjacency = vertexPtr->getAdjacency();
00241     int size = adjacency.Size();
00242     for (int i=0; i<size; i++) {
00243       Vertex *otherVertex = theElementGraph->getVertexPtr(adjacency(i));
00244       if (otherVertex->getColor() != vertexColor) {
00245         theBoundaryElements[vertexColor-1]->addVertex(vertexPtr,false);
00246         i = size;
00247       }
00248     }
00249     
00250     Element *elePtr = myDomain->getElement(eleTag);
00251     const ID &nodes = elePtr->getExternalNodes();
00252     size = nodes.Size();
00253     for (int j=0; j<size; j++) {
00254       int nodeTag = nodes(j);
00255       TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
00256       if (theTaggedObject == 0) {
00257         opserr << "DomainPartitioner::partition(int numParts)";
00258         opserr << " - failed to find NodeLocation in Map for Node: " << nodePtr->getTag() << " -- A BUG!!\n";
00259         numPartitions = 0;
00260         return -1;      
00261       }
00262       NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
00263       theNodeLocation->addPartition(vertexColor);
00264     }
00265   }
00266 
00267   // now go through the MP_Constraints and ensure the retained node is in every 
00268   // partition the constrained node is in
00269   MP_ConstraintIter &theMPs = myDomain->getMPs();
00270   MP_Constraint *mpPtr;
00271   while ((mpPtr = theMPs()) != 0) {
00272     int retained = mpPtr->getNodeRetained();
00273     int constrained = mpPtr->getNodeConstrained();
00274     
00275     TaggedObject *theRetainedObject = theNodeLocations->getComponentPtr(retained);      
00276     TaggedObject *theConstrainedObject = theNodeLocations->getComponentPtr(constrained);
00277     
00278     if (theRetainedObject == 0 || theConstrainedObject == 0) {
00279       opserr << "DomainPartitioner::partition(int numParts)";
00280       if (theRetainedObject == 0)
00281         opserr << " - failed to find NodeLocation in Map for Node: " << retained << " -- A BUG!!\n";
00282       if (theConstrainedObject == 0)
00283         opserr << " - failed to find NodeLocation in Map for Node: " << constrained << " -- A BUG!!\n";
00284       numPartitions = 0;
00285       return -1;        
00286     }
00287     
00288     NodeLocations *theRetainedLocation = (NodeLocations *)theRetainedObject;
00289     NodeLocations *theConstrainedLocation = (NodeLocations *)theConstrainedObject;
00290     ID &theConstrainedNodesPartitions = theConstrainedLocation->nodePartitions;
00291     int numPartitions = theConstrainedNodesPartitions.Size();
00292     for (int i=0; i<numPartitions; i++) {
00293       theRetainedLocation->addPartition(theConstrainedNodesPartitions(i));
00294     }
00295   }
00296 
00297   // we now add the nodes, 
00298   TaggedObjectIter &theNodeLocationIter = theNodeLocations->getComponents();
00299   TaggedObject *theNodeObject;
00300   while ((theNodeObject = theNodeLocationIter()) != 0) {
00301     NodeLocations *theNodeLocation = (NodeLocations *)theNodeObject;
00302 
00303     int nodeTag = theNodeLocation->getTag();
00304     ID &nodePartitions = theNodeLocation->nodePartitions;
00305     int numPartitions = theNodeLocation->numPartitions;
00306 
00307     for (int i=0; i<numPartitions; i++) {
00308       int partition = nodePartitions(i);          
00309       if (partition != mainPartition) {      
00310         Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
00311         if (numPartitions == 1) {
00312           Node *nodePtr = myDomain->removeNode(nodeTag);
00313           theSubdomain->addNode(nodePtr);
00314         } else {
00315           Node *nodePtr = myDomain->getNode(nodeTag);
00316           theSubdomain->addExternalNode(nodePtr);         
00317         }
00318       }
00319     }
00320   }
00321 
00322   // we now move the elements 
00323   VertexIter &theVertices = theElementGraph->getVertices();
00324   while ((vertexPtr = theVertices()) != 0) {
00325     // move the element
00326     int partition = vertexPtr->getColor();
00327     if (partition != mainPartition) {          
00328       int eleTag = vertexPtr->getRef();
00329       Element *elePtr = myDomain->removeElement(eleTag);  
00330       Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);  
00331       theSubdomain->addElement(elePtr);
00332     }
00333   }
00334 
00335   // now we go through the load patterns and move NodalLoad
00336   // 1) make sure each subdomain has a copy of the partitioneddomains load patterns.
00337   // 2) move nodal loads
00338   // 3) move SP_Constraints
00339   
00340   LoadPatternIter &theLoadPatterns = myDomain->getLoadPatterns();
00341   LoadPattern *theLoadPattern;
00342   while ((theLoadPattern = theLoadPatterns()) != 0) {
00343     int loadPatternTag = theLoadPattern->getTag();
00344 
00345     
00346     // check that each subdomain has a loadPattern with a similar tag and class tag
00347     for (int i=1; i<=numParts; i++) {
00348       if (i != mainPartition) {
00349         Subdomain *theSubdomain = myDomain->getSubdomainPtr(i);
00350         LoadPattern *loadPatternCopy = theSubdomain->getLoadPattern(loadPatternTag);
00351         if (loadPatternCopy == 0) {
00352           LoadPattern *newLoadPattern = theLoadPattern->getCopy();
00353           if (newLoadPattern == 0) {
00354             opserr << "DomaiPartitioner::partition - out of memory creating LoadPatterns\n";
00355             return -1;
00356           }
00357           theSubdomain->addLoadPattern(newLoadPattern);
00358         }
00359       }
00360     }
00361 
00362     // now remove any nodal loads that correspond to internal nodes in a subdomain
00363     // and add them to the appropriate loadpattern in the subdomain
00364     
00365     NodalLoadIter &theNodalLoads = theLoadPattern->getNodalLoads();
00366     NodalLoad *theNodalLoad;
00367     while ((theNodalLoad = theNodalLoads()) != 0) {
00368       int nodeTag = theNodalLoad->getNodeTag();
00369 
00370       TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
00371       if (theTaggedObject == 0) {
00372         opserr << "DomainPartitioner::partition(int numParts)";
00373         opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
00374         numPartitions = 0;
00375         return -1;      
00376       }
00377     
00378       NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
00379       ID &nodePartitions = theNodeLocation->nodePartitions;
00380       int numPartitions = theNodeLocation->numPartitions;
00381       for (int i=0; i<numPartitions; i++) {
00382         int partition = nodePartitions(i);        
00383         if (partition != mainPartition) {      
00384           if (numPartitions == 1) {
00385             Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);
00386             theLoadPattern->removeNodalLoad(theNodalLoad->getTag());
00387             if ((theSubdomain->addNodalLoad(theNodalLoad, loadPatternTag)) != true)
00388               opserr << "DomainPartitioner::partition() - failed to add Nodal Load\n";
00389           }
00390         }
00391       }      
00392     }
00393   
00394     SP_ConstraintIter &theSPs = theLoadPattern->getSPs();
00395     SP_Constraint *spPtr;
00396     while ((spPtr = theSPs()) != 0) {
00397       int nodeTag = spPtr->getNodeTag();
00398       
00399       TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
00400       if (theTaggedObject == 0) {
00401         opserr << "DomainPartitioner::partition(int numParts)";
00402         opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
00403         numPartitions = 0;
00404         return -1;      
00405       }
00406       
00407       NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
00408       ID &nodePartitions = theNodeLocation->nodePartitions;
00409       int numPartitions = theNodeLocation->numPartitions;
00410       for (int i=0; i<numPartitions; i++) {
00411         int partition = nodePartitions(i);        
00412         if (partition != mainPartition) {      
00413           Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
00414           if (numPartitions == 1) 
00415             theLoadPattern->removeSP_Constraint(spPtr->getTag());
00416           int res = theSubdomain->addSP_Constraint(spPtr, loadPatternTag);
00417           if (res < 0)
00418             opserr << "DomainPartitioner::partition() - failed to add SP Constraint\n";
00419         }
00420       }    
00421     }  
00422 
00423     ElementalLoadIter &theLoads = theLoadPattern->getElementalLoads();
00424     ElementalLoad *theLoad;
00425     while ((theLoad = theLoads()) != 0) {
00426       opserr << "DomainPartitioner::partition - REMOVE ELEMENTAL LOADS\n";
00427       // opserr << "DomainPartitioner::partition - REMOVE ELEMENTAL LOADS\n";
00428       //        if (theLoad->getElementTag() == eleTag)
00429       //          theLoadPattern->removeElementalLoad(theLoad->getTag());
00430       // theSubdomain->addElementalLoad(theLoad, loadPatternTag);
00431     }
00432   }
00433 
00434   // add the single point constraints, 
00435   
00436   SP_ConstraintIter &theDomainSP = myDomain->getSPs();
00437   SP_Constraint *spPtr;
00438   while ((spPtr = theDomainSP()) != 0) {
00439     int nodeTag = spPtr->getNodeTag();
00440 
00441     TaggedObject *theTaggedObject = theNodeLocations->getComponentPtr(nodeTag);
00442     if (theTaggedObject == 0) {
00443       opserr << "DomainPartitioner::partition(int numParts)";
00444       opserr << " - failed to find NodeLocation in Map for Node: " << nodeTag << " -- A BUG!!\n";
00445       numPartitions = 0;
00446       return -1;        
00447     }
00448     
00449     NodeLocations *theNodeLocation = (NodeLocations *)theTaggedObject;
00450     ID &nodePartitions = theNodeLocation->nodePartitions;
00451     int numPartitions = theNodeLocation->numPartitions;
00452     for (int i=0; i<numPartitions; i++) {
00453       int partition = nodePartitions(i);          
00454 
00455       if (partition != mainPartition) {      
00456         Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition); 
00457         if (numPartitions == 1) {
00458           myDomain->removeSP_Constraint(spPtr->getTag());
00459         }
00460         int res = theSubdomain->addSP_Constraint(spPtr);
00461         if (res < 0)
00462           opserr << "DomainPartitioner::partition() - failed to add SP Constraint\n";
00463       }
00464     }    
00465   }  
00466 
00467   // move MP_Constraints - add an MP_Constraint to every partition a constrained node is in
00468   MP_ConstraintIter &moreMPs = myDomain->getMPs();
00469   while ((mpPtr = moreMPs()) != 0) {
00470     int constrained = mpPtr->getNodeConstrained();
00471     TaggedObject *theConstrainedObject = theNodeLocations->getComponentPtr(constrained);
00472     NodeLocations *theConstrainedLocation = (NodeLocations *)theConstrainedObject;
00473     ID &theConstrainedNodesPartitions = theConstrainedLocation->nodePartitions;
00474     int numPartitions = theConstrainedLocation->numPartitions;
00475     for (int i=0; i<numPartitions; i++) {
00476       int partition = theConstrainedNodesPartitions(i);
00477       if (partition != mainPartition) {
00478         Subdomain *theSubdomain = myDomain->getSubdomainPtr(partition);
00479         if (numPartitions == 1) 
00480           myDomain->removeMP_Constraint(mpPtr->getTag());
00481         int res = theSubdomain->addMP_Constraint(mpPtr);
00482         if (res < 0)
00483           opserr << "DomainPartitioner::partition() - failed to add MP Constraint\n";
00484       }
00485     }
00486   }
00487 
00488   // now we go through all the subdomains and tell them to update
00489   // their analysis for the new layouts
00490   
00491   SubdomainIter &theSubDomains = myDomain->getSubdomains();
00492   Subdomain *theSubDomain;
00493   while ((theSubDomain = theSubDomains()) != 0) 
00494     theSubDomain->domainChange();
00495   
00496   // we invoke change on the PartitionedDomain
00497   myDomain->domainChange();
00498     
00499   // we are done
00500   partitionFlag = true;
00501 
00502   return 0;
00503 }
00504 
00505 
00506 int
00507 DomainPartitioner::balance(Graph &theWeightedPGraph)
00508 {
00509     int res = 0;
00510 
00511     // check that the object did the partitioning
00512     if (partitionFlag == false) {
00513   opserr << "DomainPartitioner::balance(const Vector &load)";
00514   opserr << " - not partitioned or DomainPartitioner did not partition\n";
00515   return -1;
00516     }
00517 
00518     if (theBalancer != 0) {
00519 
00520         // call on the LoadBalancer to partition                
00521         res = theBalancer->balance(theWeightedPGraph);
00522             
00523         // now invoke domainChanged on Subdomains and PartitionedDomain
00524         SubdomainIter &theSubDomains = myDomain->getSubdomains();
00525         Subdomain *theSubDomain;
00526 
00527         while ((theSubDomain = theSubDomains()) != 0) 
00528           theSubDomain->domainChange();
00529         
00530         // we invoke change on the PartitionedDomain
00531         myDomain->domainChange();
00532     }
00533 
00534     return res;
00535 }
00536 
00537 
00538 
00539 int 
00540 DomainPartitioner::getNumPartitions(void) const
00541 {
00542     return numPartitions;
00543 }
00544 
00545 
00546 
00547 Graph &
00548 DomainPartitioner::getPartitionGraph(void)
00549 {
00550     if (myDomain == 0) {
00551       opserr << "ERROR: DomainPartitioner::getPartitionGraph(void)";
00552       opserr << " - No domain has been set";
00553       exit(-1);
00554     }
00555     return myDomain->getSubdomainGraph();
00556 }
00557 
00558 Graph &
00559 DomainPartitioner::getColoredGraph(void)
00560 {
00561     if (myDomain == 0) {
00562       opserr << "ERROR: DomainPartitioner::getPartitionGraph(void)";
00563       opserr << " - No domain has been set";
00564       exit(0);
00565     }
00566     
00567     return myDomain->getElementGraph();
00568 }
00569 
00570 
00571 int 
00572 DomainPartitioner::swapVertex(int from, int to, int vertexTag,
00573                               bool adjacentVertexNotInOther)
00574 {
00575   opserr << "DomainPartitioner::swapVertex() " << from << " " << to << " " << vertexTag << endln;
00576 
00577   /*
00578   // check that the object did the partitioning
00579   if (partitionFlag == false) {
00580     opserr << "DomainPartitioner::balance(const Vector &load)";
00581     opserr << " - not partitioned or DomainPartitioner did not partition\n";
00582     return -1;
00583   }
00584   
00585   // check that the subdomain exist in partitioned domain
00586   Subdomain *fromSubdomain = myDomain->getSubdomainPtr(from);
00587   if (fromSubdomain == 0) {
00588     opserr << "DomainPartitioner::swapVertex - No from Subdomain: ";
00589     opserr << from << " exists\n";
00590     return -2;
00591   }
00592   Subdomain *toSubdomain = myDomain->getSubdomainPtr(to);
00593   if (toSubdomain == 0) {
00594     opserr << "DomainPartitioner::swapVertex - No to Subdomain: ";
00595     opserr << to << " exists\n";
00596     return -3;
00597   }    
00598   
00599   // remove the vertex from the boundary if there
00600   // if not there we have to get a pointer to it from the ele graph.
00601   
00602   //    Graph &theEleGraph = myDomain->getElementGraph();    
00603   Graph *fromBoundary = theBoundaryElements[from-1];
00604   Graph *toBoundary = theBoundaryElements[to-1];    
00605   Vertex *vertexPtr;
00606   
00607   // get a pointer to the vertex in the element graph
00608   if (adjacentVertexNotInOther  == false) {
00609     vertexPtr = fromBoundary->removeVertex(vertexTag,false);    
00610     if (vertexPtr == 0) 
00611       vertexPtr = theElementGraph->getVertexPtr(vertexTag);
00612 
00613     if (vertexPtr == 0)  // if still 0 no vertex given by tag exists
00614       return -4;
00615   } else { // get a pointer and check vertex not adjacent to another partition
00616     vertexPtr = fromBoundary->getVertexPtr(vertexTag);    
00617     if (vertexPtr == 0) 
00618       vertexPtr = theElementGraph->getVertexPtr(vertexTag);
00619     if (vertexPtr == 0)  // if still 0 no vertex given by tag exists
00620       return -4;        
00621     const ID &adjacent = vertexPtr->getAdjacency();
00622     bool inTo = false;
00623     bool inOther = false;
00624     int adjacentSize = adjacent.Size();
00625     for (int i=0; i<adjacentSize; i++) {
00626       Vertex *other = theElementGraph->getVertexPtr(adjacent(i));
00627       if (other->getColor() == to) 
00628         inTo = true;
00629       else if (other->getColor() != from) {
00630         inOther = true;
00631         i = adjacentSize;
00632       }
00633     }
00634     if (inTo != true || inOther == true) // we cannot remove the vertex
00635       return -5;
00636     // if can remove the vertex from the fromBoundary
00637     Vertex *theVertex = fromBoundary->removeVertex(vertexTag,false);
00638   }
00639   
00640   int eleTag = vertexPtr->getRef();
00641   
00642   //
00643   // in the FROM subdomain we:
00644   //  1. remove the element
00645   //  2. remove all nodes connected to the element divide color by prime
00646   //  3. see if have to add nodes back as external
00647   //  4. remove from the PartitionedDomain if node was external
00648   //  5. add new elements to the boundary vertices for from
00649   
00650   //  1. remove the element from the fromSubdomain
00651     //          this gives us a pointer to the element as well.
00652 
00653     Element *elePtr = fromSubdomain->removeElement(eleTag);
00654     if (elePtr == 0) // if ele not there we can just return but ERROR it should be
00655   return -6;
00656 
00657     //  2. remove all nodes connected to the element divide color by prime    
00658     //  3. add back if still in subdomain
00659     //  4. if node external remove from PartitionedDomains external nodes
00660     int primeFrom = primes(from);
00661     const ID  &nodes1 = elePtr->getExternalNodes(); // create a copy, need after send ele
00662     ID  nodes(nodes1);
00663 
00664     int nodesSize = nodes.Size();
00665     Node **nodesArray = new Node *[nodesSize];
00666     for (int i=0; i<nodesSize; i++) {
00667   int nodeTag = nodes(i);
00668 
00669   // remove the node
00670   Node *nodePtr = fromSubdomain->removeNode(nodeTag);
00671 
00672   (*nodePlace)(nodeTag) /= primeFrom;
00673   nodesArray[i] = nodePtr;
00674         // opserr << "DomainPartitioner::swapVertex -NODE " << *nodePtr;
00675   // add back as external if still needed
00676   if ((*nodePlace)(nodeTag)%primeFrom == 0)
00677       fromSubdomain->addExternalNode(nodePtr);
00678 
00679   // if it was external remove from PartitionedDomains external nodes
00680   int partition = (*nodePlace)(nodeTag);
00681   for (int j=1; j<=numPartitions; j++) 
00682       if (j != from) {
00683     int prime = primes(j);
00684     if (partition%prime == 0) {
00685         myDomain->removeExternalNode(nodeTag);
00686         j = numPartitions+1;
00687     }
00688       }
00689     }
00690 
00691     // 5. add new elements to boundary vertices of from if connected to
00692     //    vertex we just removed and of color of from and not already in boundary
00693 
00694     const ID &eleAdjacent = vertexPtr->getAdjacency();
00695     int eleAdjacentSize = eleAdjacent.Size();
00696 
00697     for (int a=0; a<eleAdjacentSize; a++) {
00698         int otherEleVertexTag = eleAdjacent(a);
00699         Vertex *other = fromBoundary->getVertexPtr(otherEleVertexTag);
00700         if (other == 0) {
00701             other = theElementGraph->getVertexPtr(otherEleVertexTag);
00702             if (other->getColor() == from)
00703                 fromBoundary->addVertex(other,false);
00704         }
00705     }
00706 
00707 
00708     
00709     // in the TO subdomain we:
00710     //  1. remove all nodes connected to the element, may or may not be there
00711     //     if there don't divide by primeTo. 
00712     //  2. mark all connecting nodes of elements as belonging to To
00713     //  3. add the nodes, checking if external or internal
00714     //  3. add the element
00715     //  4. change the vertex color to be to and add vertex to boundary
00716     //     also see if we can reduce the size of boundary
00717     //     of boundary of to vertices
00718 
00719     //  1. remove all nodes connected to the element, may or may not be there
00720     //      if there divide by primeTo, do this as may have been added as extnl
00721     int primeTo = primes(to);
00722     for (int l=0; l<nodesSize; l++) {    
00723   int nodeTag = nodesArray[l]->getTag();
00724   int nodeColor = (*nodePlace)(nodeTag);
00725   if (nodeColor % primeTo == 0) {
00726       Node *nodePtr;
00727       nodePtr = toSubdomain->removeNode(nodes(l));
00728   }
00729     }
00730 
00731 
00732     for (int m=0; m<nodesSize; m++) {
00733   Node *nodePtr = nodesArray[m];
00734   int nodeTag = nodePtr->getTag();
00735   
00736   //  2. mark all connecting nodes of elements as belonging to To      
00737   (*nodePlace)(nodeTag) *= primeTo;
00738 
00739   //  3. add the nodes, checking if external or internal  
00740   int internal = 0;
00741   for (int n=1; n<=numPartitions; n++) 
00742       if (n != to) {
00743     int prime = primes(n);
00744     if ((*nodePlace)(nodeTag)%prime == 0) { // its external
00745         internal = 1;
00746         n = numPartitions+1;
00747     }
00748       }
00749   
00750   if (internal == 0)
00751       toSubdomain->addNode(nodePtr);
00752   else {
00753       toSubdomain->addExternalNode(nodePtr);
00754       myDomain->addNode(nodePtr);
00755   }
00756     }
00757 
00758     delete [] nodesArray; // DELETE nodesArray here should not use nodePtrs
00759                           // after here as node objects deleted if parallel    
00760     
00761     //  3. add the element
00762     
00763     toSubdomain->addElement(elePtr);
00764     
00765     //  4. change the vertex color to be to and add vertex to boundary
00766     //     also see if we can reduce the size of to's boundary vertices
00767 
00768 
00769     vertexPtr->setColor(to);
00770     toBoundary->addVertex(vertexPtr,false);
00771 
00772     for (int n=0; n<eleAdjacentSize; n++) {
00773         int otherEleVertexTag = eleAdjacent(n);
00774         Vertex *other = toBoundary->removeVertex(otherEleVertexTag,false);
00775         if (other != 0) {
00776             const ID &othersAdjacency = other->getAdjacency();
00777             int otherSize = othersAdjacency.Size();
00778             for (int b=0; b<otherSize; b++) {
00779                 int anotherEleVertexTag = othersAdjacency(b);
00780                 Vertex *otherOther = theElementGraph->getVertexPtr(anotherEleVertexTag);
00781                 if (otherOther->getColor() != to) {
00782                     toBoundary->addVertex(other,false);
00783                     b=otherSize;
00784                 }
00785             }
00786         }
00787     }
00788 
00789 
00790     // now remove any SP_Constraints that may have been external to 
00791     // PartitionedDomain and are now internal to toSubdomain
00792     SP_ConstraintIter &theSPs = myDomain->getSPs();
00793     SP_Constraint *spPtr;
00794     while ((spPtr = theSPs()) != 0) {
00795   int nodeTag = spPtr->getNodeTag();
00796   for (int i=0; i<nodesSize; i++) {
00797       if (nodeTag == nodes(i)) {
00798     int internal = 0;
00799     for (int j=1; j<=numPartitions; j++) 
00800         if (j != to) {
00801       int prime = primes(j);
00802       if ((*nodePlace)(nodeTag)%prime == 0) {
00803           internal = 1;
00804           j = numPartitions+1;
00805       }
00806         }
00807     if (internal == 0) { // add to toSubdomain if inteernal
00808         myDomain->removeSP_Constraint(spPtr->getTag());
00809         toSubdomain->addSP_Constraint(spPtr);
00810     }
00811       }
00812   }
00813     }
00814 
00815     
00816     
00817     // now remove any SP_Constraints that may have been internal to fromSubdomain
00818     // and are now external to PartitionedDomain or internal to toSubdomain 
00819     SP_ConstraintIter &theSPs2 = fromSubdomain->getSPs();
00820     while ((spPtr = theSPs2()) != 0) {
00821   int nodeTag = spPtr->getNodeTag();
00822   for (int i=0; i<nodesSize; i++) {
00823       if (nodeTag == nodes(i)) {
00824     fromSubdomain->removeSP_Constraint(spPtr->getTag());
00825     int internal = 0;
00826     for (int j=1; j<=numPartitions; j++) 
00827         if (j != to) {
00828       int prime = primes(j);
00829       if ((*nodePlace)(nodeTag)%prime == 0) {
00830           internal = 1;
00831           j = numPartitions+1;
00832       }
00833         }
00834     if (internal == 0) 
00835         toSubdomain->addSP_Constraint(spPtr);
00836     else
00837         myDomain->addSP_Constraint(spPtr);
00838       }
00839   }
00840     }
00841 
00842 
00843 
00844   */
00845     /*
00846     // now remove any NodalLoads that may have been external to 
00847     // PartitionedDomain and are now internal to toSubdomain
00848     NodalLoadIter &theNodalLoads = myDomain->getNodalLoads();
00849     NodalLoad *loadPtr;
00850     while ((loadPtr = theNodalLoads()) != 0) {
00851   int nodeTag = loadPtr->getNodeTag();
00852   for (int i=0; i<nodesSize; i++) {
00853       if (nodeTag == nodes(i)) {
00854     int internal = 0;
00855     for (int j=1; j<=numPartitions; j++) 
00856         if (j != to) {
00857       int prime = primes(j);
00858       if ((*nodePlace)(nodeTag)%prime == 0) {
00859           internal = 1;
00860           j = numPartitions+1;
00861       }
00862         }
00863     if (internal == 0) { // add to toSubdomain if inteernal
00864         myDomain->removeNodalLoad(loadPtr->getTag());
00865         toSubdomain->addNodalLoad(loadPtr);
00866     }
00867       }
00868   }
00869     }
00870 
00871 
00872     // now remove any NodalLoads that may have been internal to fromSubdomain
00873     // and are now external to PartitionedDomain or internal to toSubdomain 
00874 
00875     NodalLoadIter &theNodalLoads2 = myDomain->getNodalLoads();
00876     while ((loadPtr = theNodalLoads2()) != 0) {
00877   int nodeTag = loadPtr->getNodeTag();
00878   for (int i=0; i<nodesSize; i++) {
00879       if (nodeTag == nodes(i)) {
00880     fromSubdomain->removeNodalLoad(loadPtr->getTag());
00881     int internal = 0;
00882     for (int j=1; j<=numPartitions; j++) 
00883         if (j != to) {
00884       int prime = primes(j);
00885       if ((*nodePlace)(nodeTag)%prime == 0) {
00886           internal = 1;
00887           j = numPartitions+1;
00888       }
00889         }
00890     if (internal == 0) 
00891         toSubdomain->addNodalLoad(loadPtr);
00892     else
00893         myDomain->addNodalLoad(loadPtr);
00894       }  
00895   }
00896     }
00897     */
00898 
00899     return 0;
00900 
00901 }
00902 
00903 
00904 
00905 // method to move from from to to, all elements on the interface of 
00906 // from that are adjacent with to.
00907 
00908 int 
00909 DomainPartitioner::swapBoundary(int from, int to, bool adjacentVertexNotInOther)
00910           
00911 {
00912   opserr << "DomainPartitioner::swapBoundary: from "  << from << " to " << to << endln;
00913   /***********************************************************************************
00914     opserr << "DomainPartitioner::swapBoundary from " << from << "  to " << to << endln;
00915     Timer timer;
00916     timer.start();
00917 
00918     // check that the object did the partitioning
00919     if (partitionFlag == false) {
00920   opserr << "DomainPartitioner::balance(const Vector &load)";
00921   opserr << " - not partitioned or DomainPartitioner did not partition\n";
00922   return -1;
00923     }
00924 
00925     // check that the subdomains exist in partitioned domain
00926     Subdomain *fromSubdomain = myDomain->getSubdomainPtr(from);
00927     if (fromSubdomain == 0) {
00928   opserr << "DomainPartitioner::swapBoundary - No from Subdomain: ";
00929   opserr << from << " exists\n";
00930   return -2;
00931     }
00932 
00933     Subdomain *toSubdomain = myDomain->getSubdomainPtr(to);
00934     if (toSubdomain == 0) {
00935   opserr << "DomainPartitioner::swapBoundary - No to Subdomain: ";
00936   opserr << to << " exists\n";
00937   return -3;
00938     }    
00939 
00940     // get the element graph
00941     //    Graph &theEleGraph = myDomain->getElementGraph();    
00942     Graph *fromBoundary = theBoundaryElements[from-1];
00943     Graph *toBoundary = theBoundaryElements[to-1];
00944 
00945     // into a new graph place the vertices that are to be swapped
00946     Graph *swapVertices = new Graph(fromBoundary->getNumVertex());
00947 
00948     VertexIter &swappableVertices = fromBoundary->getVertices();
00949     Vertex *vertexPtr;
00950 
00951     while ((vertexPtr = swappableVertices()) != 0) {
00952         if (adjacentVertexNotInOther == false) {   
00953             const ID &adjacency=vertexPtr->getAdjacency();
00954             int size = adjacency.Size();
00955             for (int i=0; i<size; i++) {
00956                 int otherTag = adjacency(i);
00957                 Vertex *otherVertex = toBoundary->getVertexPtr(otherTag);
00958                 if (otherVertex != 0) {
00959                     swapVertices->addVertex(vertexPtr,false);
00960                     i = size;
00961                 }
00962             }
00963         }
00964         else {
00965             const ID &adjacent = vertexPtr->getAdjacency();
00966             bool inTo = false;
00967             bool inOther = false;
00968             int adjacentSize = adjacent.Size();
00969             for (int i=0; i<adjacentSize; i++) {
00970                 Vertex *other = theElementGraph->getVertexPtr(adjacent(i));
00971                 if (other->getColor() == to) 
00972                     inTo = true;
00973                 else if (other->getColor() != from) {
00974                     inOther = true;
00975                     i = adjacentSize;
00976                 }
00977             }
00978             if (inTo == true && inOther == false) { // we remove the vertex
00979                 swapVertices->addVertex(vertexPtr,false);
00980                 vertexPtr->setColor(to);
00981             }
00982         }
00983     }
00984 
00985     //
00986     // in the FROM subdomain we:
00987     //  1. remove the elements corresponding to the vertices
00988     //  2. remove all nodes connected to the elements divide color by prime
00989     //  3. see if have to add nodes back as external
00990     //  4. remove from the PartitionedDomain if node was external
00991     //  5. add new elements to the boundary vertices for from
00992 
00993     // 1. first remove all the elements from from subdomain
00994     VertexIter &verticesToSwap = swapVertices->getVertices();
00995 
00996     int numEleToSwap = swapVertices->getNumVertex();
00997     Element **elementsArray = new Element *[numEleToSwap];
00998 
00999     int count =0; 
01000     int numCannotRemove =0;
01001     for (int i=0; i<numEleToSwap; i++) {
01002       vertexPtr = verticesToSwap();
01003   if (vertexPtr == 0) 
01004       return -1;
01005 
01006   int vertexTag = vertexPtr->getTag();
01007   int eleTag = vertexPtr->getRef();
01008 
01009   // remove the vertex from fromBoundary, set color to to
01010   // and add to toBoundary
01011   bool inFrom = true;
01012   vertexPtr = fromBoundary->removeVertex(vertexTag,false);
01013 
01014 
01015   if (inFrom == true) {
01016       vertexPtr->setColor(to);
01017       toBoundary->addVertex(vertexPtr,false);
01018       Element *elePtr = fromSubdomain->removeElement(eleTag);
01019       if (elePtr == 0) // if ele not there we can just return IT SHOULD BE
01020     return -4;
01021       elementsArray[count] = elePtr;
01022       count++;
01023   }
01024   else  // we cannot remove the element
01025       numCannotRemove++;
01026     }
01027     numEleToSwap -= numCannotRemove;
01028 
01029     //  2. remove all nodes connected to the elements divide color by prime    
01030     //     for each element and add back if still in subdomain
01031     //  3. add back if still in subdomain
01032     //  4. if node external remove from PartitionedDomains external nodes
01033 
01034     // first determine which nodes to remove
01035     int primeFrom = primes(from);
01036     int primeTo = primes(to);
01037     int numNodToSwap = 0;
01038     ID nodesToRemove(0,128);
01039     for (int j=0; j<numEleToSwap; j++) {
01040   Element *elePtr = elementsArray[j];
01041   const ID  &nodes = elePtr->getExternalNodes(); 
01042   
01043   int nodesSize = nodes.Size();
01044 
01045   for (int k=0; k<nodesSize; k++) {
01046       int nodeTag = nodes(k);
01047       int loc = nodesToRemove.getLocation(nodeTag);
01048       if (loc < 0) {
01049     nodesToRemove[numNodToSwap] = nodeTag;
01050     numNodToSwap++;
01051       }
01052       (*nodePlace)(nodeTag) /= primeFrom;    
01053       (*nodePlace)(nodeTag) *= primeTo;        
01054   }
01055     }
01056 
01057     // remove the nodes
01058     Node **nodesArray = new Node *[numNodToSwap];  
01059     for (int k=0; k<numNodToSwap; k++) {
01060   int nodeTag = nodesToRemove(k); 
01061   Node *nodePtr = fromSubdomain->removeNode(nodeTag);
01062   nodesArray[k] = nodePtr;
01063 
01064   // add the node back to from if still external
01065   if ((*nodePlace)(nodeTag)%primeFrom == 0)
01066       fromSubdomain->addExternalNode(nodePtr);
01067 
01068   // if it was external remove from PartitionedDomains external nodes
01069   int partition = (*nodePlace)(nodeTag);
01070   for (int j=1; j<=numPartitions; j++) 
01071       if (j != from) {
01072     int prime = primes(j);
01073     if (partition%prime == 0) {
01074         myDomain->removeExternalNode(nodeTag);
01075         j = numPartitions+1;
01076     }
01077       }
01078     }
01079 
01080     // 5. add new vertices to boundary vertices of from if connected to
01081     //    vertex we just removed and of color of from and not already in boundary
01082 
01083     VertexIter &verticesToSwap2 = swapVertices->getVertices();
01084     while ((vertexPtr = verticesToSwap2()) != 0) {
01085   const ID &vertexAdjacent = vertexPtr->getAdjacency();
01086   int vertexAdjacentSize = vertexAdjacent.Size();
01087 
01088         for (int a=0; a<vertexAdjacentSize; a++) {
01089             int otherEleVertexTag = vertexAdjacent(a);
01090             Vertex *other = fromBoundary->getVertexPtr(otherEleVertexTag);
01091             if (other == 0) {
01092                 other = theElementGraph->getVertexPtr(otherEleVertexTag);
01093                 if (other->getColor() == from)
01094                     fromBoundary->addVertex(other,false);
01095             }
01096         }       
01097     }
01098 
01099 
01100     // in the TO subdomain we:
01101     //  1. remove all nodes connected to the element, may or may not be there
01102     //     if there don't divide by primeTo. 
01103     //  2. mark all connecting nodes of elements as belonging to To
01104     //  3. add the nodes, checking if external or internal
01105     //  3. add the element
01106     //  4. change the vertex color to be to and add vertex to boundary
01107     //     also see if we can reduce the size of boundary
01108     //     of boundary of to vertices
01109 
01110     //  1. remove all nodes connected to the element, may or may not be there
01111     //      if there divide by primeTo, do this as may have been added as extnl
01112 
01113     for (int l=0; l<numNodToSwap; l++) {    
01114   int nodeTag = nodesArray[l]->getTag();
01115   Node *nodePtr;
01116   nodePtr = toSubdomain->removeNode(nodesToRemove(l));
01117     }
01118 
01119 
01120     for (int m=0; m<numNodToSwap; m++) {
01121   Node *nodePtr = nodesArray[m];
01122   int nodeTag = nodePtr->getTag();
01123   
01124   //  3. add the nodes, checking if external or internal  
01125   int internal = 0;
01126   for (int n=1; n<=numPartitions; n++) 
01127       if (n != to) {
01128     int prime = primes(n);
01129     if ((*nodePlace)(nodeTag)%prime == 0) { // its external
01130         internal = 1;
01131         n = numPartitions+1;
01132     }
01133       }
01134   
01135   if (internal == 0)
01136       toSubdomain->addNode(nodePtr);
01137   else {
01138       toSubdomain->addExternalNode(nodePtr);
01139       myDomain->addNode(nodePtr);
01140   }
01141     }
01142 
01143 
01144     delete [] nodesArray; // DELETE nodesArray here should not use nodePtrs
01145                           // after here as node objects deleted if parallel    
01146     
01147     //  3. add the elements
01148     for (int a=0; a<numEleToSwap; a++)
01149   toSubdomain->addElement(elementsArray[a]);
01150 
01151 
01152     //  4. change the vertex color to be to and add vertex to boundary
01153     //     also see if we can reduce the size of to's boundary vertices
01154 
01155     VertexIter &verticesToSwap3 = swapVertices->getVertices();
01156     while ((vertexPtr = verticesToSwap3()) != 0) {
01157         const ID &vertexAdjacent = vertexPtr->getAdjacency();
01158         int vertexAdjacentSize = vertexAdjacent.Size();
01159         for (int n=0; n<vertexAdjacentSize; n++) {
01160             int otherEleVertexTag = vertexAdjacent(n);
01161             Vertex *other = toBoundary->removeVertex(otherEleVertexTag,false);
01162             if (other != 0) {
01163                 const ID &othersAdjacency = other->getAdjacency();
01164                 int otherSize = othersAdjacency.Size();
01165                 for (int b=0; b<otherSize; b++) {
01166                     int anotherEleVertexTag = othersAdjacency(b);
01167                     Vertex *otherOther 
01168                         = theElementGraph->getVertexPtr(anotherEleVertexTag);
01169                     if (otherOther->getColor() != to) {
01170                         toBoundary->addVertex(other,false);
01171                         b=otherSize;
01172                     }
01173                 }
01174             }
01175         }
01176     }
01177 
01178     // now remove any SP_Constraints that may have been external to 
01179     // PartitionedDomain and are now internal to toSubdomain
01180     SP_ConstraintIter &theSPs = myDomain->getSPs();
01181     SP_Constraint *spPtr;
01182     while ((spPtr = theSPs()) != 0) {
01183   int nodeTag = spPtr->getNodeTag();
01184   int loc = nodesToRemove.getLocation(nodeTag);
01185   if (loc >= 0) {
01186       int internal = 0;
01187       for (int j=1; j<=numPartitions; j++) 
01188     if (j != to) {
01189         int prime = primes(j);
01190         if ((*nodePlace)(nodeTag)%prime == 0) {
01191       internal = 1;
01192       j = numPartitions+1;
01193         }
01194     }
01195       if (internal == 0) { // add to toSubdomain if inteernal
01196     myDomain->removeSP_Constraint(spPtr->getTag());
01197     toSubdomain->addSP_Constraint(spPtr);
01198       }
01199   }
01200     }
01201 
01202     
01203     // now remove any SP_Constraints that may have been internal to fromSubdomain
01204     // and are now external to PartitionedDomain or internal to toSubdomain 
01205     SP_ConstraintIter &theSPs2 = fromSubdomain->getSPs();
01206     while ((spPtr = theSPs2()) != 0) {
01207   int nodeTag = spPtr->getNodeTag();
01208   int loc = nodesToRemove.getLocation(nodeTag);
01209   if (loc >= 0) {
01210       fromSubdomain->removeSP_Constraint(spPtr->getTag());
01211       int internal = 0;
01212       for (int j=1; j<=numPartitions; j++) 
01213     if (j != to) {
01214         int prime = primes(j);
01215         if ((*nodePlace)(nodeTag)%prime == 0) {
01216       internal = 1;
01217       j = numPartitions+1;
01218         }
01219     }
01220       if (internal == 0) 
01221     toSubdomain->addSP_Constraint(spPtr);
01222       else
01223     myDomain->addSP_Constraint(spPtr);
01224   }  
01225     }
01226 
01227     // now remove any NodalLoads that may have been external to 
01228     // PartitionedDomain and are now internal to toSubdomain
01229     NodalLoadIter &theNodalLoads = myDomain->getNodalLoads();
01230     NodalLoad *loadPtr;
01231     while ((loadPtr = theNodalLoads()) != 0) {
01232   int nodeTag = loadPtr->getNodeTag();
01233   int loc = nodesToRemove.getLocation(nodeTag);
01234   if (loc >= 0) {
01235 
01236       int internal = 0;
01237       for (int j=1; j<=numPartitions; j++) 
01238     if (j != to) {
01239         int prime = primes(j);
01240         if ((*nodePlace)(nodeTag)%prime == 0) {
01241       internal = 1;
01242       j = numPartitions+1;
01243         }
01244     }
01245       if (internal == 0) { // add to toSubdomain if inteernal
01246     myDomain->removeNodalLoad(loadPtr->getTag());
01247     toSubdomain->addNodalLoad(loadPtr);
01248       }
01249   }
01250     }
01251 
01252 
01253     // now remove any NodalLoads that may have been internal to fromSubdomain
01254     // and are now external to PartitionedDomain or internal to toSubdomain 
01255 
01256     NodalLoadIter &theNodalLoads2 = myDomain->getNodalLoads();
01257     while ((loadPtr = theNodalLoads2()) != 0) {
01258   int nodeTag = loadPtr->getNodeTag();
01259   int loc = nodesToRemove.getLocation(nodeTag);
01260   if (loc >= 0) {
01261       fromSubdomain->removeNodalLoad(loadPtr->getTag());
01262       int internal = 0;
01263       for (int j=1; j<=numPartitions; j++) 
01264     if (j != to) {
01265         int prime = primes(j);
01266         if ((*nodePlace)(nodeTag)%prime == 0) {
01267       internal = 1;
01268       j = numPartitions+1;
01269         }
01270     }
01271       if (internal == 0) 
01272     toSubdomain->addNodalLoad(loadPtr);
01273       else
01274     myDomain->addNodalLoad(loadPtr);
01275   }  
01276     }
01277 
01278 
01279     delete swapVertices;
01280 
01281     timer.pause();
01282     opserr << "DomainPartitioner::swapBoundary DONE" << timer.getReal() << endln;
01283 
01284   ***************************************************************************/
01285     return 0;
01286 }
01287 
01288 
01289 int 
01290 DomainPartitioner::releaseVertex(int from, 
01291                                  int vertexTag, 
01292                                  Graph &theWeightedPartitionGraph,
01293                                  bool mustReleaseToLighter,
01294                                  double factorGreater,
01295                                  bool adjacentVertexNotInOther)
01296 {
01297   // check that the object did the partitioning
01298   if (partitionFlag == false) {
01299     opserr << "DomainPartitioner::balance(const Vector &load)";
01300     opserr << " - not partitioned or DomainPartitioner did not partition\n";
01301     return -1;
01302   }
01303   
01304   // we first check the vertex is on the fromBoundary
01305   Subdomain *fromSubdomain = myDomain->getSubdomainPtr(from);
01306   if (fromSubdomain == 0) {
01307     opserr << "DomainPartitioner::swapVertex - No from Subdomain: ";
01308     opserr << from << " exists\n";
01309     return -1;
01310   }
01311 
01312   // get the vertex from the boundary vertices of from
01313   // Graph &theEleGraph = myDomain->getElementGraph();    
01314   Graph *fromBoundary = theBoundaryElements[from-1];
01315     
01316   Vertex *vertexPtr = fromBoundary->getVertexPtr(vertexTag);
01317   if (vertexPtr == 0) 
01318     vertexPtr = theElementGraph->getVertexPtr(vertexTag);
01319   
01320   if (vertexPtr == 0)  // if still 0 no vertex given by tag exists
01321     return -3;
01322 
01323   ID attraction(numPartitions+1);
01324   attraction.Zero();
01325 
01326   // determine the attraction to the other partitions
01327   const ID &adjacent = vertexPtr->getAdjacency();
01328   int numAdjacent = adjacent.Size();
01329   for (int i=0; i<numAdjacent; i++) {
01330     int otherTag = adjacent(i);
01331     Vertex *otherVertex = theElementGraph->getVertexPtr(otherTag);
01332     int otherPartition = otherVertex->getColor();
01333     if (otherPartition != from)
01334       attraction(otherPartition) += 1;
01335   }
01336   
01337   // determine the other partition the vertex is most attracted to
01338   int partition = 1;
01339   int maxAttraction = attraction(1);
01340   for (int j=2; j<=numPartitions; j++)
01341     if (attraction(j) > maxAttraction) {
01342       partition = j;
01343       maxAttraction = attraction(j);
01344     }
01345 
01346   // swap the vertex
01347   if (mustReleaseToLighter == false)
01348     return swapVertex(from, partition, vertexTag, adjacentVertexNotInOther);
01349   
01350   else { // check the other partition has a lighter load
01351     Vertex *fromVertex = theWeightedPartitionGraph.getVertexPtr(from);
01352     Vertex *toVertex = theWeightedPartitionGraph.getVertexPtr(partition);           
01353     
01354     double fromWeight = fromVertex->getWeight();
01355     double toWeight  = toVertex->getWeight();
01356     
01357     if (fromWeight == toWeight)
01358       opserr << "DomainPartitioner::releaseVertex - TO CHANGE >= to >\n";
01359 
01360     if (fromWeight >= toWeight) {
01361       if (toWeight == 0.0) 
01362         return swapVertex(from,partition,vertexTag,adjacentVertexNotInOther);       
01363       if (fromWeight/toWeight > factorGreater)        
01364         return swapVertex(from,partition,vertexTag,adjacentVertexNotInOther);       
01365     }
01366   }
01367   
01368   return 0;
01369 }
01370 
01371 
01372 
01373 int 
01374 DomainPartitioner::releaseBoundary(int from, 
01375            Graph &theWeightedPartitionGraph,  
01376            bool mustReleaseToLighter,
01377            double factorGreater,
01378            bool adjacentVertexNotInOther)
01379 {
01380     // check that the object did the partitioning
01381     if (partitionFlag == false) {
01382       opserr << "DomainPartitioner::balance(const Vector &load)";
01383       opserr << " - not partitioned or DomainPartitioner did not partition\n";
01384       return -1;
01385     }
01386 
01387     // we first get a pointer to fromSubdomain & the fromBoundary
01388     Subdomain *fromSubdomain = myDomain->getSubdomainPtr(from);
01389     if (fromSubdomain == 0) {
01390       opserr << "DomainPartitioner::swapVertex - No from Subdomain: ";
01391       opserr << from << " exists\n";
01392       return -1;
01393     }
01394 
01395     //    Graph &theEleGraph = myDomain->getElementGraph();    
01396     Graph *fromBoundary = theBoundaryElements[from-1];
01397 
01398     // into a new graph place the vertices on the fromBoundary
01399     // we cannot use fromBoundary as this would empty all the nodes
01400     // as fromBoundary changes in called methods
01401 
01402     Graph *swapVertices = new Graph(fromBoundary->getNumVertex());
01403 
01404     VertexIter &swappableVertices = fromBoundary->getVertices();
01405     Vertex *vertexPtr;
01406 
01407     while ((vertexPtr = swappableVertices()) != 0) 
01408       swapVertices->addVertex(vertexPtr,false);
01409 
01410     // release all the vertices in the swapVertices
01411     VertexIter &verticesToSwap = swapVertices->getVertices();
01412     while ((vertexPtr = verticesToSwap()) != 0)
01413       releaseVertex(from,
01414                     vertexPtr->getTag(),
01415                     theWeightedPartitionGraph,
01416                     mustReleaseToLighter,
01417                     factorGreater,
01418                     adjacentVertexNotInOther);
01419     
01420     delete swapVertices;    
01421 
01422     return 0;
01423 }
01424 

Generated on Mon Oct 23 15:05:01 2006 for OpenSees by doxygen 1.5.0