Zoltan 2 Version 0.5
Zoltan2_CoordinateModel.hpp
Go to the documentation of this file.
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 
00051 #ifndef _ZOLTAN2_COORDINATEMODEL_HPP_
00052 #define _ZOLTAN2_COORDINATEMODEL_HPP_
00053 
00054 #include <Zoltan2_Model.hpp>
00055 #include <Zoltan2_MatrixInput.hpp>
00056 #include <Zoltan2_GraphInput.hpp>
00057 #include <Zoltan2_IdentifierInput.hpp>
00058 #include <Zoltan2_CoordinateInput.hpp>
00059 #include <Zoltan2_VectorInput.hpp>
00060 #include <Zoltan2_StridedData.hpp>
00061 
00062 namespace Zoltan2 {
00063 
00070 template <typename Adapter>
00071 class CoordinateModel : public Model<Adapter> 
00072 {
00073 public:
00074 
00075 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00076   typedef typename Adapter::scalar_t  scalar_t;
00077   typedef typename Adapter::gno_t     gno_t;
00078   typedef typename Adapter::lno_t     lno_t;
00079   typedef StridedData<lno_t, scalar_t> input_t;
00080 #endif
00081   
00082   CoordinateModel(){
00083     throw std::logic_error("a specific instantiation should be used");
00084   }
00085 
00087   // The CoordinateModel interface.
00089 
00092   int getCoordinateDim() const { return 0; }
00093 
00096   size_t getLocalNumCoordinates() const { return 0; }
00097 
00100   global_size_t getGlobalNumCoordinates() const { return 0; }
00101 
00104   int getCoordinateWeightDim() const { return 0; }
00105 
00128   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00129     ArrayView<input_t> &xyz,
00130     ArrayView<input_t> &wgts) const {return 0;}
00131 
00133   // The Model interface.
00135 
00136   size_t getLocalNumObjects() const
00137   {
00138     return getLocalNumCoordinates();
00139   }
00140 
00141   size_t getGlobalNumObjects() const
00142   {
00143     return getGlobalNumCoordinates();
00144   }
00145 
00146   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const { return ; }
00147 };
00148 
00149 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00150 
00152 // Coordinate model derived from CoordinateInput.
00154 
00155 template <typename User>
00156 class CoordinateModel<CoordinateInput<User> > : 
00157   public Model<CoordinateInput<User> >
00158 {
00159 
00160 public:
00161 
00162   typedef typename CoordinateInput<User>::scalar_t  scalar_t;
00163   typedef typename CoordinateInput<User>::gno_t     gno_t;
00164   typedef typename CoordinateInput<User>::lno_t     lno_t;
00165   typedef typename CoordinateInput<User>::gid_t     gid_t;
00166   typedef IdentifierMap<User> idmap_t;
00167   typedef StridedData<lno_t, scalar_t> input_t;
00168 
00177   CoordinateModel( const CoordinateInput<User> *ia, 
00178     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00179     modelFlag_t flags);
00180 
00181   int getCoordinateDim() const { return coordinateDim_; }
00182 
00183   size_t getLocalNumCoordinates() const { return gids_.size(); }
00184 
00185   global_size_t getGlobalNumCoordinates() const {return numGlobalCoordinates_;}
00186 
00187   int getCoordinateWeightDim() const { return userNumWeights_;}
00188 
00189   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00190     ArrayView<input_t> &xyz,
00191     ArrayView<input_t> &wgts) const 
00192   {
00193     xyz = xyz_.view(0, coordinateDim_);
00194     wgts = weights_.view(0, userNumWeights_);
00195 
00196     size_t nCoord = getLocalNumCoordinates();
00197     Ids =  ArrayView<const gno_t>();
00198 
00199     if (nCoord){
00200       if (gnosAreGids_)
00201         Ids = Teuchos::arrayView<const gno_t>(
00202           reinterpret_cast<const gno_t *>(gids_.getRawPtr()), nCoord);
00203       else
00204         Ids = gnosConst_.view(0, nCoord);
00205     }
00206     
00207     return nCoord;
00208   }
00209 
00211   // The Model interface.
00213 
00214   size_t getLocalNumObjects() const
00215   {
00216     return getLocalNumCoordinates();
00217   }
00218 
00219   size_t getGlobalNumObjects() const
00220   {
00221     return getGlobalNumCoordinates();
00222   }
00223 
00224   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const 
00225   { 
00226     ArrayView<input_t> xyz;
00227     ArrayView<input_t> weights;
00228     getCoordinates(gnos, xyz, weights);
00229   }
00230 
00231 private:
00232 
00233   bool gnosAreGids_;
00234   gno_t numGlobalCoordinates_;
00235   const RCP<const Environment> env_;
00236   const RCP<const Comm<int> > comm_;
00237   int coordinateDim_;
00238   ArrayRCP<const gid_t> gids_;
00239   ArrayRCP<input_t> xyz_;
00240   int userNumWeights_;
00241   ArrayRCP<input_t> weights_;
00242   ArrayRCP<gno_t> gnos_;
00243   ArrayRCP<const gno_t> gnosConst_;
00244 
00245 };
00246 
00247 template <typename User>
00248   CoordinateModel<CoordinateInput<User> >::CoordinateModel( 
00249     const CoordinateInput<User> *ia, 
00250     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00251     modelFlag_t flags):
00252       gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00253       coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(), 
00254       gnos_(), gnosConst_()
00255 {
00256   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00257 
00258   size_t nLocalIds = ia->getLocalNumberOfCoordinates();
00259 
00260   // Get coordinates and weights (if any)
00261 
00262   coordinateDim_ = ia->getCoordinateDimension();
00263   userNumWeights_ = ia->getNumberOfWeights();
00264 
00265   Model<CoordinateInput<User> >::maxCount(*comm, coordinateDim_, 
00266     userNumWeights_);
00267 
00268   env_->localBugAssertion(__FILE__, __LINE__, "coordinate dimension",
00269     coordinateDim_ > 0, COMPLEX_ASSERTION);
00270 
00271   input_t *coordArray = new input_t [coordinateDim_];
00272   input_t *weightArray = NULL;
00273   if (userNumWeights_)
00274     weightArray = new input_t [userNumWeights_];
00275 
00276   env_->localMemoryAssertion(__FILE__, __LINE__, userNumWeights_+coordinateDim_,
00277     coordArray && (!userNumWeights_ || weightArray));
00278 
00279   Array<lno_t> arrayLengths(userNumWeights_, 0);
00280 
00281   if (nLocalIds){
00282     for (int dim=0; dim < coordinateDim_; dim++){
00283       int stride;
00284       const gid_t *gids=NULL;
00285       const scalar_t *coords=NULL;
00286       try{
00287         ia->getCoordinates(dim, gids, coords, stride);
00288       }
00289       Z2_FORWARD_EXCEPTIONS;
00290 
00291       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00292       coordArray[dim] = input_t(cArray, stride);
00293 
00294       if (dim==0)
00295         gids_ = arcp(gids, 0, nLocalIds, false);
00296     }
00297 
00298     for (int dim=0; dim < userNumWeights_; dim++){
00299       int stride;
00300       const scalar_t *weights;
00301       try{
00302         ia->getCoordinateWeights(dim, weights, stride);
00303       }
00304       Z2_FORWARD_EXCEPTIONS;
00305 
00306       if (weights){
00307         ArrayRCP<const scalar_t> wArray(weights, 0, nLocalIds*stride, false);
00308         weightArray[dim] = input_t(wArray, stride);
00309         arrayLengths[dim] = nLocalIds;
00310       }
00311     }
00312   }
00313 
00314   xyz_ = arcp(coordArray, 0, coordinateDim_);
00315 
00316   if (userNumWeights_)
00317     weights_ = arcp(weightArray, 0, userNumWeights_);
00318 
00319   // Sets this->weightDim_, this->uniform_
00320   this->setWeightArrayLengths(arrayLengths, *comm_);
00321 
00322   // Create identifier map.
00323 
00324   RCP<const idmap_t> idMap;
00325 
00326   try{
00327     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00328   }
00329   Z2_FORWARD_EXCEPTIONS;
00330 
00331   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00332   gnosAreGids_ = idMap->gnosAreGids();
00333 
00334   this->setIdentifierMap(idMap);
00335 
00336   if (!gnosAreGids_ && nLocalIds>0){
00337     gno_t *tmpGno = new gno_t [nLocalIds];
00338     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00339     gnos_ = arcp(tmpGno, 0, nLocalIds);
00340 
00341     try{
00342       ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_);
00343       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds), 
00344         TRANSLATE_APP_TO_LIB);
00345     }
00346     Z2_FORWARD_EXCEPTIONS;
00347   }
00348 
00349   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00350 
00351   env_->memory("After construction of coordinate model");
00352 }
00353 
00355 // Coordinate model derived from MatrixInput.
00357 
00358 template <typename User>
00359 class CoordinateModel<MatrixInput<User> > : 
00360   public Model<MatrixInput<User> >
00361 {
00362 public:
00363 
00364   typedef typename MatrixInput<User>::scalar_t  scalar_t;
00365   typedef typename MatrixInput<User>::gno_t     gno_t;
00366   typedef typename MatrixInput<User>::lno_t     lno_t;
00367   typedef typename MatrixInput<User>::gid_t     gid_t;
00368   typedef IdentifierMap<User> idmap_t;
00369   typedef StridedData<lno_t, scalar_t> input_t;
00370 
00379   CoordinateModel( const MatrixInput<User> *ia, 
00380     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00381     modelFlag_t flags);
00382 
00383   int getCoordinateDim() const { return coordinateDim_; }
00384 
00385   size_t getLocalNumCoordinates() const { return gids_.size(); }
00386 
00387   global_size_t getGlobalNumCoordinates() const {return numGlobalCoordinates_;}
00388 
00389   /* \brief Weights are not implemented in MatrixInput.
00390    *
00391    *   Whereas a computational model may create weights to use with
00392    *   a matrix problem, they are not inherent in the input.
00393    */
00394   int getCoordinateWeightDim() const { return 0; }
00395 
00396   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00397     ArrayView<input_t> &xyz,
00398     ArrayView<input_t> &wgts) const 
00399   {
00400     xyz = xyz_.view(0, coordinateDim_);
00401     wgts = weights_.view(0, userNumWeights_);
00402 
00403     size_t nCoord = getLocalNumCoordinates();
00404     Ids =  ArrayView<const gno_t>();
00405 
00406     if (nCoord){
00407       if (gnosAreGids_)
00408         Ids = Teuchos::arrayView<const gno_t>(
00409           reinterpret_cast<const gno_t *>(gids_.getRawPtr()), nCoord);
00410       else
00411         Ids = gnosConst_.view(0, nCoord);
00412     }
00413 
00414     return nCoord;
00415   }
00416 
00418   // The Model interface.
00420 
00421   size_t getLocalNumObjects() const
00422   {
00423     return getLocalNumCoordinates();
00424   }
00425 
00426   size_t getGlobalNumObjects() const
00427   {
00428     return getGlobalNumCoordinates();
00429   }
00430 
00431   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const 
00432   { 
00433     ArrayView<input_t> xyz;
00434     ArrayView<input_t> weights;
00435     getCoordinates(gnos, xyz, weights);
00436   }
00437 
00438 private:
00439 
00440   bool gnosAreGids_;
00441   gno_t numGlobalCoordinates_;
00442   const RCP<const Environment> env_;
00443   const RCP<const Comm<int> > comm_;
00444   int coordinateDim_;
00445   ArrayRCP<const gid_t> gids_;
00446   ArrayRCP<input_t> xyz_;
00447   int userNumWeights_;
00448   ArrayRCP<input_t> weights_;
00449   ArrayRCP<gno_t> gnos_;
00450   ArrayRCP<const gno_t> gnosConst_;
00451 };
00452 
00453 template <typename User>
00454   CoordinateModel<MatrixInput<User> >::CoordinateModel( 
00455     const MatrixInput<User> *ia, 
00456     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00457     modelFlag_t flags):
00458       gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00459       coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(), 
00460       gnos_(), gnosConst_()
00461 {
00462   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00463 
00464   userNumWeights_= 0;  // matrix input does not have weights
00465 
00466   coordinateDim_ = ia->getCoordinateDimension();
00467 
00468   Model<MatrixInput<User> >::maxCount(*comm, coordinateDim_, userNumWeights_);
00469 
00470   env_->localBugAssertion(__FILE__, __LINE__, "coordinate dimension",
00471     coordinateDim_ > 0, COMPLEX_ASSERTION);
00472 
00473   size_t nLocalIds = (coordinateDim_ ? ia->getLocalNumRows() : 0);
00474 
00475   // Get coordinates
00476 
00477   input_t *coordArray = new input_t [coordinateDim_];
00478   env_->localMemoryAssertion(__FILE__, __LINE__, coordinateDim_, coordArray);
00479 
00480   if (nLocalIds){
00481     for (int dim=0; dim < coordinateDim_; dim++){
00482       int stride;
00483       const scalar_t *coords=NULL;
00484       try{
00485         ia->getRowCoordinates(dim, coords, stride);
00486       }
00487       Z2_FORWARD_EXCEPTIONS;
00488 
00489       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00490       coordArray[dim] = input_t(cArray, stride);
00491     }
00492   }
00493 
00494   xyz_ = arcp(coordArray, 0, coordinateDim_);
00495 
00496   // Create identifier map.
00497 
00498   const gid_t *rowGids;
00499   const lno_t *offsets;
00500   const gid_t *colGids;
00501 
00502   ia->getRowListView(rowGids, offsets, colGids);
00503 
00504   gids_ = arcp<const gid_t>(rowGids, 0, nLocalIds, false);
00505 
00506   RCP<const idmap_t> idMap;
00507 
00508   try{
00509     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00510   }
00511   Z2_FORWARD_EXCEPTIONS;
00512 
00513   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00514   gnosAreGids_ = idMap->gnosAreGids();
00515 
00516   this->setIdentifierMap(idMap);
00517 
00518   if (!gnosAreGids_ && nLocalIds>0){
00519     gno_t *tmpGno = new gno_t [nLocalIds];
00520     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00521     gnos_ = arcp(tmpGno, 0, nLocalIds);
00522 
00523     try{
00524       ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_);
00525       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds), 
00526         TRANSLATE_APP_TO_LIB);
00527     }
00528     Z2_FORWARD_EXCEPTIONS;
00529   }
00530 
00531   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00532 
00533   env_->memory("After construction of coordinate model");
00534 }
00535 
00537 // Coordinate model derived from VectorInput.
00539 
00540 template <typename User>
00541 class CoordinateModel<VectorInput<User> > : 
00542   public Model<VectorInput<User> >
00543 {
00544 
00545 public:
00546 
00547   typedef typename VectorInput<User>::scalar_t  scalar_t;
00548   typedef typename VectorInput<User>::gno_t     gno_t;
00549   typedef typename VectorInput<User>::gid_t     gid_t;
00550   typedef typename VectorInput<User>::lno_t     lno_t;
00551   typedef StridedData<lno_t, scalar_t> input_t;
00552   typedef IdentifierMap<User> idmap_t;
00553 
00554   CoordinateModel( const VectorInput<User> *ia, 
00555     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00556     modelFlag_t flags);
00557 
00558   int getCoordinateDim() const { return coordinateDim_;}
00559 
00560   size_t getLocalNumCoordinates() const { return gids_.size();}
00561 
00562   global_size_t getGlobalNumCoordinates() const {return numGlobalCoordinates_;}
00563 
00564   int getCoordinateWeightDim() const { return userNumWeights_;}
00565 
00566   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00567     ArrayView<input_t> &xyz,
00568     ArrayView<input_t> &wgts) const
00569   {
00570     xyz = xyz_.view(0, coordinateDim_);
00571     wgts = weights_.view(0, userNumWeights_);
00572 
00573     size_t nCoord = getLocalNumCoordinates();
00574     Ids =  ArrayView<const gno_t>();
00575 
00576     if (nCoord){
00577       if (gnosAreGids_)
00578         Ids = Teuchos::arrayView<const gno_t>(
00579           reinterpret_cast<const gno_t *>(gids_.getRawPtr()), nCoord);
00580       else
00581         Ids = gnosConst_.view(0, nCoord);
00582     }
00583 
00584     return nCoord;
00585   }
00586 
00588   // The Model interface.
00590 
00591   size_t getLocalNumObjects() const {return gids_.size();}
00592 
00593   size_t getGlobalNumObjects() const {return numGlobalCoordinates_;}
00594 
00595   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const {
00596     ArrayView<input_t> a, b;
00597     getCoordinates(gnos, a, b);
00598     return;
00599   }
00600 
00601 private:
00602 
00603   bool gnosAreGids_;
00604   gno_t numGlobalCoordinates_;
00605   const RCP<const Environment> env_;
00606   const RCP<const Comm<int> > comm_;
00607   int coordinateDim_;
00608   ArrayRCP<const gid_t> gids_;
00609   ArrayRCP<input_t> xyz_;
00610   int userNumWeights_;
00611   ArrayRCP<input_t> weights_;
00612   ArrayRCP<gno_t> gnos_;
00613   ArrayRCP<const gno_t> gnosConst_;
00614 };
00615 
00616 template <typename User>
00617 CoordinateModel<VectorInput<User> >::CoordinateModel( 
00618     const VectorInput<User> *ia, 
00619     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00620     modelFlag_t flags):
00621       gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00622       coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(), 
00623       gnos_(), gnosConst_()
00624 {
00625   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00626 
00627   size_t nLocalIds = ia->getLocalLength();
00628 
00629   // Get coordinates and weights (if any)
00630 
00631   coordinateDim_ = ia->getNumberOfVectors();
00632   userNumWeights_ = ia->getNumberOfWeights();
00633 
00634   Model<VectorInput<User> >::maxCount(*comm, coordinateDim_, userNumWeights_);
00635 
00636   env_->localBugAssertion(__FILE__, __LINE__, "coordinate dimension",
00637     coordinateDim_ > 0, COMPLEX_ASSERTION);
00638 
00639   input_t *coordArray = new input_t [coordinateDim_];
00640   input_t *weightArray = NULL;
00641   if (userNumWeights_)
00642     weightArray = new input_t [userNumWeights_];
00643 
00644   env_->localMemoryAssertion(__FILE__, __LINE__, userNumWeights_+coordinateDim_,
00645     coordArray && (!userNumWeights_|| weightArray));
00646 
00647   Array<lno_t> arrayLengths(userNumWeights_, 0);
00648 
00649   if (nLocalIds){
00650     for (int dim=0; dim < coordinateDim_; dim++){
00651       int stride;
00652       const gid_t *gids=NULL;
00653       const scalar_t *coords=NULL;
00654       try{
00655         ia->getVector(dim, gids, coords, stride);
00656       }
00657       Z2_FORWARD_EXCEPTIONS;
00658 
00659       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00660       coordArray[dim] = input_t(cArray, stride);
00661 
00662       if (dim==0)
00663         gids_ = arcp(gids, 0, nLocalIds, false);
00664     }
00665 
00666     for (int dim=0; dim < userNumWeights_; dim++){
00667       int stride;
00668       const scalar_t *weights;
00669       try{
00670         ia->getVectorWeights(dim, weights, stride);
00671       }
00672       Z2_FORWARD_EXCEPTIONS;
00673 
00674       if (weights){
00675         ArrayRCP<const scalar_t> wArray(weights, 0, nLocalIds*stride, false);
00676         weightArray[dim] = input_t(wArray, stride);
00677         arrayLengths[dim] = nLocalIds;
00678       }
00679     }
00680   }
00681 
00682   xyz_ = arcp(coordArray, 0, coordinateDim_);
00683 
00684   if (userNumWeights_)
00685     weights_ = arcp(weightArray, 0, userNumWeights_);
00686 
00687   // Sets this->weightDim_ and this->uniform_
00688   this->setWeightArrayLengths(arrayLengths, *comm_);
00689 
00690   // Create identifier map.
00691 
00692   RCP<const idmap_t> idMap;
00693 
00694   try{
00695     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00696   }
00697   Z2_FORWARD_EXCEPTIONS;
00698 
00699   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00700   gnosAreGids_ = idMap->gnosAreGids();
00701 
00702   this->setIdentifierMap(idMap);
00703 
00704   if (!gnosAreGids_ && nLocalIds>0){
00705     gno_t *tmpGno = new gno_t [nLocalIds];
00706     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00707     gnos_ = arcp(tmpGno, 0, nLocalIds);
00708 
00709     try{
00710       ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_);
00711       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds), 
00712         TRANSLATE_APP_TO_LIB);
00713     }
00714     Z2_FORWARD_EXCEPTIONS;
00715   }
00716 
00717   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00718 
00719   env_->memory("After construction of coordinate model");
00720 }
00721 
00723 // Coordinate model derived from IdentifierInput.
00724 // A coordinate model can not be built from IdentifierInput.
00725 // This specialization exists so that other code can compile.
00727 
00728 template <typename User>
00729 class CoordinateModel<IdentifierInput<User> > : 
00730   public Model<IdentifierInput<User> >
00731 {
00732 public:
00733 
00734   typedef typename IdentifierInput<User>::scalar_t  scalar_t;
00735   typedef typename IdentifierInput<User>::gno_t     gno_t;
00736   typedef typename IdentifierInput<User>::lno_t     lno_t;
00737   typedef StridedData<lno_t, scalar_t> input_t;
00738   
00739   CoordinateModel( const IdentifierInput<User> *ia, 
00740     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00741     modelFlag_t flags)
00742   {
00743     throw logic_error(
00744       "a coordinate model can not be build from identifier input");
00745   }
00746 
00747   int getCoordinateDim() const { return 0;}
00748   size_t getLocalNumCoordinates() const { return 0;}
00749   global_size_t getGlobalNumCoordinates() const {return 0;}
00750   int getCoordinateWeightDim() const { return 0;}
00751   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00752     ArrayView<input_t> &xyz,
00753     ArrayView<input_t> &wgts) const { return 0;}
00754 
00756   // The Model interface.
00758 
00759   size_t getLocalNumObjects() const {return 0;}
00760   size_t getGlobalNumObjects() const {return 0;}
00761   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const {return;}
00762 };
00763 
00764 
00766 // Coordinate model derived from GraphInput.
00768 
00769 template <typename User>
00770 class CoordinateModel<GraphInput<User> > : 
00771   public Model<GraphInput<User> >
00772 {
00773 
00774 public:
00775 
00776   typedef typename GraphInput<User>::scalar_t  scalar_t;
00777   typedef typename GraphInput<User>::gno_t     gno_t;
00778   typedef typename GraphInput<User>::gid_t     gid_t;
00779   typedef typename GraphInput<User>::lno_t     lno_t;
00780   typedef StridedData<lno_t, scalar_t> input_t;
00781   typedef IdentifierMap<User> idmap_t;
00782 
00783   CoordinateModel( const GraphInput<User> *ia, 
00784     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00785     modelFlag_t flags);
00786 
00787   int getCoordinateDim() const { return coordinateDim_;}
00788 
00789   size_t getLocalNumCoordinates() const { return gids_.size();}
00790 
00791   global_size_t getGlobalNumCoordinates() const {return numGlobalCoordinates_;}
00792 
00793   int getCoordinateWeightDim() const { return userNumWeights_;}
00794 
00795   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00796     ArrayView<input_t> &xyz,
00797     ArrayView<input_t> &wgts) const
00798   {
00799     xyz = xyz_.view(0, coordinateDim_);
00800     wgts = weights_.view(0, userNumWeights_);
00801 
00802     size_t nCoord = getLocalNumCoordinates();
00803     Ids =  ArrayView<const gno_t>();
00804 
00805     if (nCoord){
00806       if (gnosAreGids_)
00807         Ids = Teuchos::arrayView<const gno_t>(
00808           reinterpret_cast<const gno_t *>(gids_.getRawPtr()), nCoord);
00809       else
00810         Ids = gnosConst_.view(0, nCoord);
00811     }
00812 
00813     return nCoord;
00814   }
00815 
00817   // The Model interface.
00819 
00820   size_t getLocalNumObjects() const {return gids_.size();}
00821 
00822   size_t getGlobalNumObjects() const {return numGlobalCoordinates_;}
00823 
00824   void getGlobalObjectIds(ArrayView<const gno_t> &gnos) const {
00825     ArrayView<input_t> a, b;
00826     getCoordinates(gnos, a, b);
00827     return;
00828   }
00829 
00830 private:
00831 
00832   bool gnosAreGids_;
00833   gno_t numGlobalCoordinates_;
00834   const RCP<const Environment> env_;
00835   const RCP<const Comm<int> > comm_;
00836   int coordinateDim_;
00837   ArrayRCP<const gid_t> gids_;
00838   ArrayRCP<input_t> xyz_;
00839   int userNumWeights_;
00840   ArrayRCP<input_t> weights_;
00841   ArrayRCP<gno_t> gnos_;
00842   ArrayRCP<const gno_t> gnosConst_;
00843 };
00844 
00845 template <typename User>
00846 CoordinateModel<GraphInput<User> >::CoordinateModel( 
00847     const GraphInput<User> *ia, 
00848     const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, 
00849     modelFlag_t flags):
00850       gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00851       coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(), 
00852       gnos_(), gnosConst_()
00853 {
00854   coordinateDim_ = ia->getCoordinateDimension();
00855 
00856   env->localInputAssertion(__FILE__, __LINE__, 
00857    "graph input does not have vertex coordinates",
00858    coordinateDim_>0, BASIC_ASSERTION);
00859 
00860   // Get coordinates and weights (if any)
00861 
00862   userNumWeights_ = ia->getVertexWeightDimension();
00863 
00864   Model<GraphInput<User> >::maxCount(*comm, coordinateDim_, userNumWeights_);
00865 
00866   input_t *coordArray = new input_t [coordinateDim_];
00867   input_t *weightArray = NULL;
00868   if (userNumWeights_)
00869     weightArray = new input_t [userNumWeights_];
00870 
00871   env_->localMemoryAssertion(__FILE__, __LINE__, userNumWeights_+coordinateDim_,
00872     coordArray && (!userNumWeights_|| weightArray));
00873 
00874   Array<lno_t> arrayLengths(userNumWeights_, 0);
00875 
00876   size_t nLocalIds = ia->getLocalNumberOfVertices();
00877 
00878   if (nLocalIds){
00879     const gid_t *globalIds=NULL;
00880     const lno_t *offsets=NULL;
00881     const gid_t *edgeIds=NULL;
00882 
00883     size_t numIds = ia->getVertexListView(globalIds, offsets, edgeIds);
00884 
00885     gids_ = arcp(globalIds, 0, nLocalIds, false);
00886 
00887     for (int dim=0; dim < coordinateDim_; dim++){
00888       int stride;
00889       const scalar_t *coords=NULL;
00890       try{
00891         ia->getVertexCoordinates(dim, coords, stride);
00892       }
00893       Z2_FORWARD_EXCEPTIONS;
00894 
00895       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00896       coordArray[dim] = input_t(cArray, stride);
00897     }
00898 
00899     for (int dim=0; dim < userNumWeights_; dim++){
00900       int stride;
00901       const scalar_t *weights;
00902       try{
00903         ia->getVertexWeights(dim, weights, stride);
00904       }
00905       Z2_FORWARD_EXCEPTIONS;
00906 
00907       if (weights){
00908         ArrayRCP<const scalar_t> wArray(weights, 0, nLocalIds*stride, false);
00909         weightArray[dim] = input_t(wArray, stride);
00910         arrayLengths[dim] = nLocalIds;
00911       }
00912     }
00913   }
00914 
00915   xyz_ = arcp(coordArray, 0, coordinateDim_);
00916 
00917   if (userNumWeights_)
00918     weights_ = arcp(weightArray, 0, userNumWeights_);
00919 
00920   // Sets this->weightDim_ and this->uniform_
00921   this->setWeightArrayLengths(arrayLengths, *comm_);
00922 
00923   // Create identifier map.
00924 
00925   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00926 
00927   RCP<const idmap_t> idMap;
00928 
00929   try{
00930     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00931   }
00932   Z2_FORWARD_EXCEPTIONS;
00933 
00934   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00935   gnosAreGids_ = idMap->gnosAreGids();
00936 
00937   this->setIdentifierMap(idMap);
00938 
00939   if (!gnosAreGids_ && nLocalIds>0){
00940     gno_t *tmpGno = new gno_t [nLocalIds];
00941     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00942     gnos_ = arcp(tmpGno, 0, nLocalIds);
00943 
00944     try{
00945       ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_);
00946       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds), 
00947         TRANSLATE_APP_TO_LIB);
00948     }
00949     Z2_FORWARD_EXCEPTIONS;
00950   }
00951 
00952   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00953 
00954   env_->memory("After construction of coordinate model");
00955 }
00956 #endif   // DOXYGEN_SHOULD_SKIP_THIS
00957 
00958 }   // namespace Zoltan2
00959 
00960 #endif