Tpetra Matrix/Vector Services Version of the Day
Tpetra_RTI_detail.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 // 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00038 // 
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #ifndef TPETRA_RTI_detail_HPP
00043 #define TPETRA_RTI_detail_HPP
00044 
00045 #include <Teuchos_Assert.hpp>
00046 #include <Teuchos_CommHelpers.hpp>
00047 #include <Kokkos_NodeHelpers.hpp>
00048 
00049 #include "Tpetra_Vector.hpp"
00050 
00051 namespace Tpetra {
00052 
00053   namespace RTI {
00054 
00056     namespace detail {
00057 
00059       template <class S>
00060       class StdOpKernel
00061       {
00062         protected:
00063           S _alpha, _beta;
00064           S       * _vec_inout;
00065           const S * _vec_in2;
00066         public:
00067           inline StdOpKernel() : _alpha(ScalarTraits<S>::one()), _beta(ScalarTraits<S>::zero()) {}
00068           inline void setData(S * vec_inout, const S * vec_in2)   { _vec_inout = vec_inout; _vec_in2 = vec_in2; }
00069           inline void setAlphaBeta(const S &alpha, const S &beta) { _alpha = alpha; _beta = beta; }
00070       };
00071 
00073       template <class OP, class S>
00074       class UnaryFunctorAdapter {
00075         protected:
00076           OP   _op;
00077           S  * _vec;
00078         public:
00079           UnaryFunctorAdapter(OP op) : _op(op) {}
00080           inline void setData(S *vec)                    { _vec = vec;             }
00081           inline void execute(int i)                     { _vec[i] = _op(_vec[i]); }
00082       };
00083 
00085       template <class OP, class S1, class S2>
00086       class BinaryFunctorAdapter {
00087         protected:
00088           OP         _op;
00089           S1       * _vec_inout;
00090           const S2 * _vec_in2;
00091         public:
00092           BinaryFunctorAdapter(OP op) : _op(op)    {}
00093           inline void setData(S1 *vec_inout, const S2 *vec_in2) { _vec_inout = vec_inout; _vec_in2 = vec_in2;   }
00094           inline void execute(int i)                            { _vec_inout[i] = _op(_vec_inout[i], _vec_in2[i]); }
00095       };
00096 
00098       template <class OP, class S>
00099       class BinaryFunctorAdapterWithAlphaBeta : public StdOpKernel<S> {
00100         protected:
00101           OP        _op;
00102           S       * _vec_inout;
00103           const S * _vec_in2;
00104         public:
00105           BinaryFunctorAdapterWithAlphaBeta(OP op) : _op(op)  {}
00106           inline void setData(S *vec_inout, const S *vec_in2) { _vec_inout = vec_inout; _vec_in2 = vec_in2;   }
00107           inline void execute(int i) 
00108           { 
00109             S res = _op(_vec_inout[i], _vec_in2[i]); 
00110             _vec_inout[i] = this->_alpha * res + this->_beta * _vec_inout[i];
00111           }
00112       };
00113 
00115       template <class OP, class S1, class S2, class S3>
00116       class TertiaryFunctorAdapter {
00117         protected:
00118           OP         _op;
00119           S1       * _vec_inout;
00120           const S2 * _vec_in2;
00121           const S3 * _vec_in3;
00122         public:
00123           TertiaryFunctorAdapter(OP op) : _op(op)    {}
00124           inline void setData(S1 *vec_inout, const S2 *vec_in2, const S3 *vec_in3) { _vec_inout = vec_inout; _vec_in2 = vec_in2; _vec_in3 = vec_in3;  }
00125           inline void execute(int i)                            { _vec_inout[i] = _op(_vec_inout[i], _vec_in2[i], _vec_in3[i]); }
00126       };
00127 
00129       template <class Glob, class S>
00130       class RTIReductionAdapter1 {
00131         public:
00132           typedef typename Glob::GenOP                GenOP;
00133           typedef typename Glob::RedOP                RedOP;
00134           typedef typename Glob::IdOP                  IdOP;
00135           typedef typename RedOP::result_type ReductionType;
00136         protected:
00137           GenOP      _genop;
00138           RedOP      _redop;
00139           const S * _vec_in;
00140         public:
00141           RTIReductionAdapter1(Glob glob)                               : _genop(glob.genop), _redop(glob.redop)  {}
00142           inline void setData(const S *vec_in)                          { _vec_in = vec_in;                        }
00143           static inline ReductionType identity()                        { return IdOP::identity();                 }
00144           inline ReductionType generate(int i)                          { return _genop(_vec_in[i]);               }
00145           inline ReductionType reduce(ReductionType a, ReductionType b) { return _redop(a, b);                     }
00146       };
00147 
00149       template <class Glob, class S1, class S2>
00150       class RTIReductionAdapter2 {
00151         public:
00152           typedef typename Glob::GenOP                GenOP;
00153           typedef typename Glob::RedOP                RedOP;
00154           typedef typename Glob::IdOP                  IdOP;
00155           typedef typename RedOP::result_type ReductionType;
00156         protected:
00157           GenOP      _genop;
00158           RedOP      _redop;
00159           const S1 * _vec_in1;
00160           const S2 * _vec_in2;
00161         public:
00162           RTIReductionAdapter2(Glob glob)                               : _genop(glob.genop), _redop(glob.redop)  {}
00163           inline void setData(const S1 *vec_in1, const S2 *vec_in2)     { _vec_in1 = vec_in1; _vec_in2 = vec_in2;  }
00164           static inline ReductionType identity()                        { return IdOP::identity();                 }
00165           inline ReductionType generate(int i)                          { return _genop(_vec_in1[i], _vec_in2[i]); }
00166           inline ReductionType reduce(ReductionType a, ReductionType b) { return _redop(a, b);                     }
00167       };
00168 
00170       template <class Glob, class S1, class S2, class S3>
00171       class RTIReductionAdapter3 {
00172         public:
00173           typedef typename Glob::GenOP                GenOP;
00174           typedef typename Glob::RedOP                RedOP;
00175           typedef typename Glob::IdOP                  IdOP;
00176           typedef typename RedOP::result_type ReductionType;
00177         protected:
00178           GenOP      _genop;
00179           RedOP      _redop;
00180           const S1 * _vec_in1;
00181           const S2 * _vec_in2;
00182           const S3 * _vec_in3;
00183         public:
00184           RTIReductionAdapter3(Glob glob)                                              : _genop(glob.genop), _redop(glob.redop)                     {}
00185           inline void setData(const S1 *vec_in1, const S2 *vec_in2, const S3 *vec_in3) { _vec_in1 = vec_in1; _vec_in2 = vec_in2; _vec_in3 = vec_in3; }
00186           static inline ReductionType identity()                                       { return IdOP::identity();                                    }
00187           inline ReductionType generate(int i)                                         { return _genop(_vec_in1[i], _vec_in2[i], _vec_in3[i]);       }
00188           inline ReductionType reduce(ReductionType a, ReductionType b)                { return _redop(a, b);                                        }
00189       };
00190 
00192       template <class Glob, class S1, class S2>
00193       class RTIPreTransformReductionAdapter {
00194         public:
00195           typedef typename Glob::TOP                    TOP;
00196           typedef typename Glob::GenOP                GenOP;
00197           typedef typename Glob::RedOP                RedOP;
00198           typedef typename Glob::IdOP                  IdOP;
00199           typedef typename RedOP::result_type ReductionType;
00200         protected:
00201           TOP        _top;
00202           GenOP      _genop;
00203           RedOP      _redop;
00204           S1       * _vec_inout;
00205           const S2 * _vec_in2;
00206         public:
00207           RTIPreTransformReductionAdapter(Glob glob)                    : _top(glob.top), _genop(glob.genop), _redop(glob.redop) {}
00208           inline void setData(S1 *vec_inout, const S2 *vec_in2)         { _vec_inout = vec_inout; _vec_in2 = vec_in2; }
00209           static inline ReductionType identity()                        { return IdOP::identity();                    }
00210           inline ReductionType reduce(ReductionType a, ReductionType b) { return _redop(a, b);                        }
00211           inline ReductionType generate(int i)
00212           {
00213             _vec_inout[i] = _top( _vec_inout[i], _vec_in2[i] );
00214             return _genop( _vec_inout[i], _vec_in2[i] ); 
00215           }
00216       };
00217 
00219       template <class Glob, class S1, class S2, class S3>
00220       class RTIPreTransformReductionAdapter3 {
00221         public:
00222           typedef typename Glob::TOP                    TOP;
00223           typedef typename Glob::GenOP                GenOP;
00224           typedef typename Glob::RedOP                RedOP;
00225           typedef typename Glob::IdOP                  IdOP;
00226           typedef typename RedOP::result_type ReductionType;
00227         protected:
00228           TOP        _top;
00229           GenOP      _genop;
00230           RedOP      _redop;
00231           S1       * _vec_inout;
00232           const S2 * _vec_in2;
00233           const S3 * _vec_in3;
00234         public:
00235           RTIPreTransformReductionAdapter3(Glob glob)                              : _top(glob.top), _genop(glob.genop), _redop(glob.redop) {}
00236           inline void setData(S1 *vec_inout, const S2 *vec_in2, const S3 *vec_in3) { _vec_inout = vec_inout; _vec_in2 = vec_in2; _vec_in3 = vec_in3; }
00237           static inline ReductionType identity()                                   { return IdOP::identity();                    }
00238           inline ReductionType reduce(ReductionType a, ReductionType b)            { return _redop(a, b);                        }
00239           inline ReductionType generate(int i)
00240           {
00241             _vec_inout[i] = _top( _vec_inout[i], _vec_in2[i], _vec_in3[i] );
00242             return _genop( _vec_inout[i], _vec_in2[i], _vec_in3[i] ); 
00243           }
00244       };
00245 
00247       template <class OP>
00248       class TeuchosValueTypeReductionOpAdapter : public Teuchos::ValueTypeReductionOp<int,typename OP::ReductionType> 
00249       {
00250         protected:
00251           mutable OP _op;
00252         public:
00253           typedef typename OP::ReductionType Packet;
00254           TeuchosValueTypeReductionOpAdapter(OP op) : _op(op) {}
00255           void reduce(const int count, const Packet inBuffer[], Packet inoutBuffer []) const 
00256           {
00257             for (int i=0; i != count; ++i) {
00258               inoutBuffer[i] = _op.reduce( inoutBuffer[i], inBuffer[i] );
00259             }
00260           }
00261       };
00262 
00264       template <class S, class LO, class GO, class Node, class OP>
00265       void unary_transform(Vector<S,LO,GO,Node> &vec, OP op) 
00266       {
00267         Kokkos::MultiVector<S,Node> &mv = vec.getLocalMVNonConst();
00268         const RCP<Node> node = mv.getNode();
00269         // ready data
00270         Kokkos::ReadyBufferHelper<Node> rbh(node);
00271         rbh.begin();
00272         S * out_ptr = rbh.addNonConstBuffer(mv.getValuesNonConst());
00273         rbh.end();
00274         op.setData(out_ptr);
00275         const size_t N = mv.getNumRows();
00276         node->template parallel_for(0, N, op);
00277       }
00278 
00280       template <class S1, class S2, class LO, class GO, class Node, class OP>
00281       void binary_transform(Vector<S1,LO,GO,Node> &vec_inout, const Vector<S2,LO,GO,Node> &vec_in2, OP op) 
00282       {
00283         Kokkos::MultiVector<S1,Node>       &mv_inout = vec_inout.getLocalMVNonConst();
00284         const Kokkos::MultiVector<S2,Node> &mv_in2   = vec_in2.getLocalMV();
00285         const RCP<Node> node = mv_inout.getNode();
00286         // ready data
00287         Kokkos::ReadyBufferHelper<Node> rbh(node);
00288         rbh.begin();
00289         S1       * out_ptr = rbh.addNonConstBuffer(mv_inout.getValuesNonConst());
00290         const S2 * in_ptr  = rbh.addConstBuffer(mv_in2.getValues());
00291         rbh.end();
00292         op.setData(out_ptr, in_ptr);
00293         const size_t N = mv_inout.getNumRows();
00294 #ifdef HAVE_TPETRA_DEBUG
00295         TEUCHOS_TEST_FOR_EXCEPTION( mv_in2.getNode() != mv_inout.getNode(), std::runtime_error, 
00296             "Tpetra::RTI::detail::binary_transform(): multivectors must share the same node.");
00297 #endif
00298         node->template parallel_for(0, N, op);
00299       }
00300 
00302       template <class S1, class S2, class S3, class LO, class GO, class Node, class OP>
00303       void tertiary_transform(Vector<S1,LO,GO,Node> &vec_inout, const Vector<S2,LO,GO,Node> &vec_in2, const Vector<S3,LO,GO,Node> &vec_in3, OP op) 
00304       {
00305         Kokkos::MultiVector<S1,Node>       &mv_inout = vec_inout.getLocalMVNonConst();
00306         const Kokkos::MultiVector<S2,Node> &mv_in2   = vec_in2.getLocalMV();
00307         const Kokkos::MultiVector<S3,Node> &mv_in3   = vec_in3.getLocalMV();
00308         const RCP<Node> node = mv_inout.getNode();
00309         // ready data
00310         Kokkos::ReadyBufferHelper<Node> rbh(node);
00311         rbh.begin();
00312         S1       * out_ptr = rbh.addNonConstBuffer(mv_inout.getValuesNonConst());
00313         const S2 * in_ptr2 = rbh.addConstBuffer(mv_in2.getValues());
00314         const S3 * in_ptr3 = rbh.addConstBuffer(mv_in3.getValues());
00315         rbh.end();
00316         op.setData(out_ptr, in_ptr2, in_ptr3);
00317         const size_t N = mv_inout.getNumRows();
00318 #ifdef HAVE_TPETRA_DEBUG
00319         TEUCHOS_TEST_FOR_EXCEPTION( mv_in2.getNode() != mv_inout.getNode() || mv_in3.getNode() != mv_in2.getNode(), std::runtime_error, 
00320             "Tpetra::RTI::detail::tertiary_transform(): multivectors must share the same node.");
00321 #endif
00322         node->template parallel_for(0, N, op);
00323       }
00324 
00326       template <class S, class LO, class GO, class Node, class OP>
00327       typename OP::ReductionType 
00328       reduce(const Vector<S,LO,GO,Node> &vec_in, OP op) 
00329       {
00330         const Kokkos::MultiVector<S,Node> &mv_in = vec_in.getLocalMV();
00331         const RCP<Node> node = mv_in.getNode();
00332         const RCP<const Teuchos::Comm<int> > comm = vec_in.getMap()->getComm();
00333         // ready data
00334         Kokkos::ReadyBufferHelper<Node> rbh(node);
00335         rbh.begin();
00336         const S * in_ptr = rbh.addConstBuffer(mv_in.getValues());
00337         rbh.end();
00338         op.setData( in_ptr );
00339         const size_t N = mv_in.getNumRows();
00340         // compute local reduction
00341         typename OP::ReductionType gbl_res, lcl_res;
00342         lcl_res = node->template parallel_reduce(0, N, op);
00343         // compute global reduction
00344         TeuchosValueTypeReductionOpAdapter<OP> vtrop(op);
00345         Teuchos::reduceAll(*comm, vtrop, 1, &lcl_res, &gbl_res);
00346         return gbl_res;
00347       }
00348 
00350       template <class S1, class S2, class LO, class GO, class Node, class OP>
00351       typename OP::ReductionType 
00352       reduce(const Vector<S1,LO,GO,Node> &vec_in1, const Vector<S2,LO,GO,Node> &vec_in2, OP op) 
00353       {
00354         const Kokkos::MultiVector<S1,Node> &mv_in1 = vec_in1.getLocalMV(),
00355                                            &mv_in2 = vec_in2.getLocalMV();
00356         const RCP<Node> node = mv_in1.getNode();
00357         const RCP<const Teuchos::Comm<int> > comm = vec_in1.getMap()->getComm();
00358         // ready data
00359         Kokkos::ReadyBufferHelper<Node> rbh(node);
00360         rbh.begin();
00361         const S1 * in_ptr1 = rbh.addConstBuffer(mv_in1.getValues());
00362         const S2 * in_ptr2 = rbh.addConstBuffer(mv_in2.getValues());
00363         rbh.end();
00364         op.setData( in_ptr1, in_ptr2 );
00365         const size_t N = mv_in1.getNumRows();
00366 #ifdef HAVE_TPETRA_DEBUG
00367         TEUCHOS_TEST_FOR_EXCEPTION( mv_in1.getNode() != mv_in2.getNode(), std::runtime_error, 
00368             "Tpetra::RTI::detail::reduce(): multivectors must share the same node.");
00369 #endif
00370         // compute local reduction
00371         typename OP::ReductionType gbl_res, lcl_res;
00372         lcl_res = node->template parallel_reduce(0, N, op);
00373         // compute global reduction
00374         TeuchosValueTypeReductionOpAdapter<OP> vtrop(op);
00375         Teuchos::reduceAll(*comm, vtrop, 1, &lcl_res, &gbl_res);
00376         return gbl_res;
00377       }
00378 
00380       template <class S1, class S2, class S3, class LO, class GO, class Node, class OP>
00381       typename OP::ReductionType 
00382       reduce(const Vector<S1,LO,GO,Node> &vec_in1, const Vector<S2,LO,GO,Node> &vec_in2, const Vector<S3,LO,GO,Node> &vec_in3, OP op) 
00383       {
00384         const Kokkos::MultiVector<S1,Node> &mv_in1 = vec_in1.getLocalMV();
00385         const Kokkos::MultiVector<S2,Node> &mv_in2 = vec_in2.getLocalMV();
00386         const Kokkos::MultiVector<S3,Node> &mv_in3 = vec_in3.getLocalMV();
00387         const RCP<Node> node = mv_in1.getNode();
00388         const RCP<const Teuchos::Comm<int> > comm = vec_in1.getMap()->getComm();
00389         // ready data
00390         Kokkos::ReadyBufferHelper<Node> rbh(node);
00391         rbh.begin();
00392         const S1 * in_ptr1 = rbh.addConstBuffer(mv_in1.getValues());
00393         const S2 * in_ptr2 = rbh.addConstBuffer(mv_in2.getValues());
00394         const S3 * in_ptr3 = rbh.addConstBuffer(mv_in3.getValues());
00395         rbh.end();
00396         op.setData( in_ptr1, in_ptr2, in_ptr3 );
00397         const size_t N = mv_in1.getNumRows();
00398 #ifdef HAVE_TPETRA_DEBUG
00399         TEUCHOS_TEST_FOR_EXCEPTION( mv_in1.getNode() != mv_in2.getNode() || mv_in2.getNode() != mv_in3.getNode(), std::runtime_error, 
00400             "Tpetra::RTI::detail::reduce(): multivectors must share the same node.");
00401 #endif
00402         // compute local reduction
00403         typename OP::ReductionType gbl_res, lcl_res;
00404         lcl_res = node->template parallel_reduce(0, N, op);
00405         // compute global reduction
00406         TeuchosValueTypeReductionOpAdapter<OP> vtrop(op);
00407         Teuchos::reduceAll(*comm, vtrop, 1, &lcl_res, &gbl_res);
00408         return gbl_res;
00409       }
00410 
00412       template <class S1, class S2, class LO, class GO, class Node, class OP>
00413       typename OP::ReductionType 
00414       transform_reduce(Vector<S1,LO,GO,Node> &vec_inout, const Vector<S2,LO,GO,Node> &vec_in2, OP op) 
00415       {
00416         Kokkos::MultiVector<S1,Node>       &mv_inout = vec_inout.getLocalMVNonConst();
00417         const Kokkos::MultiVector<S2,Node> &mv_in2   = vec_in2.getLocalMV();
00418         const RCP<Node> node = mv_inout.getNode();
00419         const RCP<const Teuchos::Comm<int> > comm = vec_inout.getMap()->getComm();
00420         // ready data
00421         Kokkos::ReadyBufferHelper<Node> rbh(node);
00422         rbh.begin();
00423         S1 * in_ptr1 = rbh.addNonConstBuffer(mv_inout.getValuesNonConst());
00424         const S2 * in_ptr2 = rbh.addConstBuffer(mv_in2.getValues());
00425         rbh.end();
00426         op.setData( in_ptr1, in_ptr2 );
00427         const size_t N = mv_inout.getNumRows();
00428 #ifdef HAVE_TPETRA_DEBUG
00429         TEUCHOS_TEST_FOR_EXCEPTION( mv_inout.getNode() != mv_in2.getNode(), std::runtime_error, 
00430             "Tpetra::RTI::detail::transform_reduce(): multivectors must share the same node.");
00431 #endif
00432         // compute local reduction
00433         typename OP::ReductionType gbl_res, lcl_res;
00434         lcl_res = node->template parallel_reduce(0, N, op);
00435         // compute global reduction
00436         TeuchosValueTypeReductionOpAdapter<OP> vtrop(op);
00437         Teuchos::reduceAll(*comm, vtrop, 1, &lcl_res, &gbl_res);
00438         return gbl_res;
00439       }
00440 
00442       template <class S1, class S2, class S3, class LO, class GO, class Node, class OP>
00443       typename OP::ReductionType 
00444       transform_reduce(Vector<S1,LO,GO,Node> &vec_inout, const Vector<S2,LO,GO,Node> &vec_in2, const Vector<S3,LO,GO,Node> &vec_in3, OP op) 
00445       {
00446         Kokkos::MultiVector<S1,Node>       &mv_inout = vec_inout.getLocalMVNonConst();
00447         const Kokkos::MultiVector<S2,Node> &mv_in2   = vec_in2.getLocalMV();
00448         const Kokkos::MultiVector<S3,Node> &mv_in3   = vec_in3.getLocalMV();
00449         const RCP<Node> node = mv_inout.getNode();
00450         const RCP<const Teuchos::Comm<int> > comm = vec_inout.getMap()->getComm();
00451         // ready data
00452         Kokkos::ReadyBufferHelper<Node> rbh(node);
00453         rbh.begin();
00454         S1 * in_ptr1 = rbh.addNonConstBuffer(mv_inout.getValuesNonConst());
00455         const S2 * in_ptr2 = rbh.addConstBuffer(mv_in2.getValues());
00456         const S3 * in_ptr3 = rbh.addConstBuffer(mv_in3.getValues());
00457         rbh.end();
00458         op.setData( in_ptr1, in_ptr2, in_ptr3 );
00459         const size_t N = mv_inout.getNumRows();
00460 #ifdef HAVE_TPETRA_DEBUG
00461         TEUCHOS_TEST_FOR_EXCEPTION( mv_inout.getNode() != mv_in2.getNode() && mv_inout.getNode() != mv_in3.getNode(), std::runtime_error, 
00462             "Tpetra::RTI::detail::transform_transform(): multivectors must share the same node.");
00463 #endif
00464         // compute local reduction
00465         typename OP::ReductionType gbl_res, lcl_res;
00466         lcl_res = node->template parallel_reduce(0, N, op);
00467         // compute global reduction
00468         TeuchosValueTypeReductionOpAdapter<OP> vtrop(op);
00469         Teuchos::reduceAll(*comm, vtrop, 1, &lcl_res, &gbl_res);
00470         return gbl_res;
00471       }
00472 
00473     } // end of namespace Tpetra::RTI::detail
00474 
00475   } // end of namespace Tpetra::RTI
00476 
00477 } // end of namespace Tpetra
00478 
00479 #endif // TPETRA_RTI_detail_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines