Zoltan2
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 // disable clang warnings
00055 #ifdef __clang__
00056 #pragma clang system_header
00057 #endif
00058 
00059 #include <Zoltan2_Model.hpp>
00060 #include <Zoltan2_MeshAdapter.hpp>
00061 #include <Zoltan2_MatrixAdapter.hpp>
00062 #include <Zoltan2_GraphAdapter.hpp>
00063 #include <Zoltan2_IdentifierAdapter.hpp>
00064 #include <Zoltan2_VectorAdapter.hpp>
00065 #include <Zoltan2_StridedData.hpp>
00066 
00067 namespace Zoltan2 {
00068 
00075 template <typename Adapter>
00076 class CoordinateModel : public Model<Adapter>
00077 {
00078 public:
00079 
00080 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00081   typedef typename Adapter::scalar_t    scalar_t;
00082   typedef typename Adapter::gno_t       gno_t;
00083   typedef typename Adapter::zgid_t       zgid_t;
00084   typedef typename Adapter::lno_t       lno_t;
00085   typedef typename Adapter::user_t      user_t;
00086   typedef typename Adapter::userCoord_t userCoord_t;
00087   typedef StridedData<lno_t, scalar_t>  input_t;
00088   typedef IdentifierMap<user_t>         idmap_t;
00089 #endif
00090 
00092   // Constructors for each Adapter type
00094 
00095   // VectorAdapter
00096   CoordinateModel(const VectorAdapter<user_t> *ia,
00097                   const RCP<const Environment> &env,
00098                   const RCP<const Comm<int> > &comm,
00099                   modelFlag_t &flags):
00100       gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00101       coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(),
00102       gnos_(), gnosConst_()
00103   {
00104     typedef VectorAdapter<user_t> adapterWithCoords_t;
00105     sharedConstructor<adapterWithCoords_t>(ia, env, comm, flags);
00106   }
00107 
00108   // MatrixAdapter
00109   CoordinateModel(const MatrixAdapter<user_t,userCoord_t> *ia,
00110                   const RCP<const Environment> &env,
00111                   const RCP<const Comm<int> > &comm,
00112                   modelFlag_t &flags) :
00113                   gnosAreGids_(false), numGlobalCoordinates_(),
00114                   env_(env), comm_(comm),
00115                   coordinateDim_(), gids_(), xyz_(),
00116                   userNumWeights_(0), weights_(),
00117                   gnos_(), gnosConst_()
00118   {
00119     if (!(ia->coordinatesAvailable()))
00120       throw std::logic_error("No coordinate info provided to MatrixAdapter.");
00121     else {
00122       typedef VectorAdapter<userCoord_t> adapterWithCoords_t;
00123       adapterWithCoords_t *va = ia->getCoordinateInput();
00124       sharedConstructor<adapterWithCoords_t>(va, env, comm, flags);
00125     }
00126   }
00127 
00128   // GraphAdapter
00129   CoordinateModel(const GraphAdapter<user_t,userCoord_t> *ia,
00130                   const RCP<const Environment> &env,
00131                   const RCP<const Comm<int> > &comm,
00132                   modelFlag_t &flags) :
00133                   gnosAreGids_(false), numGlobalCoordinates_(),
00134                   env_(env), comm_(comm),
00135                   coordinateDim_(), gids_(), xyz_(),
00136                   userNumWeights_(0), weights_(),
00137                   gnos_(), gnosConst_()
00138   {
00139     if (!(ia->coordinatesAvailable()))
00140       throw std::logic_error("No coordinate info provided to GraphAdapter.");
00141     else {
00142       typedef VectorAdapter<userCoord_t> adapterWithCoords_t;
00143       adapterWithCoords_t *va = ia->getCoordinateInput();
00144       sharedConstructor<adapterWithCoords_t>(va, env, comm, flags);
00145     }
00146   }
00147 
00148   // MeshAdapter
00149   CoordinateModel(const MeshAdapter<user_t> *ia,
00150       const RCP<const Environment> &env,
00151       const RCP<const Comm<int> > &comm,
00152       modelFlag_t &flags) :
00153     gnosAreGids_(false), numGlobalCoordinates_(), env_(env), comm_(comm),
00154     coordinateDim_(), gids_(), xyz_(), userNumWeights_(0), weights_(),
00155     gnos_(), gnosConst_()
00156   {
00157     typedef MeshAdapter<user_t> adapterWithCoords_t;
00158     sharedConstructor<adapterWithCoords_t>(ia, env, comm, flags);
00159   }
00160 
00161   // IdentifierAdapter
00162   CoordinateModel(const IdentifierAdapter<user_t> *ia,
00163                   const RCP<const Environment> &env,
00164                   const RCP<const Comm<int> > &comm,
00165                   modelFlag_t &flags)
00166   {
00167     throw std::logic_error(
00168       "A coordinate model can not be build from an IdentifierAdapter");
00169   }
00170 
00172   // CoordinateModel interface.
00174 
00177   int getCoordinateDim() const { return coordinateDim_;}
00178 
00181   size_t getLocalNumCoordinates() const { return gids_.size();}
00182 
00185   global_size_t getGlobalNumCoordinates() const {return numGlobalCoordinates_;}
00186 
00189   int getNumWeightsPerCoordinate() const { return userNumWeights_;}
00190 
00213   size_t getCoordinates(ArrayView<const gno_t>  &Ids,
00214                         ArrayView<input_t> &xyz,
00215                         ArrayView<input_t> &wgts) const
00216   {
00217     xyz = xyz_.view(0, coordinateDim_);
00218     wgts = weights_.view(0, userNumWeights_);
00219 
00220     size_t nCoord = getLocalNumCoordinates();
00221     Ids =  ArrayView<const gno_t>();
00222 
00223     if (nCoord){
00224       if (gnosAreGids_)
00225         Ids = Teuchos::arrayView<const gno_t>(
00226           reinterpret_cast<const gno_t *>(gids_.getRawPtr()), nCoord);
00227       else
00228         Ids = gnosConst_.view(0, nCoord);
00229     }
00230 
00231     return nCoord;
00232   }
00233 
00235   // The Model interface.
00237 
00238   size_t getLocalNumObjects() const
00239   {
00240     return getLocalNumCoordinates();
00241   }
00242 
00243   size_t getGlobalNumObjects() const
00244   {
00245     return getGlobalNumCoordinates();
00246   }
00247 
00248 private:
00249   bool gnosAreGids_;
00250   gno_t numGlobalCoordinates_;
00251   const RCP<const Environment> env_;
00252   const RCP<const Comm<int> > comm_;
00253   int coordinateDim_;
00254   ArrayRCP<const zgid_t> gids_;
00255   ArrayRCP<input_t> xyz_;
00256   int userNumWeights_;
00257   ArrayRCP<input_t> weights_;
00258   ArrayRCP<gno_t> gnos_;
00259   ArrayRCP<const gno_t> gnosConst_;
00260 
00261   template <typename AdapterWithCoords>
00262   void sharedConstructor(const AdapterWithCoords *ia,
00263                          const RCP<const Environment> &env,
00264                          const RCP<const Comm<int> > &comm,
00265                          modelFlag_t &flags);
00266 
00267 };
00268 
00269 
00271 
00272 // sharedConstructor
00273 template <typename Adapter>
00274 template <typename AdapterWithCoords>
00275 void CoordinateModel<Adapter>::sharedConstructor(
00276     const AdapterWithCoords *ia,
00277     const RCP<const Environment> &env,
00278     const RCP<const Comm<int> > &comm,
00279     modelFlag_t &flags)
00280 {
00281   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00282 
00283   size_t nLocalIds = ia->getLocalNumIDs();
00284 
00285   // Get coordinates and weights (if any)
00286 
00287   int tmp[2], gtmp[2];
00288   tmp[0] = ia->getDimension();
00289   tmp[1] = ia->getNumWeightsPerID();
00290   Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, 2, tmp, gtmp);
00291   coordinateDim_ = gtmp[0];
00292   userNumWeights_ = gtmp[1];
00293 
00294   env_->localBugAssertion(__FILE__, __LINE__, "coordinate dimension",
00295     coordinateDim_ > 0, COMPLEX_ASSERTION);
00296 
00297   input_t *coordArray = new input_t [coordinateDim_];
00298   input_t *weightArray = NULL;
00299   if (userNumWeights_)
00300     weightArray = new input_t [userNumWeights_];
00301 
00302   env_->localMemoryAssertion(__FILE__, __LINE__, userNumWeights_+coordinateDim_,
00303     coordArray && (!userNumWeights_|| weightArray));
00304 
00305 
00306   if (nLocalIds){
00307     const zgid_t *gids=NULL;
00308     ia->getIDsView(gids);
00309     gids_ = arcp(gids, 0, nLocalIds, false);
00310 
00311     for (int dim=0; dim < coordinateDim_; dim++){
00312       int stride;
00313       const scalar_t *coords=NULL;
00314       try{
00315         ia->getCoordinatesView(coords, stride, dim);
00316       }
00317       Z2_FORWARD_EXCEPTIONS;
00318 
00319       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00320       coordArray[dim] = input_t(cArray, stride);
00321     }
00322 
00323     for (int idx=0; idx < userNumWeights_; idx++){
00324       int stride;
00325       const scalar_t *weights;
00326       try{
00327         ia->getWeightsView(weights, stride, idx);
00328       }
00329       Z2_FORWARD_EXCEPTIONS;
00330 
00331       ArrayRCP<const scalar_t> wArray(weights, 0, nLocalIds*stride, false);
00332       weightArray[idx] = input_t(wArray, stride);
00333     }
00334   }
00335 
00336   xyz_ = arcp(coordArray, 0, coordinateDim_);
00337 
00338   if (userNumWeights_)
00339     weights_ = arcp(weightArray, 0, userNumWeights_);
00340 
00341   // Create identifier map.
00342   // TODO:  Why do coordinate models need an IdentifierMap?
00343 
00344   RCP<const idmap_t> idMap;
00345 
00346   try{
00347     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00348   }
00349   Z2_FORWARD_EXCEPTIONS;
00350 
00351   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00352   gnosAreGids_ = idMap->gnosAreGids();
00353 
00354   this->setIdentifierMap(idMap);
00355 
00356   if (!gnosAreGids_ && nLocalIds>0){
00357     gno_t *tmpGno = new gno_t [nLocalIds];
00358     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00359     gnos_ = arcp(tmpGno, 0, nLocalIds);
00360 
00361     try{
00362       ArrayRCP<zgid_t> gidsNonConst = arcp_const_cast<zgid_t>(gids_);
00363       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds),
00364         TRANSLATE_APP_TO_LIB);
00365     }
00366     Z2_FORWARD_EXCEPTIONS;
00367   }
00368 
00369   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00370 
00371   env_->memory("After construction of coordinate model");
00372 }
00373 
00374 #ifdef KDDKDD_NO_LONGER_NEED_DUPLICATE_CODE
00375 // meshConstructor
00376 template <typename Adapter>
00377 void CoordinateModel<Adapter>::meshConstructor(
00378     const MeshAdapter<typename Adapter::userCoord_t> *ia,
00379     const RCP<const Environment> &env,
00380     const RCP<const Comm<int> > &comm,
00381     modelFlag_t &flags)
00382 {
00383   bool consecutiveIds = flags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE);
00384 
00385   size_t nLocalIds = ia->getLocalNumIDs();
00386 
00387   // Get coordinates and weights (if any)
00388 
00389   int tmp[2], gtmp[2];
00390   tmp[0] = ia->getDimension();
00391   tmp[1] = ia->getNumWeightsPerID();
00392   Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, 2, tmp, gtmp);
00393   coordinateDim_ = gtmp[0];
00394   userNumWeights_ = gtmp[1];
00395 
00396   env_->localBugAssertion(__FILE__, __LINE__, "coordinate dimension",
00397     coordinateDim_ > 0, COMPLEX_ASSERTION);
00398 
00399   input_t *coordArray = new input_t [coordinateDim_];
00400   input_t *weightArray = NULL;
00401   if (userNumWeights_)
00402     weightArray = new input_t [userNumWeights_];
00403 
00404   env_->localMemoryAssertion(__FILE__, __LINE__, userNumWeights_+coordinateDim_,
00405     coordArray && (!userNumWeights_|| weightArray));
00406 
00407 
00408   if (nLocalIds){
00409     const zgid_t *gids=NULL;
00410     ia->getIDsView(gids);
00411     gids_ = arcp(gids, 0, nLocalIds, false);
00412 
00413     for (int dim=0; dim < coordinateDim_; dim++){
00414       int stride;
00415       const scalar_t *coords=NULL;
00416       try{
00417   ia->getCoordinatesViewOf(ia->getPrimaryEntityType(), coords, stride, dim);
00418       }
00419       Z2_FORWARD_EXCEPTIONS;
00420 
00421       ArrayRCP<const scalar_t> cArray(coords, 0, nLocalIds*stride, false);
00422       coordArray[dim] = input_t(cArray, stride);
00423     }
00424 
00425     for (int idx=0; idx < userNumWeights_; idx++){
00426       int stride;
00427       const scalar_t *weights;
00428       try{
00429         ia->getWeightsView(weights, stride, idx);
00430       }
00431       Z2_FORWARD_EXCEPTIONS;
00432 
00433       ArrayRCP<const scalar_t> wArray(weights, 0, nLocalIds*stride, false);
00434       weightArray[idx] = input_t(wArray, stride);
00435     }
00436   }
00437 
00438   xyz_ = arcp(coordArray, 0, coordinateDim_);
00439 
00440   if (userNumWeights_)
00441     weights_ = arcp(weightArray, 0, userNumWeights_);
00442 
00443   // Create identifier map.
00444   // TODO:  Why do coordinate models need an IdentifierMap?
00445 
00446   RCP<const idmap_t> idMap;
00447 
00448   try{
00449     idMap = rcp(new idmap_t(env_, comm_, gids_, consecutiveIds));
00450   }
00451   Z2_FORWARD_EXCEPTIONS;
00452 
00453   numGlobalCoordinates_ = idMap->getGlobalNumberOfIds();
00454   gnosAreGids_ = idMap->gnosAreGids();
00455 
00456   this->setIdentifierMap(idMap);
00457 
00458   if (!gnosAreGids_ && nLocalIds>0){
00459     gno_t *tmpGno = new gno_t [nLocalIds];
00460     env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
00461     gnos_ = arcp(tmpGno, 0, nLocalIds);
00462 
00463     try{
00464       ArrayRCP<zgid_t> gidsNonConst = arcp_const_cast<zgid_t>(gids_);
00465       idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds),
00466         TRANSLATE_APP_TO_LIB);
00467     }
00468     Z2_FORWARD_EXCEPTIONS;
00469   }
00470 
00471   gnosConst_ = arcp_const_cast<const gno_t>(gnos_);
00472 
00473   env_->memory("After construction of coordinate model");
00474 }
00475 #endif
00476 
00477 }   // namespace Zoltan2
00478 
00479 #endif