Zoltan2
Zoltan2_XpetraTraits.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 
00050 #ifndef _ZOLTAN2_XPETRATRAITS_HPP_
00051 #define _ZOLTAN2_XPETRATRAITS_HPP_
00052 
00053 #include <Zoltan2_InputTraits.hpp>
00054 #include <Zoltan2_Standards.hpp>
00055 
00056 #include <Xpetra_EpetraCrsMatrix.hpp>
00057 #include <Xpetra_TpetraCrsMatrix.hpp>
00058 #include <Xpetra_TpetraRowMatrix.hpp>
00059 #include <Xpetra_EpetraVector.hpp>
00060 #include <Xpetra_TpetraVector.hpp>
00061 #include <Xpetra_EpetraUtils.hpp>
00062 #include <Tpetra_Vector.hpp>
00063 
00064 namespace Zoltan2 {
00065 
00067 // Extra traits needed only for Xpetra matrices and graphs
00068 
00091 template <typename User>
00092 struct XpetraTraits
00093 {
00096   static inline RCP<const User> convertToXpetra(const RCP<const User> &a) 
00097   {
00098     return a;
00099   }
00100 
00103   typedef long gno_t;
00104 
00107   typedef int lno_t;
00108 
00114   static RCP<const User> doMigration(const RCP<const User> &from,
00115       size_t numLocalRows, const gno_t *myNewRows)
00116   {
00117     return from;
00118   }
00119 };
00120 
00121 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00122 
00124 // Tpetra::CrsMatrix
00125 template <typename scalar_t,
00126           typename lno_t,
00127           typename gno_t,
00128           typename node_t>
00129 struct XpetraTraits<Tpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> >
00130 {
00131   typedef typename Xpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> 
00132                    xmatrix_t;
00133   typedef typename Xpetra::TpetraCrsMatrix<scalar_t,lno_t,gno_t,node_t> 
00134                    xtmatrix_t;
00135   typedef typename Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> 
00136                    tmatrix_t;
00137 
00138   static inline RCP<const xmatrix_t> convertToXpetra(
00139     const RCP<const tmatrix_t> &a)
00140     {
00141       return rcp(new xtmatrix_t(rcp_const_cast<tmatrix_t>(a)));
00142     }
00143 
00144   static RCP<const tmatrix_t> doMigration(const RCP<const tmatrix_t> &from,
00145       size_t numLocalRows, const gno_t *myNewRows)
00146   {
00147     typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
00148     lno_t base = 0;
00149 
00150     // source map
00151     const RCP<const map_t> &smap = from->getRowMap();
00152     int oldNumElts = smap->getNodeNumElements();
00153     gno_t numGlobalRows = smap->getGlobalNumElements();
00154 
00155     // target map
00156     ArrayView<const gno_t> rowList(myNewRows, numLocalRows);
00157     const RCP<const Teuchos::Comm<int> > &comm = from->getComm();
00158     RCP<const map_t> tmap = rcp(
00159       new map_t(numGlobalRows, rowList, base, comm));
00160     int newNumElts = numLocalRows;
00161 
00162     // importer
00163     Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
00164 
00165     // number of non zeros in my new rows
00166     typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> vector_t;
00167     vector_t numOld(smap);  // TODO These vectors should have scalar = size_t, 
00168     vector_t numNew(tmap);  // but explicit instantiation does not yet support that.
00169     for (int lid=0; lid < oldNumElts; lid++){
00170       numOld.replaceGlobalValue(smap->getGlobalElement(lid), 
00171         scalar_t(from->getNumEntriesInLocalRow(lid)));
00172     }
00173     numNew.doImport(numOld, importer, Tpetra::INSERT);
00174 
00175     // TODO Could skip this copy if could declare vector with scalar = size_t.
00176     ArrayRCP<size_t> nnz(newNumElts);
00177     if (newNumElts > 0){
00178       ArrayRCP<scalar_t> ptr = numNew.getDataNonConst(0);
00179       for (int lid=0; lid < newNumElts; lid++){
00180         nnz[lid] = static_cast<size_t>(ptr[lid]);
00181       }
00182     }
00183 
00184     // target matrix
00185     RCP<tmatrix_t> M = rcp(new tmatrix_t(tmap, nnz, Tpetra::StaticProfile));
00186     M->doImport(*from, importer, Tpetra::INSERT);
00187     M->fillComplete();
00188 
00189     return rcp_const_cast<const tmatrix_t>(M);
00190   }
00191 };
00192 
00194 // Epetra_CrsMatrix
00195 
00196 template <>
00197 struct XpetraTraits<Epetra_CrsMatrix>
00198 {
00199   typedef InputTraits<Epetra_CrsMatrix>::scalar_t scalar_t;
00200   typedef InputTraits<Epetra_CrsMatrix>::lno_t lno_t;
00201   typedef InputTraits<Epetra_CrsMatrix>::gno_t gno_t;
00202   typedef InputTraits<Epetra_CrsMatrix>::node_t node_t;
00203 
00204   static inline RCP<const Xpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> >
00205     convertToXpetra(const RCP<const Epetra_CrsMatrix> &a)
00206     {
00207       return rcp(new Xpetra::EpetraCrsMatrix(
00208                              rcp_const_cast<Epetra_CrsMatrix>(a)));
00209     }
00210 
00211 
00212   static RCP<Epetra_CrsMatrix> doMigration(
00213       const RCP<const Epetra_CrsMatrix> &from,
00214       size_t numLocalRows, const gno_t *myNewRows)
00215   {
00216     lno_t base = 0;
00217 
00218     // source map
00219     const Epetra_Map &smap = from->RowMap();
00220     int oldNumElts = smap.NumMyElements();
00221     gno_t numGlobalRows = smap.NumGlobalElements();
00222 
00223     // target map
00224     const Epetra_Comm &comm = from->Comm();
00225     Epetra_Map tmap(numGlobalRows, numLocalRows, myNewRows, base, comm);
00226     int newNumElts = numLocalRows;
00227 
00228     // importer
00229     Epetra_Import importer(tmap, smap);
00230 
00231     // number of non zeros in my new rows
00232     Epetra_Vector numOld(smap);
00233     Epetra_Vector numNew(tmap);
00234 
00235     for (int lid=0; lid < oldNumElts; lid++){
00236       numOld[lid] = from->NumMyEntries(lid);
00237     }
00238     numNew.Import(numOld, importer, Insert);
00239 
00240     Array<int> nnz(newNumElts);
00241     for (int lid=0; lid < newNumElts; lid++){
00242       nnz[lid] = static_cast<int>(numNew[lid]);
00243     }
00244 
00245     // target matrix
00246     RCP<Epetra_CrsMatrix> M = rcp(new Epetra_CrsMatrix(::Copy, tmap, nnz.getRawPtr(), true));
00247     M->Import(*from, importer, Insert);
00248     M->FillComplete();
00249 
00250     return M;
00251   }
00252 };
00253 
00255 // Xpetra::CrsMatrix
00256 // KDDKDD:  Do we need specializations for Xpetra::EpetraCrsMatrix and
00257 // KDDKDD:  Xpetra::TpetraCrsMatrix
00258 template <typename scalar_t,
00259           typename lno_t,
00260           typename gno_t,
00261           typename node_t>
00262 struct XpetraTraits<Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> >
00263 {
00264   typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> x_matrix_t;
00265   typedef Xpetra::TpetraCrsMatrix<scalar_t, lno_t, gno_t, node_t> xt_matrix_t;
00266   typedef Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> t_matrix_t; 
00267 
00268   static inline RCP<const x_matrix_t>
00269     convertToXpetra( const RCP<const x_matrix_t > &a)
00270     {
00271       return a;
00272     }
00273 
00274   static RCP<const x_matrix_t> doMigration(const RCP<const x_matrix_t> &from,
00275       size_t numLocalRows, const gno_t *myNewRows)
00276   {
00277     Xpetra::UnderlyingLib lib = from->getRowMap()->lib();
00278 
00279     if (lib == Xpetra::UseEpetra){
00280        throw std::logic_error("compiler should have used specialization");
00281     } else{
00282       // Do the import with the Tpetra::CrsMatrix traits object
00283       const x_matrix_t *xm = from.get();
00284       const xt_matrix_t *xtm = dynamic_cast<const xt_matrix_t *>(xm);
00285       RCP<const t_matrix_t> tm = xtm->getTpetra_CrsMatrix();
00286 
00287       RCP<const t_matrix_t> tmnew = XpetraTraits<t_matrix_t>::doMigration(
00288         tm, numLocalRows, myNewRows);
00289 
00290       RCP<const x_matrix_t> xmnew = 
00291         XpetraTraits<t_matrix_t>::convertToXpetra(tmnew);
00292 
00293       return xmnew;
00294     }
00295   }
00296 };
00297 
00299 // Xpetra::CrsMatrix specialization
00300 
00301 template <typename node_t>
00302 struct XpetraTraits<Xpetra::CrsMatrix<double, int, int, node_t> >
00303 {
00304   typedef double scalar_t;
00305   typedef int lno_t;
00306   typedef int gno_t;
00307   typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> x_matrix_t;
00308   typedef Xpetra::TpetraCrsMatrix<scalar_t, lno_t, gno_t, node_t> xt_matrix_t;
00309   typedef Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> t_matrix_t; 
00310   typedef Xpetra::EpetraCrsMatrix xe_matrix_t;
00311   typedef Epetra_CrsMatrix e_matrix_t; 
00312 
00313   static inline RCP<const x_matrix_t>
00314     convertToXpetra( const RCP<const x_matrix_t > &a)
00315     {
00316       return a;
00317     }
00318 
00319   static RCP<const x_matrix_t> doMigration(const RCP<const x_matrix_t> &from,
00320       size_t numLocalRows, const gno_t *myNewRows)
00321   {
00322     Xpetra::UnderlyingLib lib = from->getRowMap()->lib();
00323     const x_matrix_t *xm = from.get();
00324 
00325     if (lib == Xpetra::UseEpetra){
00326       // Do the import with the Epetra_CrsMatrix traits object
00327       const xe_matrix_t *xem = dynamic_cast<const xe_matrix_t *>(xm);
00328       RCP<const e_matrix_t> em = xem->getEpetra_CrsMatrix();
00329 
00330       RCP<const e_matrix_t> emnew = XpetraTraits<e_matrix_t>::doMigration(
00331         em, numLocalRows, myNewRows);
00332 
00333       RCP<const x_matrix_t> xmnew = 
00334         XpetraTraits<e_matrix_t>::convertToXpetra(emnew);
00335 
00336       return xmnew;
00337     } else{
00338       // Do the import with the Tpetra::CrsMatrix traits object
00339       const xt_matrix_t *xtm = dynamic_cast<const xt_matrix_t *>(xm);
00340       RCP<const t_matrix_t> tm = xtm->getTpetra_CrsMatrix();
00341 
00342       RCP<const t_matrix_t> tmnew = XpetraTraits<t_matrix_t>::doMigration(
00343         tm, numLocalRows, myNewRows);
00344 
00345       RCP<const x_matrix_t> xmnew = 
00346         XpetraTraits<t_matrix_t>::convertToXpetra(tmnew);
00347 
00348       return xmnew;
00349     }
00350   }
00351 };
00352 
00353 
00355 // Tpetra::CrsGraph
00356 template <typename lno_t,
00357           typename gno_t,
00358           typename node_t>
00359 struct XpetraTraits<Tpetra::CrsGraph<lno_t, gno_t, node_t> >
00360 {
00361   typedef typename Xpetra::CrsGraph<lno_t, gno_t, node_t> xgraph_t;
00362   typedef typename Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xtgraph_t;
00363   typedef typename Tpetra::CrsGraph<lno_t, gno_t, node_t> tgraph_t;
00364 
00365   static inline RCP<const xgraph_t> convertToXpetra(
00366     const RCP<const tgraph_t> &a)
00367     {
00368       return rcp(new xtgraph_t(rcp_const_cast<tgraph_t>(a)));
00369     }
00370 
00371   static RCP<const tgraph_t> doMigration(const RCP<const tgraph_t> &from,
00372       size_t numLocalRows, const gno_t *myNewRows)
00373   {
00374     typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
00375     lno_t base = 0;
00376 
00377     // source map
00378     const RCP<const map_t> &smap = from->getRowMap();
00379     int oldNumElts = smap->getNodeNumElements();
00380     gno_t numGlobalRows = smap->getGlobalNumElements();
00381 
00382     // target map
00383     ArrayView<const gno_t> rowList(myNewRows, numLocalRows);
00384     const RCP<const Teuchos::Comm<int> > &comm = from->getComm();
00385     RCP<const map_t> tmap = rcp(
00386       new map_t(numGlobalRows, rowList, base, comm));
00387 
00388     // importer
00389     Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
00390 
00391     // number of entries in my new rows
00392     typedef Tpetra::Vector<gno_t, lno_t, gno_t, node_t> vector_t;
00393     vector_t numOld(smap);
00394     vector_t numNew(tmap);
00395     for (int lid=0; lid < oldNumElts; lid++){
00396       numOld.replaceGlobalValue(smap->getGlobalElement(lid),
00397         from->getNumEntriesInLocalRow(lid));
00398     }
00399     numNew.doImport(numOld, importer, Tpetra::INSERT);
00400 
00401     size_t numElts = tmap->getNodeNumElements();
00402     ArrayRCP<const gno_t> nnz;
00403     if (numElts > 0)
00404       nnz = numNew.getData(0);    // hangs if vector len == 0
00405 
00406     ArrayRCP<const size_t> nnz_size_t;
00407 
00408     if (numElts && sizeof(gno_t) != sizeof(size_t)){
00409       size_t *vals = new size_t [numElts];
00410       nnz_size_t = arcp(vals, 0, numElts, true);
00411       for (size_t i=0; i < numElts; i++){
00412         vals[i] = static_cast<size_t>(nnz[i]);
00413       }
00414     }
00415     else{
00416       nnz_size_t = arcp_reinterpret_cast<const size_t>(nnz);
00417     }
00418 
00419     // target graph
00420     RCP<tgraph_t> G = rcp(new tgraph_t(tmap, nnz_size_t, Tpetra::StaticProfile));
00421 
00422     G->doImport(*from, importer, Tpetra::INSERT);
00423     G->fillComplete();
00424 
00425     return G;
00426   }
00427 
00428 };
00429 
00431 // Epetra_CrsGraph
00432 template < >
00433 struct XpetraTraits<Epetra_CrsGraph>
00434 {
00435   typedef InputTraits<Epetra_CrsGraph>::lno_t    lno_t;
00436   typedef InputTraits<Epetra_CrsGraph>::gno_t    gno_t;
00437   typedef InputTraits<Epetra_CrsGraph>::node_t   node_t;
00438   static inline RCP<const Xpetra::CrsGraph<lno_t,gno_t,node_t> >
00439     convertToXpetra(const RCP<const Epetra_CrsGraph> &a)
00440     {
00441       return rcp(new Xpetra::EpetraCrsGraph(
00442                              rcp_const_cast<Epetra_CrsGraph>(a)));
00443     }
00444 
00445   static RCP<const Epetra_CrsGraph> doMigration(
00446       const RCP<const Epetra_CrsGraph> &from,
00447       size_t numLocalRows, const gno_t *myNewRows)
00448   {
00449     lno_t base = 0;
00450 
00451     // source map
00452     const Epetra_BlockMap &smap = from->RowMap();
00453     gno_t numGlobalRows = smap.NumGlobalElements();
00454     lno_t oldNumElts = smap.NumMyElements();
00455 
00456     // target map
00457     const Epetra_Comm &comm = from->Comm();
00458     Epetra_BlockMap tmap(numGlobalRows, numLocalRows, 
00459        myNewRows, 1, base, comm);
00460     lno_t newNumElts = tmap.NumMyElements();
00461 
00462     // importer
00463     Epetra_Import importer(tmap, smap);
00464 
00465     // number of non zeros in my new rows
00466     Epetra_Vector numOld(smap);
00467     Epetra_Vector numNew(tmap);
00468 
00469     for (int lid=0; lid < oldNumElts; lid++){
00470       numOld[lid] = from->NumMyIndices(lid);
00471     }
00472     numNew.Import(numOld, importer, Insert);
00473 
00474     Array<int> nnz(newNumElts);
00475     for (int lid=0; lid < newNumElts; lid++){
00476       nnz[lid] = static_cast<int>(numNew[lid]);
00477     }
00478 
00479     // target graph
00480     RCP<Epetra_CrsGraph> G = rcp(new Epetra_CrsGraph(::Copy, tmap, nnz.getRawPtr(), true));
00481     G->Import(*from, importer, Insert);
00482     G->FillComplete();
00483 
00484     return G;
00485   }
00486 
00487 };
00488 
00490 // Xpetra::CrsGraph
00491 // KDDKDD Do we need specializations for Xpetra::TpetraCrsGraph and
00492 // KDDKDD Xpetra::EpetraCrsGraph?
00493 template <typename lno_t,
00494           typename gno_t,
00495           typename node_t>
00496 struct XpetraTraits<Xpetra::CrsGraph<lno_t, gno_t, node_t> >
00497 {
00498   typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> x_graph_t;
00499   typedef Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xt_graph_t;
00500   typedef Tpetra::CrsGraph<lno_t,gno_t,node_t> t_graph_t; 
00501 
00502   static inline RCP<const x_graph_t>
00503     convertToXpetra(const RCP<const x_graph_t> &a)
00504     {
00505       return a;
00506     }
00507 
00508   static RCP<const x_graph_t> doMigration(const RCP<const x_graph_t> &from,
00509       size_t numLocalRows, const gno_t *myNewRows)
00510   {
00511     Xpetra::UnderlyingLib lib = from->getRowMap()->lib();
00512 
00513     if (lib == Xpetra::UseEpetra){
00514        throw std::logic_error("compiler should have used specialization");
00515     } else{
00516       // Do the import with the Tpetra::CrsGraph traits object
00517       const x_graph_t *xg = from.get();
00518       const xt_graph_t *xtg = dynamic_cast<const xt_graph_t *>(xg);
00519       RCP<const t_graph_t> tg = xtg->getTpetra_CrsGraph();
00520 
00521       RCP<const t_graph_t> tgnew = XpetraTraits<t_graph_t>::doMigration(
00522         tg, numLocalRows, myNewRows);
00523 
00524       RCP<const x_graph_t> xgnew =
00525         XpetraTraits<t_graph_t>::convertToXpetra(tgnew);
00526       return xgnew;
00527     }
00528   }
00529 };
00530 
00531 
00532 
00534 // Xpetra::RowMatrix
00535 template <typename scalar_t,
00536           typename lno_t,
00537           typename gno_t,
00538           typename node_t>
00539 struct XpetraTraits<Xpetra::RowMatrix<scalar_t, lno_t, gno_t, node_t> >
00540 {
00541   typedef Xpetra::RowMatrix<scalar_t, lno_t, gno_t, node_t> x_matrix_t;
00542   typedef Xpetra::TpetraRowMatrix<scalar_t, lno_t, gno_t, node_t> xt_matrix_t;
00543   typedef Tpetra::RowMatrix<scalar_t,lno_t,gno_t,node_t> t_matrix_t; 
00544 
00545   static inline RCP<const x_matrix_t>
00546     convertToXpetra( const RCP<const x_matrix_t > &a)
00547     {
00548       return a;
00549     }
00550 
00551   static RCP<const x_matrix_t> doMigration(const RCP<const x_matrix_t> &from,
00552       size_t numLocalRows, const gno_t *myNewRows)
00553   {
00554     Xpetra::UnderlyingLib lib = from->getRowMap()->lib();
00555 
00556     if (lib == Xpetra::UseEpetra){
00557        throw std::logic_error("compiler should have used specialization");
00558     } else{
00559       // Do the import with the Tpetra::CrsMatrix traits object
00560       const x_matrix_t *xm = from.get();
00561       const xt_matrix_t *xtm = dynamic_cast<const xt_matrix_t *>(xm);
00562       RCP<const t_matrix_t> tm = xtm->getTpetra_CrsMatrix();
00563 
00564       RCP<const t_matrix_t> tmnew = XpetraTraits<t_matrix_t>::doMigration(
00565         tm, numLocalRows, myNewRows);
00566 
00567       RCP<const x_matrix_t> xmnew = 
00568         XpetraTraits<t_matrix_t>::convertToXpetra(tmnew);
00569 
00570       return xmnew;
00571     }
00572   }
00573 };
00574 
00576 // Xpetra::CrsGraph specialization
00577 template < typename node_t>
00578 struct XpetraTraits<Xpetra::CrsGraph<int, int, node_t> >
00579 {
00580   typedef int lno_t;
00581   typedef int gno_t;
00582   typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> x_graph_t;
00583   typedef Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xt_graph_t;
00584   typedef Tpetra::CrsGraph<lno_t,gno_t,node_t> t_graph_t; 
00585   typedef Xpetra::EpetraCrsGraph xe_graph_t;
00586   typedef Epetra_CrsGraph e_graph_t; 
00587 
00588   static inline RCP<const x_graph_t>
00589     convertToXpetra(const RCP<const x_graph_t> &a)
00590     {
00591       return a;
00592     }
00593 
00594   static RCP<const x_graph_t> doMigration(const RCP<const x_graph_t> &from,
00595       size_t numLocalRows, const gno_t *myNewRows)
00596   {
00597     Xpetra::UnderlyingLib lib = from->getRowMap()->lib();
00598     const x_graph_t *xg = from.get();
00599 
00600     if (lib == Xpetra::UseEpetra){
00601       // Do the import with the Epetra_CrsGraph traits object
00602       const xe_graph_t *xeg = dynamic_cast<const xe_graph_t *>(xg);
00603       RCP<const e_graph_t> eg = xeg->getEpetra_CrsGraph();
00604 
00605       RCP<const e_graph_t> egnew = XpetraTraits<e_graph_t>::doMigration(
00606         eg, numLocalRows, myNewRows);
00607 
00608       RCP<const x_graph_t> xgnew =
00609         XpetraTraits<e_graph_t>::convertToXpetra(egnew);
00610 
00611       return xgnew;
00612     } else{
00613       // Do the import with the Tpetra::CrsGraph traits object
00614       const xt_graph_t *xtg = dynamic_cast<const xt_graph_t *>(xg);
00615       RCP<const t_graph_t> tg = xtg->getTpetra_CrsGraph();
00616 
00617       RCP<const t_graph_t> tgnew = XpetraTraits<t_graph_t>::doMigration(
00618         tg, numLocalRows, myNewRows);
00619 
00620       RCP<const x_graph_t> xgnew =
00621         XpetraTraits<t_graph_t>::convertToXpetra(tgnew);
00622 
00623       return xgnew;
00624     }
00625   }
00626 };
00627 
00629 // Tpetra::Vector
00630 template <typename scalar_t,
00631           typename lno_t,
00632           typename gno_t,
00633           typename node_t>
00634 struct XpetraTraits<Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> >
00635 {
00636   typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
00637   typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
00638   typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
00639 
00640   static inline RCP<const x_vector_t>
00641     convertToXpetra(const RCP<const t_vector_t> &a)
00642     {
00643       return rcp(new xt_vector_t(rcp_const_cast<t_vector_t>(a)));
00644     }
00645 
00646   static RCP<const t_vector_t> doMigration(const RCP<const t_vector_t> &from,
00647       size_t numLocalElts, const gno_t *myNewElts)
00648   {
00649     lno_t base = 0;
00650     typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
00651 
00652     // source map
00653     const RCP<const map_t> &smap = from->getMap();
00654     gno_t numGlobalElts = smap->getGlobalNumElements();
00655 
00656     // target map
00657     ArrayView<const gno_t> eltList(myNewElts, numLocalElts);
00658     const RCP<const Teuchos::Comm<int> > comm = from->getMap()->getComm();
00659     RCP<const map_t> tmap = rcp(
00660       new map_t(numGlobalElts, eltList, base, comm));
00661 
00662     // importer
00663     Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
00664 
00665     // target vector 
00666     RCP<t_vector_t> V = 
00667       Tpetra::createVector<scalar_t,lno_t,gno_t,node_t>(tmap);
00668     V->doImport(*from, importer, Tpetra::INSERT);
00669 
00670     return V;
00671   }
00672 };
00673 
00675 // Epetra_Vector
00676 template < >
00677 struct XpetraTraits<Epetra_Vector>
00678 {
00679   typedef InputTraits<Epetra_Vector>::lno_t    lno_t;
00680   typedef InputTraits<Epetra_Vector>::gno_t    gno_t;
00681   typedef InputTraits<Epetra_Vector>::node_t   node_t;
00682   typedef InputTraits<Epetra_Vector>::scalar_t   scalar_t;
00683   
00684   typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
00685 
00686   static inline RCP<const x_vector_t>
00687     convertToXpetra(const RCP<const Epetra_Vector> &a)
00688     {
00689       RCP<Xpetra::EpetraVector> xev = rcp(
00690         new Xpetra::EpetraVector(rcp_const_cast<Epetra_Vector>(a)));
00691       return rcp_implicit_cast<x_vector_t>(xev);
00692     }
00693 
00694   static RCP<Epetra_Vector> doMigration(const RCP<const Epetra_Vector> &from,
00695       size_t numLocalElts, const gno_t *myNewElts)
00696   {
00697     lno_t base = 0;
00698     // source map
00699     const Epetra_BlockMap &smap = from->Map();
00700     gno_t numGlobalElts = smap.NumGlobalElements();
00701 
00702     // target map
00703     const Epetra_Comm &comm = from->Comm();
00704     const Epetra_BlockMap tmap(numGlobalElts, numLocalElts, myNewElts, 
00705       1, base, comm);
00706 
00707     // importer
00708     Epetra_Import importer(tmap, smap);
00709 
00710     // target vector 
00711     RCP<Epetra_Vector> V = rcp(new Epetra_Vector(tmap, true));
00712     Epetra_CombineMode c = Insert;
00713     V->Import(*from, importer, c);
00714 
00715     return V;
00716   }
00717 };
00718 
00720 // Xpetra::Vector
00721 template <typename scalar_t,
00722           typename lno_t,
00723           typename gno_t,
00724           typename node_t>
00725 struct XpetraTraits<Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> >
00726 {
00727   typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
00728   typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
00729   typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
00730 
00731   static inline RCP<const x_vector_t>
00732     convertToXpetra(const RCP<const x_vector_t> &a)
00733     {
00734       return a;
00735     }
00736 
00737   static RCP<const x_vector_t> doMigration(const RCP<const x_vector_t> &from,
00738       size_t numLocalRows, const gno_t *myNewRows)
00739   {
00740     Xpetra::UnderlyingLib lib = from->getMap()->lib();
00741 
00742     if (lib == Xpetra::UseEpetra){
00743        throw std::logic_error("compiler should have used specialization");
00744     } else{
00745       // Do the import with the Tpetra::Vector traits object
00746       const x_vector_t *xv = from.get();
00747       const xt_vector_t *xtv = dynamic_cast<const xt_vector_t *>(xv);
00748       RCP<const t_vector_t> tv = xtv->getTpetra_Vector();
00749 
00750       RCP<const t_vector_t> tvnew = XpetraTraits<t_vector_t>::doMigration(
00751         tv, numLocalRows, myNewRows);
00752 
00753       RCP<const x_vector_t> xvnew =
00754         XpetraTraits<t_vector_t>::convertToXpetra(tvnew);
00755 
00756       return xvnew;
00757     }
00758   }
00759 };
00760 
00762 // Xpetra::Vector specialization
00763 template <typename node_t>
00764 struct XpetraTraits<Xpetra::Vector<double, int, int, node_t> >
00765 {
00766   typedef double scalar_t;
00767   typedef int lno_t;
00768   typedef int gno_t;
00769   typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
00770   typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
00771   typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
00772   typedef Xpetra::EpetraVector xe_vector_t;
00773   typedef Epetra_Vector e_vector_t;
00774 
00775   static inline RCP<const x_vector_t>
00776     convertToXpetra(const RCP<const x_vector_t> &a)
00777     {
00778       return a;
00779     }
00780 
00781   static RCP<const x_vector_t> doMigration(const RCP<const x_vector_t> &from,
00782       size_t numLocalRows, const gno_t *myNewRows)
00783   {
00784     Xpetra::UnderlyingLib lib = from->getMap()->lib();
00785     const x_vector_t *vec = from.get();
00786 
00787     if (lib == Xpetra::UseEpetra){
00788       // Do the import with the Epetra_Vector traits object
00789       const xe_vector_t *xev = dynamic_cast<const xe_vector_t *>(vec);
00790       RCP<const e_vector_t> ev = rcp(xev->getEpetra_Vector());
00791 
00792       RCP<const e_vector_t> evnew = XpetraTraits<e_vector_t>::doMigration(
00793         ev, numLocalRows, myNewRows);
00794 
00795       RCP<const x_vector_t> xvnew =
00796         XpetraTraits<e_vector_t>::convertToXpetra(evnew);
00797           
00798       return xvnew;
00799     } else{
00800       // Do the import with the Tpetra::Vector traits object
00801       const xt_vector_t *xtv = dynamic_cast<const xt_vector_t *>(vec);
00802       RCP<t_vector_t> tv = xtv->getTpetra_Vector();
00803       RCP<const t_vector_t> ctv = rcp_const_cast<const t_vector_t>(tv);
00804 
00805       RCP<const t_vector_t> tvnew = XpetraTraits<t_vector_t>::doMigration(
00806         ctv, numLocalRows, myNewRows);
00807 
00808       RCP<const x_vector_t> xvnew =
00809         XpetraTraits<t_vector_t>::convertToXpetra(tvnew);
00810 
00811       return xvnew;
00812     }
00813   }
00814 };
00815 
00817 // Tpetra::MultiVector
00818 template <typename scalar_t,
00819           typename lno_t,
00820           typename gno_t,
00821           typename node_t>
00822 struct XpetraTraits<Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >
00823 {
00824   typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
00825   typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
00826   typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
00827 
00828   static inline RCP<const x_vector_t>
00829     convertToXpetra(const RCP<const t_vector_t> &a)
00830     {
00831       return rcp(new xt_vector_t(rcp_const_cast<t_vector_t>(a)));
00832     }
00833 
00834   static RCP<const t_vector_t> doMigration(const RCP<const t_vector_t> &from,
00835       size_t numLocalElts, const gno_t *myNewElts)
00836   {
00837     typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
00838     lno_t base = 0;
00839 
00840     // source map
00841     const RCP<const map_t> &smap = from->getMap();
00842     gno_t numGlobalElts = smap->getGlobalNumElements();
00843 
00844     // target map
00845     ArrayView<const gno_t> eltList(myNewElts, numLocalElts);
00846     const RCP<const Teuchos::Comm<int> > comm = from->getMap()->getComm();
00847     RCP<const map_t> tmap = rcp(
00848       new map_t(numGlobalElts, eltList, base, comm));
00849 
00850     // importer
00851     Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
00852 
00853     // target vector 
00854     RCP<t_vector_t> MV = rcp(
00855       new t_vector_t(tmap, from->getNumVectors(), true));
00856     MV->doImport(*from, importer, Tpetra::INSERT);
00857 
00858     return MV;
00859   }
00860 };
00861 
00863 // Epetra_MultiVector
00864 template < >
00865 struct XpetraTraits<Epetra_MultiVector>
00866 {
00867   typedef InputTraits<Epetra_MultiVector>::lno_t    lno_t;
00868   typedef InputTraits<Epetra_MultiVector>::gno_t    gno_t;
00869   typedef InputTraits<Epetra_MultiVector>::node_t   node_t;
00870   typedef InputTraits<Epetra_MultiVector>::scalar_t   scalar_t;
00871   typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
00872 
00873   static inline RCP<const x_mvector_t>
00874     convertToXpetra(const RCP<const Epetra_MultiVector> &a)
00875     {
00876       RCP<Xpetra::EpetraMultiVector> xemv = rcp(
00877         new Xpetra::EpetraMultiVector(
00878           rcp_const_cast<Epetra_MultiVector>(a)));
00879       return rcp_implicit_cast<x_mvector_t>(xemv);
00880     }
00881 
00882   static RCP<Epetra_MultiVector> doMigration(
00883     const RCP<const Epetra_MultiVector> &from,
00884     size_t numLocalElts, const gno_t *myNewElts)
00885   {
00886     lno_t base = 0;
00887     // source map
00888     const Epetra_BlockMap &smap = from->Map();
00889     gno_t numGlobalElts = smap.NumGlobalElements();
00890 
00891     // target map
00892     const Epetra_Comm &comm = from->Comm();
00893     const Epetra_BlockMap tmap(numGlobalElts, numLocalElts, myNewElts, 
00894       1, base, comm);
00895 
00896     // importer
00897     Epetra_Import importer(tmap, smap);
00898 
00899     // target vector 
00900     RCP<Epetra_MultiVector> MV = rcp(
00901       new Epetra_MultiVector(tmap, from->NumVectors(), true));
00902     Epetra_CombineMode c = Insert;
00903     MV->Import(*from, importer, c);
00904 
00905     return MV;
00906   }
00907 };
00908 
00910 // Xpetra::MultiVector
00911 template <typename scalar_t,
00912           typename lno_t,
00913           typename gno_t,
00914           typename node_t>
00915 struct XpetraTraits<Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >
00916 {
00917   typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
00918   typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_mvector_t;
00919   typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_mvector_t;
00920 
00921   static inline RCP<const x_mvector_t>
00922     convertToXpetra(const RCP<const x_mvector_t> &a)
00923     {
00924       return a;
00925     }
00926 
00927   static RCP<const x_mvector_t> doMigration(const RCP<const x_mvector_t> &from,
00928       size_t numLocalRows, const gno_t *myNewRows)
00929   {
00930     Xpetra::UnderlyingLib lib = from->getMap()->lib();
00931 
00932     if (lib == Xpetra::UseEpetra){
00933        throw std::logic_error("compiler should have used specialization");
00934     } else{
00935       // Do the import with the Tpetra::MultiVector traits object
00936       const x_mvector_t *xmv = from.get();
00937       const xt_mvector_t *xtv = dynamic_cast<const xt_mvector_t *>(xmv);
00938       RCP<t_mvector_t> tv = xtv->getTpetra_MultiVector();
00939       RCP<const t_mvector_t> ctv = rcp_const_cast<const t_mvector_t>(tv);
00940 
00941       RCP<const t_mvector_t> tvnew = XpetraTraits<t_mvector_t>::doMigration(
00942         ctv, numLocalRows, myNewRows);
00943 
00944       RCP<const x_mvector_t> xvnew =
00945         XpetraTraits<t_mvector_t>::convertToXpetra(tvnew);
00946 
00947       return xvnew;
00948     }
00949   }
00950 };
00951 
00953 // Xpetra::MultiVector specialization
00954 template <typename node_t>
00955 struct XpetraTraits<Xpetra::MultiVector<double, int, int, node_t> >
00956 {
00957   typedef double scalar_t;
00958   typedef int lno_t;
00959   typedef int gno_t;
00960   typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
00961   typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_mvector_t;
00962   typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_mvector_t;
00963   typedef Xpetra::EpetraMultiVector xe_mvector_t;
00964   typedef Epetra_MultiVector e_mvector_t;
00965 
00966   static inline RCP<const x_mvector_t>
00967     convertToXpetra(const RCP<const x_mvector_t> &a)
00968     {
00969       return a;
00970     }
00971 
00972   static RCP<const x_mvector_t> doMigration(const RCP<const x_mvector_t> &from,
00973       size_t numLocalRows, const gno_t *myNewRows)
00974   {
00975     Xpetra::UnderlyingLib lib = from->getMap()->lib();
00976     const x_mvector_t *xmv = from.get();
00977 
00978     if (lib == Xpetra::UseEpetra){
00979       // Do the import with the Epetra_MultiVector traits object
00980       const xe_mvector_t *xev = dynamic_cast<const xe_mvector_t *>(xmv);
00981       RCP<e_mvector_t> ev = xev->getEpetra_MultiVector();
00982       RCP<const e_mvector_t> cev = rcp_const_cast<const e_mvector_t>(ev);
00983 
00984       RCP<const e_mvector_t> evnew = XpetraTraits<e_mvector_t>::doMigration(
00985         cev, numLocalRows, myNewRows);
00986 
00987       RCP<const x_mvector_t> xvnew =
00988         XpetraTraits<e_mvector_t>::convertToXpetra(evnew);
00989 
00990       return xvnew;
00991 
00992     } else{
00993       // Do the import with the Tpetra::MultiVector traits object
00994       const xt_mvector_t *xtv = dynamic_cast<const xt_mvector_t *>(xmv);
00995       RCP<t_mvector_t> tv = xtv->getTpetra_MultiVector();
00996       RCP<const t_mvector_t> ctv = rcp_const_cast<const t_mvector_t>(tv);
00997 
00998       RCP<const t_mvector_t> tvnew = XpetraTraits<t_mvector_t>::doMigration(
00999         ctv, numLocalRows, myNewRows);
01000 
01001       RCP<const x_mvector_t> xvnew =
01002         XpetraTraits<t_mvector_t>::convertToXpetra(tvnew);
01003 
01004       return xvnew;
01005     }
01006   }
01007 };
01008 
01009 #endif // DOXYGEN_SHOULD_SKIP_THIS
01010 
01011 }  //namespace Zoltan2
01012 
01013 #endif // _ZOLTAN2_XPETRATRAITS_HPP_