|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 00050 #ifndef _ZOLTAN2_PARTITIONINGPROBLEM_HPP_ 00051 #define _ZOLTAN2_PARTITIONINGPROBLEM_HPP_ 00052 00053 #include <Zoltan2_Problem.hpp> 00054 #include <Zoltan2_PartitioningAlgorithms.hpp> 00055 #include <Zoltan2_PartitioningSolution.hpp> 00056 #include <Zoltan2_PartitioningSolutionQuality.hpp> 00057 #include <Zoltan2_GraphModel.hpp> 00058 #include <Zoltan2_IdentifierModel.hpp> 00059 #include <Zoltan2_IntegerRangeList.hpp> 00060 #include <Zoltan2_MachineRepresentation.hpp> 00061 #include <Zoltan2_TaskMapping.hpp> 00062 00063 #ifndef _WIN32 00064 #include <unistd.h> 00065 #else 00066 #include <process.h> 00067 #define NOMINMAX 00068 #include <windows.h> 00069 #endif 00070 00071 #ifdef HAVE_ZOLTAN2_OVIS 00072 #include <ovis.h> 00073 #endif 00074 00075 namespace Zoltan2{ 00076 00100 template<typename Adapter> 00101 class PartitioningProblem : public Problem<Adapter> 00102 { 00103 public: 00104 00105 typedef typename Adapter::scalar_t scalar_t; 00106 typedef typename Adapter::zgid_t zgid_t; 00107 typedef typename Adapter::gno_t gno_t; 00108 typedef typename Adapter::lno_t lno_t; 00109 typedef typename Adapter::part_t part_t; 00110 typedef typename Adapter::user_t user_t; 00111 typedef typename Adapter::base_adapter_t base_adapter_t; 00112 00113 #ifdef HAVE_ZOLTAN2_MPI 00114 typedef Teuchos::OpaqueWrapper<MPI_Comm> mpiWrapper_t; 00117 PartitioningProblem(Adapter *A, ParameterList *p, MPI_Comm comm): 00118 Problem<Adapter>(A,p,comm), solution_(), 00119 problemComm_(), problemCommConst_(), 00120 inputType_(InvalidAdapterType), 00121 graphFlags_(), idFlags_(), coordFlags_(), algName_(), 00122 numberOfWeights_(), partIds_(), partSizes_(), 00123 numberOfCriteria_(), levelNumberParts_(), hierarchical_(false), 00124 timer_(), metricsRequested_(false), metrics_() 00125 { 00126 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) modelAvail_[i]=false; 00127 initializeProblem(); 00128 } 00129 #endif 00130 00132 PartitioningProblem(Adapter *A, ParameterList *p): 00133 Problem<Adapter>(A,p), solution_(), 00134 problemComm_(), problemCommConst_(), 00135 inputType_(InvalidAdapterType), 00136 graphFlags_(), idFlags_(), coordFlags_(), algName_(), 00137 numberOfWeights_(), 00138 partIds_(), partSizes_(), numberOfCriteria_(), 00139 levelNumberParts_(), hierarchical_(false), timer_(), 00140 metricsRequested_(false), metrics_() 00141 { 00142 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) modelAvail_[i]=false; 00143 initializeProblem(); 00144 } 00145 00147 PartitioningProblem(Adapter *A, ParameterList *p, 00148 RCP<const Teuchos::Comm<int> > &comm): 00149 Problem<Adapter>(A,p,comm), solution_(), 00150 problemComm_(), problemCommConst_(), 00151 inputType_(InvalidAdapterType), 00152 graphFlags_(), idFlags_(), coordFlags_(), algName_(), 00153 numberOfWeights_(), 00154 partIds_(), partSizes_(), numberOfCriteria_(), 00155 levelNumberParts_(), hierarchical_(false), timer_(), 00156 metricsRequested_(false), metrics_() 00157 { 00158 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) modelAvail_[i]=false; 00159 initializeProblem(); 00160 } 00161 00164 ~PartitioningProblem() {}; 00165 00167 // 00168 // \param updateInputData If true this indicates that either 00169 // this is the first attempt at solution, or that we 00170 // are computing a new solution and the input data has 00171 // changed since the previous solution was computed. 00172 // By input data we mean coordinates, topology, or weights. 00173 // If false, this indicates that we are computing a 00174 // new solution using the same input data was used for 00175 // the previous solution, even though the parameters 00176 // may have been changed. 00177 // 00178 // For the sake of performance, we ask the caller to set \c updateInputData 00179 // to false if he/she is computing a new solution using the same input data, 00180 // but different problem parameters, than that which was used to compute 00181 // the most recent solution. 00182 00183 void solve(bool updateInputData=true ); 00184 00186 // when a point lies on a part boundary, the lowest part 00187 // number on that boundary is returned. 00188 // Note that not all partitioning algorithms will support 00189 // this method. 00190 // 00191 // \param dim : the number of dimensions specified for the point in space 00192 // \param point : the coordinates of the point in space; array of size dim 00193 // \return the part number of a part overlapping the given point 00194 // 00195 // TODO: This method might be more appropriate in a partitioning solution 00196 // TODO: But then the solution would need to know about the algorithm. 00197 // TODO: Consider moving the algorithm to the partitioning solution. 00198 part_t pointAssign(int dim, scalar_t *point) 00199 { 00200 part_t p; 00201 try { 00202 if (this->algorithm_ == Teuchos::null) 00203 throw std::logic_error("no partitioning algorithm has been run yet"); 00204 00205 p = this->algorithm_->pointAssign(dim, point); 00206 } 00207 Z2_FORWARD_EXCEPTIONS 00208 return p; 00209 } 00210 00212 // This method allocates memory for the return argument, but does not 00213 // control that memory. The user is responsible for freeing the 00214 // memory. 00215 // 00216 // \param dim : (in) the number of dimensions specified for the box 00217 // \param lower : (in) the coordinates of the lower corner of the box; 00218 // array of size dim 00219 // \param upper : (in) the coordinates of the upper corner of the box; 00220 // array of size dim 00221 // \param nPartsFound : (out) the number of parts overlapping the box 00222 // \param partsFound : (out) array of parts overlapping the box 00223 // TODO: This method might be more appropriate in a partitioning solution 00224 // TODO: But then the solution would need to know about the algorithm. 00225 // TODO: Consider moving the algorithm to the partitioning solution. 00226 void boxAssign(int dim, scalar_t *lower, scalar_t *upper, 00227 size_t &nPartsFound, part_t **partsFound) 00228 { 00229 try { 00230 if (this->algorithm_ == Teuchos::null) 00231 throw std::logic_error("no partitioning algorithm has been run yet"); 00232 00233 this->algorithm_->boxAssign(dim, lower, upper, nPartsFound, partsFound); 00234 } 00235 Z2_FORWARD_EXCEPTIONS 00236 } 00237 00239 // 00240 // \return a reference to the solution to the most recent solve(). 00241 00242 const PartitioningSolution<Adapter> &getSolution() { 00243 return *(solution_.getRawPtr()); 00244 }; 00245 00254 const scalar_t getWeightImbalance(int idx=0) const { 00255 scalar_t imb = 0; 00256 if (!metrics_.is_null()) 00257 metrics_->getWeightImbalance(imb, idx); 00258 00259 return imb; 00260 } 00261 00266 ArrayRCP<const MetricValues<scalar_t> > getMetrics() const { 00267 if (metrics_.is_null()){ 00268 ArrayRCP<const MetricValues<scalar_t> > emptyMetrics; 00269 return emptyMetrics; 00270 } 00271 else 00272 return metrics_->getMetrics(); 00273 } 00274 00280 void printMetrics(std::ostream &os) const { 00281 if (metrics_.is_null()) 00282 os << "No metrics available." << endl; 00283 else 00284 metrics_->printMetrics(os); 00285 }; 00286 00325 void setPartSizes(int len, part_t *partIds, scalar_t *partSizes, 00326 bool makeCopy=true) 00327 { 00328 setPartSizesForCriteria(0, len, partIds, partSizes, makeCopy); 00329 } 00330 00365 void setPartSizesForCriteria(int criteria, int len, part_t *partIds, 00366 scalar_t *partSizes, bool makeCopy=true) ; 00367 /* 00368 void setMachine(MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> *machine); 00369 */ 00372 void resetParameters(ParameterList *params) 00373 { 00374 Problem<Adapter>::resetParameters(params); // creates new environment 00375 if (timer_.getRawPtr() != NULL) 00376 this->env_->setTimer(timer_); 00377 } 00378 00383 const RCP<const Environment> & getEnvironment() const 00384 { 00385 return this->envConst_; 00386 } 00387 00388 private: 00389 void initializeProblem(); 00390 00391 void createPartitioningProblem(bool newData); 00392 00393 RCP<PartitioningSolution<Adapter> > solution_; 00394 00395 RCP<MachineRepresentation <typename Adapter::base_adapter_t::scalar_t> > machine_; 00396 00397 RCP<Comm<int> > problemComm_; 00398 RCP<const Comm<int> > problemCommConst_; 00399 00400 BaseAdapterType inputType_; 00401 00402 //ModelType modelType_; 00403 bool modelAvail_[MAX_NUM_MODEL_TYPES]; 00404 00405 modelFlag_t graphFlags_; 00406 modelFlag_t idFlags_; 00407 modelFlag_t coordFlags_; 00408 std::string algName_; 00409 00410 int numberOfWeights_; 00411 00412 // Suppose Array<part_t> partIds = partIds_[w]. If partIds.size() > 0 00413 // then the user supplied part sizes for weight index "w", and the sizes 00414 // corresponding to the Ids in partIds are partSizes[w]. 00415 // 00416 // If numberOfWeights_ >= 0, then there is an Id and Sizes array for 00417 // for each weight. Otherwise the user did not supply object weights, 00418 // but they can still specify part sizes. 00419 // So numberOfCriteria_ is numberOfWeights_ or one, whichever is greater. 00420 00421 ArrayRCP<ArrayRCP<part_t> > partIds_; 00422 ArrayRCP<ArrayRCP<scalar_t> > partSizes_; 00423 int numberOfCriteria_; 00424 00425 // Number of parts to be computed at each level in hierarchical partitioning. 00426 00427 ArrayRCP<int> levelNumberParts_; 00428 bool hierarchical_; 00429 00430 // Create a Timer if the user asked for timing stats. 00431 00432 RCP<TimerManager> timer_; 00433 00434 // Did the user request metrics? 00435 00436 bool metricsRequested_; 00437 RCP<const PartitioningSolutionQuality<Adapter> > metrics_; 00438 }; 00440 00441 /* 00442 template <typename Adapter> 00443 void PartitioningProblem<Adapter>::setMachine(MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> *machine){ 00444 this->machine_ = RCP<MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> > (machine, false); 00445 } 00446 */ 00447 00448 00449 template <typename Adapter> 00450 void PartitioningProblem<Adapter>::initializeProblem() 00451 { 00452 HELLO; 00453 00454 this->env_->debug(DETAILED_STATUS, "PartitioningProblem::initializeProblem"); 00455 00456 if (getenv("DEBUGME")){ 00457 #ifndef _WIN32 00458 std::cout << getpid() << std::endl; 00459 sleep(15); 00460 #else 00461 std::cout << _getpid() << std::endl; 00462 Sleep(15000); 00463 #endif 00464 } 00465 00466 #ifdef HAVE_ZOLTAN2_OVIS 00467 ovis_enabled(this->comm_->getRank()); 00468 #endif 00469 00470 // Create a copy of the user's communicator. 00471 00472 problemComm_ = this->comm_->duplicate(); 00473 problemCommConst_ = rcp_const_cast<const Comm<int> > (problemComm_); 00474 00475 machine_ = RCP <Zoltan2::MachineRepresentation<typename Adapter::scalar_t> >(new Zoltan2::MachineRepresentation<typename Adapter::scalar_t>(problemComm_)); 00476 00477 // Number of criteria is number of user supplied weights if non-zero. 00478 // Otherwise it is 1 and uniform weight is implied. 00479 00480 numberOfWeights_ = this->inputAdapter_->getNumWeightsPerID(); 00481 00482 numberOfCriteria_ = (numberOfWeights_ > 1) ? numberOfWeights_ : 1; 00483 00484 inputType_ = this->inputAdapter_->adapterType(); 00485 00486 // The Caller can specify part sizes in setPartSizes(). If he/she 00487 // does not, the part size arrays are empty. 00488 00489 ArrayRCP<part_t> *noIds = new ArrayRCP<part_t> [numberOfCriteria_]; 00490 ArrayRCP<scalar_t> *noSizes = new ArrayRCP<scalar_t> [numberOfCriteria_]; 00491 00492 partIds_ = arcp(noIds, 0, numberOfCriteria_, true); 00493 partSizes_ = arcp(noSizes, 0, numberOfCriteria_, true); 00494 00495 if (this->env_->getDebugLevel() >= DETAILED_STATUS){ 00496 std::ostringstream msg; 00497 msg << problemComm_->getSize() << " procs," 00498 << numberOfWeights_ << " user-defined weights\n"; 00499 this->env_->debug(DETAILED_STATUS, msg.str()); 00500 } 00501 00502 this->env_->memory("After initializeProblem"); 00503 } 00504 00505 template <typename Adapter> 00506 void PartitioningProblem<Adapter>::setPartSizesForCriteria( 00507 int criteria, int len, part_t *partIds, scalar_t *partSizes, bool makeCopy) 00508 { 00509 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid length", 00510 len>= 0, BASIC_ASSERTION); 00511 00512 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid criteria", 00513 criteria >= 0 && criteria < numberOfCriteria_, BASIC_ASSERTION); 00514 00515 if (len == 0){ 00516 partIds_[criteria] = ArrayRCP<part_t>(); 00517 partSizes_[criteria] = ArrayRCP<scalar_t>(); 00518 return; 00519 } 00520 00521 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid arrays", 00522 partIds && partSizes, BASIC_ASSERTION); 00523 00524 // The global validity of the partIds and partSizes arrays is performed 00525 // by the PartitioningSolution, which computes global part distribution and 00526 // part sizes. 00527 00528 part_t *z2_partIds = NULL; 00529 scalar_t *z2_partSizes = NULL; 00530 bool own_memory = false; 00531 00532 if (makeCopy){ 00533 z2_partIds = new part_t [len]; 00534 z2_partSizes = new scalar_t [len]; 00535 this->env_->localMemoryAssertion(__FILE__, __LINE__, len, z2_partSizes); 00536 memcpy(z2_partIds, partIds, len * sizeof(part_t)); 00537 memcpy(z2_partSizes, partSizes, len * sizeof(scalar_t)); 00538 own_memory=true; 00539 } 00540 else{ 00541 z2_partIds = partIds; 00542 z2_partSizes = partSizes; 00543 } 00544 00545 partIds_[criteria] = arcp(z2_partIds, 0, len, own_memory); 00546 partSizes_[criteria] = arcp(z2_partSizes, 0, len, own_memory); 00547 } 00548 00549 template <typename Adapter> 00550 void PartitioningProblem<Adapter>::solve(bool updateInputData) 00551 { 00552 HELLO; 00553 this->env_->debug(DETAILED_STATUS, "Entering solve"); 00554 00555 // Create the computational model. 00556 00557 this->env_->timerStart(MACRO_TIMERS, "create problem"); 00558 00559 createPartitioningProblem(updateInputData); 00560 00561 this->env_->timerStop(MACRO_TIMERS, "create problem"); 00562 00563 // TODO: If hierarchical_ 00564 00565 // Create the solution. The algorithm will query the Solution 00566 // for part and weight information. The algorithm will 00567 // update the solution with part assignments and quality 00568 // metrics. The Solution object itself will convert our internal 00569 // global numbers back to application global Ids if needed. 00570 00571 RCP<const IdentifierMap<user_t> > idMap = 00572 this->baseModel_->getIdentifierMap(); 00573 00574 PartitioningSolution<Adapter> *soln = NULL; 00575 00576 this->env_->timerStart(MACRO_TIMERS, "create solution"); 00577 00578 try{ 00579 soln = new PartitioningSolution<Adapter>( 00580 this->envConst_, problemCommConst_, idMap, numberOfWeights_, 00581 partIds_.view(0, numberOfCriteria_), 00582 partSizes_.view(0, numberOfCriteria_)); 00583 } 00584 Z2_FORWARD_EXCEPTIONS; 00585 00586 solution_ = rcp(soln); 00587 00588 this->env_->timerStop(MACRO_TIMERS, "create solution"); 00589 00590 this->env_->memory("After creating Solution"); 00591 00592 // Call the algorithm 00593 00594 try { 00595 if (algName_ == std::string("scotch")) { 00596 00597 this->algorithm_ = rcp(new AlgPTScotch<Adapter>(this->envConst_, 00598 problemComm_, 00599 this->graphModel_)); 00600 this->algorithm_->partition(solution_); 00601 } 00602 00603 else if (algName_ == std::string("parmetis")) { 00604 00605 this->algorithm_ = rcp(new AlgParMETIS<Adapter>(this->envConst_, 00606 problemComm_, 00607 this->graphModel_)); 00608 this->algorithm_->partition(solution_); 00609 } 00610 00611 else if (algName_ == std::string("block")) { 00612 00613 this->algorithm_ = rcp(new AlgBlock<Adapter>(this->envConst_, 00614 problemComm_, this->identifierModel_)); 00615 this->algorithm_->partition(solution_); 00616 } 00617 00618 else if (algName_ == std::string("rcb")) { 00619 00620 this->algorithm_ = rcp(new AlgRCB<Adapter>(this->envConst_, problemComm_, 00621 this->coordinateModel_)); 00622 this->algorithm_->partition(solution_); 00623 } 00624 00625 else if (algName_ == std::string("multijagged")) { 00626 00627 this->algorithm_ = rcp(new Zoltan2_AlgMJ<Adapter>(this->envConst_, 00628 problemComm_, 00629 this->coordinateModel_)); 00630 this->algorithm_->partition(solution_); 00631 } 00632 00633 else if (algName_ == std::string("wolf")) { 00634 00635 this->algorithm_ = rcp(new AlgWolf<Adapter>(this->envConst_, 00636 problemComm_,this->graphModel_, 00637 this->coordinateModel_)); 00638 00639 // need to add coordModel, make sure this is built 00640 this->algorithm_->partition(solution_); 00641 } 00642 else { 00643 throw std::logic_error("partitioning algorithm not supported"); 00644 } 00645 } 00646 Z2_FORWARD_EXCEPTIONS; 00647 00648 //if mapping is requested 00649 const Teuchos::ParameterEntry *pe = this->envConst_->getParameters().getEntryPtr("mapping_type"); 00650 int mapping_type = -1; 00651 if (pe){ 00652 mapping_type = pe->getValue(&mapping_type); 00653 } 00654 //if mapping is 0 -- coordinate mapping 00655 00656 if (mapping_type == 0){ 00657 00658 //part_t *task_communication_xadj = NULL, *task_communication_adj = NULL; 00659 00660 Zoltan2::CoordinateTaskMapper <Adapter, part_t> *ctm= 00661 new Zoltan2::CoordinateTaskMapper<Adapter,part_t>( 00662 problemComm_.getRawPtr(), 00663 machine_.getRawPtr(), 00664 this->coordinateModel_.getRawPtr(), 00665 solution_.getRawPtr(), 00666 this->envConst_.getRawPtr() 00667 //,task_communication_xadj, 00668 //task_communication_adj 00669 ); 00670 //for now just delete the object. 00671 delete ctm; 00672 } 00673 else if (mapping_type == 1){ 00674 //if mapping is 1 -- graph mapping 00675 } 00676 00677 if (metricsRequested_){ 00678 typedef PartitioningSolution<Adapter> ps_t; 00679 typedef PartitioningSolutionQuality<Adapter> psq_t; 00680 00681 psq_t *quality = NULL; 00682 RCP<const ps_t> solutionConst = rcp_const_cast<const ps_t>(solution_); 00683 RCP<const Adapter> adapter = rcp(this->inputAdapter_, false); 00684 00685 try{ 00686 quality = new psq_t(this->envConst_, problemCommConst_, adapter, 00687 solutionConst); 00688 } 00689 Z2_FORWARD_EXCEPTIONS 00690 00691 metrics_ = rcp(quality); 00692 } 00693 00694 this->env_->debug(DETAILED_STATUS, "Exiting solve"); 00695 } 00696 00697 template <typename Adapter> 00698 void PartitioningProblem<Adapter>::createPartitioningProblem(bool newData) 00699 { 00700 HELLO; 00701 this->env_->debug(DETAILED_STATUS, 00702 "PartitioningProblem::createPartitioningProblem"); 00703 00704 using std::string; 00705 using Teuchos::ParameterList; 00706 00707 // A Problem object may be reused. The input data may have changed and 00708 // new parameters or part sizes may have been set. 00709 // 00710 // Save these values in order to determine if we need to create a new model. 00711 00712 //ModelType previousModel = modelType_; 00713 bool prevModelAvail[MAX_NUM_MODEL_TYPES]; 00714 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) 00715 { 00716 prevModelAvail[i] = modelAvail_[i]; 00717 } 00718 00719 00720 modelFlag_t previousGraphModelFlags = graphFlags_; 00721 modelFlag_t previousIdentifierModelFlags = idFlags_; 00722 modelFlag_t previousCoordinateModelFlags = coordFlags_; 00723 00724 //modelType_ = InvalidModel; 00725 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) 00726 { 00727 modelAvail_[i] = false; 00728 } 00729 00730 graphFlags_.reset(); 00731 idFlags_.reset(); 00732 coordFlags_.reset(); 00733 00735 // It's possible at this point that the Problem may want to 00736 // add problem parameters to the parameter list in the Environment. 00737 // 00738 // Since the parameters in the Environment have already been 00739 // validated in its constructor, a new Environment must be created: 00741 // Teuchos::RCP<const Teuchos::Comm<int> > oldComm = this->env_->comm_; 00742 // const ParameterList &oldParams = this->env_->getUnvalidatedParameters(); 00743 // 00744 // ParameterList newParams = oldParams; 00745 // newParams.set("new_parameter", "new_value"); 00746 // 00747 // ParameterList &newPartParams = newParams.sublist("partitioning"); 00748 // newPartParams.set("new_partitioning_parameter", "its_value"); 00749 // 00750 // this->env_ = rcp(new Environment(newParams, oldComm)); 00752 00753 this->env_->debug(DETAILED_STATUS, " parameters"); 00754 Environment &env = *(this->env_); 00755 ParameterList &pl = env.getParametersNonConst(); 00756 00757 std::string defString("default"); 00758 00759 // Did the user ask for computation of quality metrics? 00760 00761 int yesNo=0; 00762 const Teuchos::ParameterEntry *pe = pl.getEntryPtr("compute_metrics"); 00763 if (pe){ 00764 yesNo = pe->getValue<int>(&yesNo); 00765 metricsRequested_ = true; 00766 } 00767 00768 // Did the user specify a computational model? 00769 00770 std::string model(defString); 00771 pe = pl.getEntryPtr("model"); 00772 if (pe) 00773 model = pe->getValue<std::string>(&model); 00774 00775 // Did the user specify an algorithm? 00776 00777 std::string algorithm(defString); 00778 pe = pl.getEntryPtr("algorithm"); 00779 if (pe) 00780 algorithm = pe->getValue<std::string>(&algorithm); 00781 00782 // Possible algorithm requirements that must be conveyed to the model: 00783 00784 bool needConsecutiveGlobalIds = false; 00785 bool removeSelfEdges= false; 00786 00788 // Determine algorithm, model, and algorithm requirements. This 00789 // is a first pass. Feel free to change this and add to it. 00790 00791 if (algorithm != defString) 00792 { 00793 00794 // Figure out the model required by the algorithm 00795 if (algorithm == std::string("block") || 00796 algorithm == std::string("random") || 00797 algorithm == std::string("cyclic") ){ 00798 00799 //modelType_ = IdentifierModelType; 00800 modelAvail_[IdentifierModelType] = true; 00801 00802 algName_ = algorithm; 00803 needConsecutiveGlobalIds = true; 00804 } 00805 else if (algorithm == std::string("rcb") || 00806 algorithm == std::string("rib") || 00807 algorithm == std::string("multijagged") || 00808 algorithm == std::string("hsfc")) 00809 { 00810 //modelType_ = CoordinateModelType; 00811 modelAvail_[CoordinateModelType]=true; 00812 00813 algName_ = algorithm; 00814 } 00815 else if (algorithm == std::string("metis") || 00816 algorithm == std::string("parmetis") || 00817 algorithm == std::string("scotch") || 00818 algorithm == std::string("ptscotch")) 00819 { 00820 00821 //modelType_ = GraphModelType; 00822 modelAvail_[GraphModelType]=true; 00823 00824 algName_ = algorithm; 00825 removeSelfEdges = true; 00826 needConsecutiveGlobalIds = true; 00827 } 00828 else if (algorithm == std::string("patoh") || 00829 algorithm == std::string("phg")) 00830 { 00831 // if ((modelType_ != GraphModelType) && 00832 // (modelType_ != HypergraphModelType) ) 00833 if ((modelAvail_[GraphModelType]==false) && 00834 (modelAvail_[HypergraphModelType]==false) ) 00835 { 00836 //modelType_ = HypergraphModelType; 00837 modelAvail_[HypergraphModelType]=true; 00838 } 00839 algName_ = algorithm; 00840 needConsecutiveGlobalIds = true; 00841 } 00842 else if (algorithm == std::string("wolf")) 00843 { 00844 modelAvail_[GraphModelType]=true; 00845 modelAvail_[CoordinateModelType]=true; 00846 algName_ = algorithm; 00847 } 00848 else 00849 { 00850 // Parameter list should ensure this does not happen. 00851 throw std::logic_error("parameter list algorithm is invalid"); 00852 } 00853 } 00854 else if (model != defString) 00855 { 00856 // Figure out the algorithm suggested by the model. 00857 if (model == std::string("hypergraph")) 00858 { 00859 //modelType_ = HypergraphModelType; 00860 modelAvail_[HypergraphModelType]=true; 00861 00862 if (problemComm_->getSize() > 1) 00863 algName_ = std::string("phg"); 00864 else 00865 algName_ = std::string("patoh"); 00866 needConsecutiveGlobalIds = true; 00867 } 00868 else if (model == std::string("graph")) 00869 { 00870 //modelType_ = GraphModelType; 00871 modelAvail_[GraphModelType]=true; 00872 00873 #ifdef HAVE_ZOLTAN2_SCOTCH 00874 if (problemComm_->getSize() > 1) 00875 algName_ = std::string("ptscotch"); 00876 else 00877 algName_ = std::string("scotch"); 00878 removeSelfEdges = true; 00879 needConsecutiveGlobalIds = true; 00880 #else 00881 #ifdef HAVE_ZOLTAN2_PARMETIS 00882 if (problemComm_->getSize() > 1) 00883 algName_ = std::string("parmetis"); 00884 else 00885 algName_ = std::string("metis"); 00886 removeSelfEdges = true; 00887 needConsecutiveGlobalIds = true; 00888 #else 00889 if (problemComm_->getSize() > 1) 00890 algName_ = std::string("phg"); 00891 else 00892 algName_ = std::string("patoh"); 00893 removeSelfEdges = true; 00894 needConsecutiveGlobalIds = true; 00895 #endif 00896 #endif 00897 } 00898 else if (model == std::string("geometry")) 00899 { 00900 //modelType_ = CoordinateModelType; 00901 modelAvail_[CoordinateModelType]=true; 00902 00903 algName_ = std::string("rcb"); 00904 } 00905 else if (model == std::string("ids")) 00906 { 00907 //modelType_ = IdentifierModelType; 00908 modelAvail_[IdentifierModelType]=true; 00909 00910 algName_ = std::string("block"); 00911 needConsecutiveGlobalIds = true; 00912 } 00913 else 00914 { 00915 // Parameter list should ensure this does not happen. 00916 env.localBugAssertion(__FILE__, __LINE__, 00917 "parameter list model type is invalid", 1, BASIC_ASSERTION); 00918 } 00919 } 00920 else 00921 { 00922 // Determine an algorithm and model suggested by the input type. 00923 // TODO: this is a good time to use the time vs. quality parameter 00924 // in choosing an algorithm, and setting some parameters 00925 00926 if (inputType_ == MatrixAdapterType) 00927 { 00928 //modelType_ = HypergraphModelType; 00929 modelAvail_[HypergraphModelType]=true; 00930 00931 if (problemComm_->getSize() > 1) 00932 algName_ = std::string("phg"); 00933 else 00934 algName_ = std::string("patoh"); 00935 } 00936 else if (inputType_ == GraphAdapterType || 00937 inputType_ == MeshAdapterType) 00938 { 00939 //modelType_ = GraphModelType; 00940 modelAvail_[GraphModelType]=true; 00941 00942 if (problemComm_->getSize() > 1) 00943 algName_ = std::string("phg"); 00944 else 00945 algName_ = std::string("patoh"); 00946 } 00947 else if (inputType_ == CoordinateAdapterType) 00948 { 00949 //modelType_ = CoordinateModelType; 00950 modelAvail_[CoordinateModelType]=true; 00951 00952 if(algName_ != std::string("multijagged")) 00953 algName_ = std::string("rcb"); 00954 } 00955 else if (inputType_ == VectorAdapterType || 00956 inputType_ == IdentifierAdapterType) 00957 { 00958 //modelType_ = IdentifierModelType; 00959 modelAvail_[IdentifierModelType]=true; 00960 00961 algName_ = std::string("block"); 00962 } 00963 else{ 00964 // This should never happen 00965 throw std::logic_error("input type is invalid"); 00966 } 00967 } 00968 00969 // Hierarchical partitioning? 00970 00971 Array<int> valueList; 00972 pe = pl.getEntryPtr("topology"); 00973 00974 if (pe){ 00975 valueList = pe->getValue<Array<int> >(&valueList); 00976 00977 if (!Zoltan2::noValuesAreInRangeList<int>(valueList)){ 00978 int *n = new int [valueList.size() + 1]; 00979 levelNumberParts_ = arcp(n, 0, valueList.size() + 1, true); 00980 int procsPerNode = 1; 00981 for (int i=0; i < valueList.size(); i++){ 00982 levelNumberParts_[i+1] = valueList[i]; 00983 procsPerNode *= valueList[i]; 00984 } 00985 // Number of parts in the first level 00986 levelNumberParts_[0] = env.numProcs_ / procsPerNode; 00987 00988 if (env.numProcs_ % procsPerNode > 0) 00989 levelNumberParts_[0]++; 00990 } 00991 } 00992 else{ 00993 levelNumberParts_.clear(); 00994 } 00995 00996 hierarchical_ = levelNumberParts_.size() > 0; 00997 00998 // Object to be partitioned? (rows, columns, etc) 00999 01000 std::string objectOfInterest(defString); 01001 pe = pl.getEntryPtr("objects_to_partition"); 01002 if (pe) 01003 objectOfInterest = pe->getValue<std::string>(&objectOfInterest); 01004 01006 // Set model creation flags, if any. 01007 01008 this->env_->debug(DETAILED_STATUS, " models"); 01009 // if (modelType_ == GraphModelType) 01010 if (modelAvail_[GraphModelType]==true) 01011 { 01012 01013 // Any parameters in the graph sublist? 01014 01015 std::string symParameter(defString); 01016 pe = pl.getEntryPtr("symmetrize_graph"); 01017 if (pe){ 01018 symParameter = pe->getValue<std::string>(&symParameter); 01019 if (symParameter == std::string("transpose")) 01020 graphFlags_.set(SYMMETRIZE_INPUT_TRANSPOSE); 01021 else if (symParameter == std::string("bipartite")) 01022 graphFlags_.set(SYMMETRIZE_INPUT_BIPARTITE); 01023 } 01024 01025 int sgParameter = 0; 01026 pe = pl.getEntryPtr("subset_graph"); 01027 if (pe) 01028 sgParameter = pe->getValue<int>(&sgParameter); 01029 01030 if (sgParameter == 1) 01031 graphFlags_.set(GRAPH_IS_A_SUBSET_GRAPH); 01032 01033 // Any special behaviors required by the algorithm? 01034 01035 if (removeSelfEdges) 01036 graphFlags_.set(SELF_EDGES_MUST_BE_REMOVED); 01037 01038 if (needConsecutiveGlobalIds) 01039 graphFlags_.set(IDS_MUST_BE_GLOBALLY_CONSECUTIVE); 01040 01041 // How does user input map to vertices and edges? 01042 01043 if (inputType_ == MatrixAdapterType){ 01044 if (objectOfInterest == defString || 01045 objectOfInterest == std::string("matrix_rows") ) 01046 graphFlags_.set(VERTICES_ARE_MATRIX_ROWS); 01047 else if (objectOfInterest == std::string("matrix_columns")) 01048 graphFlags_.set(VERTICES_ARE_MATRIX_COLUMNS); 01049 else if (objectOfInterest == std::string("matrix_nonzeros")) 01050 graphFlags_.set(VERTICES_ARE_MATRIX_NONZEROS); 01051 } 01052 01053 else if (inputType_ == MeshAdapterType){ 01054 if (objectOfInterest == defString || 01055 objectOfInterest == std::string("mesh_nodes") ) 01056 graphFlags_.set(VERTICES_ARE_MESH_NODES); 01057 else if (objectOfInterest == std::string("mesh_elements")) 01058 graphFlags_.set(VERTICES_ARE_MESH_ELEMENTS); 01059 } 01060 } 01061 //MMW is it ok to remove else? 01062 // else if (modelType_ == IdentifierModelType) 01063 if (modelAvail_[IdentifierModelType]==true) 01064 { 01065 01066 // Any special behaviors required by the algorithm? 01067 01068 if (needConsecutiveGlobalIds) 01069 idFlags_.set(IDS_MUST_BE_GLOBALLY_CONSECUTIVE); 01070 } 01071 // else if (modelType_ == CoordinateModelType) 01072 if (modelAvail_[CoordinateModelType]==true) 01073 { 01074 01075 // Any special behaviors required by the algorithm? 01076 01077 if (needConsecutiveGlobalIds) 01078 coordFlags_.set(IDS_MUST_BE_GLOBALLY_CONSECUTIVE); 01079 } 01080 01081 01082 if ( newData || 01083 (modelAvail_[GraphModelType]!=prevModelAvail[GraphModelType]) || 01084 (modelAvail_[HypergraphModelType]!=prevModelAvail[HypergraphModelType]) || 01085 (modelAvail_[CoordinateModelType]!=prevModelAvail[CoordinateModelType]) || 01086 (modelAvail_[IdentifierModelType]!=prevModelAvail[IdentifierModelType]) || 01087 // (modelType_ != previousModel) || 01088 (graphFlags_ != previousGraphModelFlags) || 01089 (coordFlags_ != previousCoordinateModelFlags) || 01090 (idFlags_ != previousIdentifierModelFlags) ) 01091 { 01092 01093 // Create the computational model. 01094 // Models are instantiated for base input adapter types (mesh, 01095 // matrix, graph, and so on). We pass a pointer to the input 01096 // adapter, cast as the base input type. 01097 01098 //KDD Not sure why this shadow declaration is needed 01099 //KDD Comment out for now; revisit later if problems. 01100 //KDD const Teuchos::ParameterList pl = this->envConst_->getParameters(); 01101 //bool exceptionThrow = true; 01102 01103 if(modelAvail_[GraphModelType]==false && modelAvail_[HypergraphModelType]==false && 01104 modelAvail_[CoordinateModelType]==false && modelAvail_[IdentifierModelType]==false) 01105 { 01106 cout << __func__zoltan2__ << " Invalid model" << endl; 01107 } 01108 else 01109 { 01110 if(modelAvail_[GraphModelType]==true) 01111 { 01112 this->env_->debug(DETAILED_STATUS, " building graph model"); 01113 this->graphModel_ = rcp(new GraphModel<base_adapter_t>( 01114 this->baseInputAdapter_, this->envConst_, problemComm_, graphFlags_)); 01115 01116 this->baseModel_ = rcp_implicit_cast<const Model<base_adapter_t> >(this->graphModel_); 01117 } 01118 if(modelAvail_[HypergraphModelType]==true) 01119 { 01120 std::cout << "Hypergraph model not implemented yet..." << std::endl; 01121 } 01122 01123 if(modelAvail_[CoordinateModelType]==true) 01124 { 01125 this->env_->debug(DETAILED_STATUS, " building coordinate model"); 01126 this->coordinateModel_ = rcp(new CoordinateModel<base_adapter_t>( 01127 this->baseInputAdapter_, this->envConst_, problemComm_, coordFlags_)); 01128 01129 this->baseModel_ = rcp_implicit_cast<const Model<base_adapter_t> >(this->coordinateModel_); 01130 } 01131 01132 if(modelAvail_[IdentifierModelType]==true) 01133 { 01134 this->env_->debug(DETAILED_STATUS, " building identifier model"); 01135 this->identifierModel_ = rcp(new IdentifierModel<base_adapter_t>( 01136 this->baseInputAdapter_, this->envConst_, problemComm_, idFlags_)); 01137 01138 this->baseModel_ = rcp_implicit_cast<const Model<base_adapter_t> >(this->identifierModel_); 01139 } 01140 01141 01142 } 01143 01144 01145 01146 this->env_->memory("After creating Model"); 01147 this->env_->debug(DETAILED_STATUS, "createPartitioningProblem done"); 01148 } 01149 01150 } 01151 01152 } // namespace Zoltan2 01153 #endif
1.7.6.1