Tpetra Matrix/Vector Services Version of the Day
Tpetra_CrsGraph_decl.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_CRSGRAPH_DECL_HPP
00043 #define TPETRA_CRSGRAPH_DECL_HPP
00044 
00045 #include <Teuchos_CompileTimeAssert.hpp>
00046 #include <Teuchos_Describable.hpp>
00047 #include <Teuchos_ParameterListAcceptorDefaultBase.hpp>
00048 
00049 #include <Kokkos_DefaultNode.hpp>
00050 #include <Kokkos_DefaultKernels.hpp>
00051 
00052 #include "Tpetra_ConfigDefs.hpp"
00053 #include "Tpetra_RowGraph.hpp"
00054 #include "Tpetra_DistObject.hpp"
00055 #include "Tpetra_Exceptions.hpp"
00056 
00057 
00058 namespace Tpetra {
00059 
00060 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00061   // forward declaration
00062   template <class LO, class GO, class N, class SpMatOps>
00063   class CrsGraph;
00064 
00065   // forward declaration
00066   template <class S, class LO, class GO, class N, class SpMatOps>
00067   class CrsMatrix;
00068 
00069   namespace Details {
00070     template<class OutputCrsGraphType, class InputCrsGraphType>
00071     class CrsGraphCopier {
00072     public:
00073       static Teuchos::RCP<OutputCrsGraphType>
00074       clone (const InputCrsGraphType& graphIn,
00075              const Teuchos::RCP<typename OutputCrsGraphType::node_type> nodeOut,
00076              const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
00077     };
00078   } // namespace Details
00079 #endif
00080 
00089   struct RowInfo {
00090     size_t localRow;
00091     size_t allocSize;
00092     size_t numEntries;
00093     size_t offset1D;
00094   };
00095 
00096   enum ELocalGlobal {
00097     LocalIndices,
00098     GlobalIndices
00099   };
00100 
00178   template <class LocalOrdinal,
00179             class GlobalOrdinal = LocalOrdinal,
00180             class Node = KokkosClassic::DefaultNode::DefaultNodeType,
00181             class LocalMatOps = typename KokkosClassic::DefaultKernels<void,LocalOrdinal,Node>::SparseOps >
00182   class CrsGraph :
00183     public RowGraph<LocalOrdinal,GlobalOrdinal,Node>,
00184     public DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>,
00185     public Teuchos::ParameterListAcceptorDefaultBase
00186   {
00187     template <class S, class LO, class GO, class N, class SpMatOps>
00188     friend class CrsMatrix;
00189     template <class LO2, class GO2, class N2, class SpMatOps2>
00190     friend class CrsGraph;
00191     template<class OutputCrsGraphType, class InputCrsGraphType>
00192     friend class Details::CrsGraphCopier;
00193 
00194   public:
00196     typedef LocalOrdinal local_ordinal_type;
00198     typedef GlobalOrdinal global_ordinal_type;
00200     typedef Node node_type;
00201 
00203     typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, node_type> map_type;
00205     typedef Tpetra::Import<LocalOrdinal, GlobalOrdinal, node_type> import_type;
00207     typedef Tpetra::Export<LocalOrdinal, GlobalOrdinal, node_type> export_type;
00208 
00210 
00211 
00229     CrsGraph (const RCP<const map_type>& rowMap,
00230               size_t maxNumEntriesPerRow,
00231               ProfileType pftype = DynamicProfile,
00232               const RCP<ParameterList>& params = null);
00233 
00251     CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rowMap,
00252               const ArrayRCP<const size_t>& NumEntriesPerRowToAlloc,
00253               ProfileType pftype = DynamicProfile,
00254               const RCP<ParameterList>& params = null);
00255 
00275     CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rowMap,
00276               const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& colMap,
00277               size_t maxNumEntriesPerRow,
00278               ProfileType pftype = DynamicProfile,
00279               const RCP<ParameterList>& params = null);
00280 
00300     CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rowMap,
00301               const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& colMap,
00302               const ArrayRCP<const size_t> &NumEntriesPerRowToAlloc,
00303               ProfileType pftype = DynamicProfile,
00304               const RCP<ParameterList>& params = null);
00305 
00325     CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rowMap,
00326               const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& colMap,
00327               const ArrayRCP<size_t> & rowPointers,
00328               const ArrayRCP<LocalOrdinal> & columnIndices,
00329               const RCP<ParameterList>& params = null);
00330 
00331 
00359     template<class Node2>
00360     RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node2,
00361                  typename KokkosClassic::DefaultKernels<void, LocalOrdinal, Node2>::SparseOps> >
00362     clone (const Teuchos::RCP<Node2> &node2,
00363            const Teuchos::RCP<Teuchos::ParameterList> &params = null) const
00364     {
00365       typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node2,
00366         typename KokkosClassic::DefaultKernels<void, LocalOrdinal, Node2>::SparseOps> output_crs_graph_type;
00367       typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> input_crs_graph_type;
00368       typedef Details::CrsGraphCopier<output_crs_graph_type, input_crs_graph_type> copier_type;
00369       return copier_type::clone (*this, node2, params);
00370     }
00371 
00373     virtual ~CrsGraph();
00374 
00376 
00377 
00378 
00380     void setParameterList (const RCP<ParameterList>& params);
00381 
00383     RCP<const ParameterList> getValidParameters () const;
00384 
00386 
00387 
00388 
00410     void
00411     insertGlobalIndices (GlobalOrdinal globalRow,
00412                          const ArrayView<const GlobalOrdinal>& indices);
00413 
00415 
00429     void
00430     insertLocalIndices (const LocalOrdinal localRow,
00431                         const ArrayView<const LocalOrdinal> &indices);
00432 
00434 
00443     void removeLocalIndices (LocalOrdinal localRow);
00444 
00446 
00447 
00453 
00459     void globalAssemble ();
00460 
00469     void resumeFill (const RCP<ParameterList> &params = null);
00470 
00488     void
00489     fillComplete (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &domainMap,
00490                   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rangeMap,
00491                   const RCP<ParameterList> &params = null);
00492 
00499     void fillComplete (const RCP<ParameterList> &params = null);
00500 
00511     void
00512     expertStaticFillComplete (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & domainMap,
00513                               const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & rangeMap,
00514                               const RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > &importer=Teuchos::null,
00515                               const RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > &exporter=Teuchos::null,
00516                               const RCP<ParameterList> &params=Teuchos::null);
00518 
00519 
00520 
00522     RCP<const Comm<int> > getComm() const;
00523 
00525     RCP<Node> getNode() const;
00526 
00528     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > getRowMap() const;
00529 
00531     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > getColMap() const;
00532 
00534     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > getDomainMap() const;
00535 
00537     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > getRangeMap() const;
00538 
00540     RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > getImporter() const;
00541 
00543     RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > getExporter() const;
00544 
00546 
00548     global_size_t getGlobalNumRows() const;
00549 
00551 
00554     global_size_t getGlobalNumCols() const;
00555 
00557     size_t getNodeNumRows() const;
00558 
00560 
00562     size_t getNodeNumCols() const;
00563 
00565     GlobalOrdinal getIndexBase() const;
00566 
00568 
00570     global_size_t getGlobalNumEntries() const;
00571 
00573     size_t getNodeNumEntries() const;
00574 
00576 
00577     size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const;
00578 
00580 
00581     size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const;
00582 
00584 
00591     size_t getNodeAllocationSize() const;
00592 
00594 
00595     size_t getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const;
00596 
00598 
00599     size_t getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const;
00600 
00602 
00604     global_size_t getGlobalNumDiags() const;
00605 
00607 
00609     size_t getNodeNumDiags() const;
00610 
00623     size_t getGlobalMaxNumRowEntries() const;
00624 
00626 
00628     size_t getNodeMaxNumRowEntries() const;
00629 
00644     bool hasColMap() const;
00645 
00653     bool isLowerTriangular() const;
00654 
00662     bool isUpperTriangular() const;
00663 
00679     bool isLocallyIndexed() const;
00680 
00696     bool isGloballyIndexed() const;
00697 
00706     bool isFillComplete() const;
00707 
00722     bool isFillActive() const;
00723 
00725 
00728     bool isSorted() const;
00729 
00731 
00737     bool isStorageOptimized() const;
00738 
00740     ProfileType getProfileType() const;
00741 
00789     void
00790     getGlobalRowCopy (GlobalOrdinal GlobalRow,
00791                       const ArrayView<GlobalOrdinal>& Indices,
00792                       size_t& NumIndices) const;
00793 
00840     void
00841     getLocalRowCopy (LocalOrdinal LocalRow,
00842                      const ArrayView<LocalOrdinal>& indices,
00843                      size_t& NumIndices) const;
00844 
00864     void
00865     getGlobalRowView (GlobalOrdinal GlobalRow,
00866                       ArrayView<const GlobalOrdinal>& Indices) const;
00867 
00887     void
00888     getLocalRowView (LocalOrdinal LocalRow,
00889                      ArrayView<const LocalOrdinal>& indices) const;
00890 
00892 
00893 
00894 
00896     std::string description() const;
00897 
00899     void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const;
00900 
00902 
00903 
00904 
00905     virtual bool
00906     checkSizes (const SrcDistObject& source);
00907 
00908     virtual void
00909     copyAndPermute (const SrcDistObject& source,
00910                     size_t numSameIDs,
00911                     const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs,
00912                     const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs);
00913 
00914     virtual void
00915     packAndPrepare (const SrcDistObject& source,
00916                     const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs,
00917                     Teuchos::Array<GlobalOrdinal> &exports,
00918                     const Teuchos::ArrayView<size_t> & numPacketsPerLID,
00919                     size_t& constantNumPackets,
00920                     Distributor &distor);
00921 
00922     virtual void
00923     pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
00924           Teuchos::Array<GlobalOrdinal>& exports,
00925           const Teuchos::ArrayView<size_t>& numPacketsPerLID,
00926           size_t& constantNumPackets,
00927           Distributor& distor) const;
00928 
00929     virtual void
00930     unpackAndCombine (const Teuchos::ArrayView<const LocalOrdinal> &importLIDs,
00931                       const Teuchos::ArrayView<const GlobalOrdinal> &imports,
00932                       const Teuchos::ArrayView<size_t> &numPacketsPerLID,
00933                       size_t constantNumPackets,
00934                       Distributor &distor,
00935                       CombineMode CM);
00937 
00938 
00939 
00962     void
00963     getNumEntriesPerLocalRowUpperBound (Teuchos::ArrayRCP<const size_t>& boundPerLocalRow,
00964                                         size_t& boundForAllLocalRows,
00965                                         bool& boundSameForAllLocalRows) const;
00966 
00975     void
00976     setAllIndices (const ArrayRCP<size_t> & rowPointers,
00977                    const ArrayRCP<LocalOrdinal> & columnIndices);
00978 
00980 
00983     ArrayRCP<const size_t> getNodeRowPtrs() const;
00984 
00986 
00988     ArrayRCP<const LocalOrdinal> getNodePackedIndices() const;
00989 
00994     void replaceColMap (const Teuchos::RCP<const map_type>& newColMap);
00995 
01008     void
01009     replaceDomainMapAndImporter (const Teuchos::RCP<const map_type>& newDomainMap,
01010                                  const Teuchos::RCP<const import_type>& newImporter);
01011 
01039     virtual void
01040     removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
01042 
01043   protected:
01044     typedef typename LocalMatOps::template graph<LocalOrdinal,Node>::graph_type local_graph_type;
01045 
01046     // these structs are conveniences, to cut down on the number of
01047     // arguments to some of the methods below.
01048     struct SLocalGlobalViews {
01049       ArrayView<const GlobalOrdinal> ginds;
01050       ArrayView<const LocalOrdinal>  linds;
01051     };
01052     struct SLocalGlobalNCViews {
01053       ArrayView<GlobalOrdinal>       ginds;
01054       ArrayView<LocalOrdinal>        linds;
01055     };
01056     //
01057     // Allocation
01058     //
01059     bool indicesAreAllocated() const;
01060 
01061     void allocateIndices (ELocalGlobal lg);
01062 
01063     template <class T>
01064     ArrayRCP<T> allocateValues1D () const;
01065     template <class T>
01066     ArrayRCP<Array<T> > allocateValues2D () const;
01067 
01068     template <ELocalGlobal lg, class T>
01069     RowInfo updateAllocAndValues (RowInfo rowinfo, size_t newAllocSize, Array<T>& rowVals)
01070     {
01071 #ifdef HAVE_TPETRA_DEBUG
01072       TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement(rowinfo.localRow) );
01073       TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowinfo.allocSize );
01074       TEUCHOS_TEST_FOR_EXCEPT( (lg == LocalIndices && ! isLocallyIndexed()) ||
01075                                (lg == GlobalIndices && ! isGloballyIndexed()) );
01076       TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
01077       TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() );
01078 #endif
01079       // ArrayRCP::resize automatically copies over values on reallocation.
01080       if (lg == LocalIndices) {
01081         lclInds2D_[rowinfo.localRow].resize (newAllocSize);
01082       }
01083       else { // lg == GlobalIndices
01084         gblInds2D_[rowinfo.localRow].resize (newAllocSize);
01085       }
01086       rowVals.resize (newAllocSize);
01087       nodeNumAllocated_ += (newAllocSize - rowinfo.allocSize);
01088       rowinfo.allocSize = newAllocSize;
01089       return rowinfo;
01090     }
01091 
01093 
01094 
01096     void makeColMap ();
01097     void makeIndicesLocal ();
01098     void makeImportExport ();
01099 
01101 
01102 
01103 
01104     template<ELocalGlobal lg>
01105     size_t filterIndices (const SLocalGlobalNCViews &inds) const;
01106 
01107     template<class T>
01108     size_t
01109     filterGlobalIndicesAndValues (const ArrayView<GlobalOrdinal>& ginds,
01110                                   const ArrayView<T>& vals) const
01111     {
01112       const Map<LocalOrdinal,GlobalOrdinal,Node>& cmap = *colMap_;
01113       size_t numFiltered = 0;
01114       typename ArrayView<T>::iterator fvalsend = vals.begin();
01115       typename ArrayView<T>::iterator valscptr = vals.begin();
01116 #ifdef HAVE_TPETRA_DEBUG
01117       size_t numFiltered_debug = 0;
01118 #endif
01119       typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
01120       typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
01121       while (cptr != ginds.end()) {
01122         if (cmap.isNodeGlobalElement (*cptr)) {
01123           *fend++ = *cptr;
01124           *fvalsend++ = *valscptr;
01125 #ifdef HAVE_TPETRA_DEBUG
01126           ++numFiltered_debug;
01127 #endif
01128         }
01129         ++cptr;
01130         ++valscptr;
01131       }
01132       numFiltered = fend - ginds.begin();
01133 #ifdef HAVE_TPETRA_DEBUG
01134       TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
01135       TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
01136       const size_t numFilteredActual =
01137         Teuchos::as<size_t> (fvalsend - vals.begin ());
01138       TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
01139 #endif
01140       return numFiltered;
01141     }
01142 
01143     template<class T>
01144     size_t
01145     filterLocalIndicesAndValues (const ArrayView<LocalOrdinal>& linds,
01146                                  const ArrayView<T>& vals) const
01147     {
01148       const Map<LocalOrdinal,GlobalOrdinal,Node>& cmap = *colMap_;
01149       size_t numFiltered = 0;
01150       typename ArrayView<T>::iterator fvalsend = vals.begin();
01151       typename ArrayView<T>::iterator valscptr = vals.begin();
01152 #ifdef HAVE_TPETRA_DEBUG
01153       size_t numFiltered_debug = 0;
01154 #endif
01155       typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
01156       typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
01157       while (cptr != linds.end()) {
01158         if (cmap.isNodeLocalElement (*cptr)) {
01159           *fend++ = *cptr;
01160           *fvalsend++ = *valscptr;
01161 #ifdef HAVE_TPETRA_DEBUG
01162           ++numFiltered_debug;
01163 #endif
01164         }
01165         ++cptr;
01166         ++valscptr;
01167       }
01168       numFiltered = fend - linds.begin();
01169 #ifdef HAVE_TPETRA_DEBUG
01170       TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
01171       TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
01172       const size_t numFilteredActual =
01173         Teuchos::as<size_t> (fvalsend - vals.begin ());
01174       TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
01175 #endif
01176       return numFiltered;
01177     }
01178 
01208     size_t
01209     insertIndices (const RowInfo& rowInfo,
01210                    const SLocalGlobalViews& newInds,
01211                    const ELocalGlobal lg,
01212                    const ELocalGlobal I);
01213 
01253     template<class Scalar>
01254     void
01255     insertIndicesAndValues (const RowInfo& rowInfo,
01256                             const SLocalGlobalViews& newInds,
01257                             const ArrayView<Scalar>& oldRowVals,
01258                             const ArrayView<const Scalar>& newRowVals,
01259                             const ELocalGlobal lg,
01260                             const ELocalGlobal I)
01261     {
01262       const size_t numNewInds = insertIndices (rowInfo, newInds, lg, I);
01263       typename ArrayView<const Scalar>::const_iterator newRowValsBegin =
01264         newRowVals.begin ();
01265       std::copy (newRowValsBegin, newRowValsBegin + numNewInds,
01266                  oldRowVals.begin () + rowInfo.numEntries);
01267     }
01268 
01269     void
01270     insertGlobalIndicesImpl (const LocalOrdinal myRow,
01271                              const ArrayView<const GlobalOrdinal> &indices);
01272     void
01273     insertLocalIndicesImpl (const LocalOrdinal myRow,
01274                             const ArrayView<const LocalOrdinal> &indices);
01276     void
01277     insertLocalIndicesFiltered (const LocalOrdinal localRow,
01278                                 const ArrayView<const LocalOrdinal> &indices);
01279 
01281     void
01282     insertGlobalIndicesFiltered (const GlobalOrdinal localRow,
01283                                  const ArrayView<const GlobalOrdinal> &indices);
01284 
01312     template<class Scalar, class BinaryFunction>
01313     LocalOrdinal
01314     transformLocalValues (RowInfo rowInfo,
01315                           const Teuchos::ArrayView<Scalar>& rowVals,
01316                           const Teuchos::ArrayView<const LocalOrdinal>& inds,
01317                           const Teuchos::ArrayView<const Scalar>& newVals,
01318                           BinaryFunction f) const
01319     {
01320       typedef typename Teuchos::ArrayView<Scalar>::size_type size_type;
01321       const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
01322       const size_type numElts = inds.size ();
01323       size_t hint = 0; // Guess for the current index k into rowVals
01324 
01325       // Get a view of the column indices in the row.  This amortizes
01326       // the cost of getting the view over all the entries of inds.
01327       Teuchos::ArrayView<const LocalOrdinal> colInds = getLocalView (rowInfo);
01328 
01329       LocalOrdinal numValid = 0; // number of valid local column indices
01330       for (size_type j = 0; j < numElts; ++j) {
01331         const size_t k = findLocalIndex (rowInfo, inds[j], colInds, hint);
01332         if (k != STINV) {
01333           rowVals[k] = f (rowVals[k], newVals[j]); // use binary function f
01334           hint = k+1;
01335           ++numValid;
01336         }
01337       }
01338       return numValid;
01339     }
01340 
01360     template<class Scalar, class BinaryFunction>
01361     LocalOrdinal
01362     transformGlobalValues (RowInfo rowInfo,
01363                            const Teuchos::ArrayView<Scalar>& rowVals,
01364                            const Teuchos::ArrayView<const GlobalOrdinal>& inds,
01365                            const Teuchos::ArrayView<const Scalar>& newVals,
01366                            BinaryFunction f) const
01367     {
01368       typedef typename Teuchos::ArrayView<Scalar>::size_type size_type;
01369       const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
01370       const size_type numElts = inds.size ();
01371       size_t hint = 0; // guess at the index's relative offset in the row
01372 
01373       LocalOrdinal numValid = 0; // number of valid local column indices
01374       for (size_type j = 0; j < numElts; ++j) {
01375         const size_t k = findGlobalIndex (rowInfo, inds[j], hint);
01376         if (k != STINV) {
01377           rowVals[k] = f (rowVals[k], newVals[j]); // use binary function f
01378           hint = k+1;
01379           numValid++;
01380         }
01381       }
01382       return numValid;
01383     }
01384 
01386 
01387 
01388 
01390     bool isMerged () const;
01391 
01397     void setLocallyModified ();
01398 
01400     void sortAllIndices ();
01401 
01403     void sortRowIndices (RowInfo rowinfo);
01404 
01419     template <class Scalar>
01420     void sortRowIndicesAndValues (RowInfo rowinfo, ArrayView<Scalar> values);
01421 
01430     void mergeAllIndices ();
01431 
01436     void mergeRowIndices (RowInfo rowinfo);
01437 
01438 
01449     template<class Scalar>
01450     void
01451     mergeRowIndicesAndValues (RowInfo rowinfo,
01452                               const Teuchos::ArrayView<Scalar>& rowValues);
01454 
01464     void
01465     setDomainRangeMaps (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &domainMap,
01466                         const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rangeMap);
01467 
01468     void staticAssertions() const;
01469     // global consts
01470     void clearGlobalConstants();
01471     void computeGlobalConstants();
01472 
01474 
01475 
01479     RowInfo getRowInfo (size_t myRow) const;
01480 
01487     ArrayView<const LocalOrdinal> getLocalView (RowInfo rowinfo) const;
01488 
01495     ArrayView<LocalOrdinal> getLocalViewNonConst (RowInfo rowinfo);
01496 
01503     ArrayView<const GlobalOrdinal> getGlobalView (RowInfo rowinfo) const;
01504 
01511     ArrayView<GlobalOrdinal> getGlobalViewNonConst (RowInfo rowinfo);
01512 
01547     size_t
01548     findLocalIndex (RowInfo rowinfo,
01549                     LocalOrdinal ind,
01550                     size_t hint = 0) const;
01551 
01580     size_t
01581     findLocalIndex (RowInfo rowinfo,
01582                     LocalOrdinal ind,
01583                     ArrayView<const LocalOrdinal> colInds,
01584                     size_t hint = 0) const;
01585 
01593     size_t findGlobalIndex (RowInfo rowinfo, GlobalOrdinal ind, size_t hint = 0) const;
01594 
01596 
01597 
01598 
01599     void fillLocalGraph(const RCP<ParameterList> &params);
01600     const RCP<const local_graph_type> getLocalGraph() const;
01601     const RCP<local_graph_type> getLocalGraphNonConst();
01602 
01604 
01613     void checkInternalState() const;
01614 
01616     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > rowMap_;
01618     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > colMap_;
01620     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > rangeMap_;
01622     RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > domainMap_;
01623 
01630     RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > importer_;
01631 
01637     RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > exporter_;
01638 
01639     // local data, stored in a KokkosClassic::CrsGraph. only initialized after fillComplete()
01640     RCP<local_graph_type> lclGraph_;
01641 
01642     // Local and Global Counts
01643     // nodeNumEntries_ and nodeNumAllocated_ are required to be always consistent
01644     // nodeMaxNumEntries_, nodeNumDiags_ and the global quantities are computed during fillComplete() and only valid when isFillComplete()
01645     global_size_t globalNumEntries_, globalNumDiags_, globalMaxNumRowEntries_;
01646     size_t          nodeNumEntries_,   nodeNumDiags_,   nodeMaxNumRowEntries_, nodeNumAllocated_;
01647 
01649     ProfileType pftype_;
01650 
01660     ArrayRCP<const size_t> numAllocPerRow_;
01661 
01666     size_t numAllocForAllRows_;
01667 
01668     // graph indices. before allocation, all are null.
01669     // after allocation, except during makeIndicesLocal(), one of local or global is null.
01670     // we will never have 1D and 2D structures being non-null
01671     // this is host memory
01672     // 1D == StaticAllocation, 2D == DynamicAllocation
01674     //
01675     // 1D/Static structures
01676     //
01678 
01680     ArrayRCP< LocalOrdinal>                     lclInds1D_;
01682     ArrayRCP<GlobalOrdinal>                     gblInds1D_;
01683     // offset to the beg entries of each row. only used for 1D (Static) allocation.
01684     // i.e., indices for row R are lclInds1D_[i] for i in [b,e) where b = rowPtrs_[R] and e = rowPtrs_[R+1]
01685     // only the first numRowEntries_[R] of these are valid
01686     // both of these are null for 2D (Dynamic) allocations
01687     // rowPtrs_ has length N+1, while numRowEntries_ has length N
01688     // we may delete this to save memory on fillComplete, if "Delete Row Pointers" is specified
01689     ArrayRCP<size_t> rowPtrs_;
01690 
01692     //
01693     // 2D/Dynamic structures.
01694     //
01696 
01698     ArrayRCP<Array< LocalOrdinal> > lclInds2D_;
01699 
01701     ArrayRCP<Array<GlobalOrdinal> > gblInds2D_;
01702 
01707     ArrayRCP<size_t> numRowEntries_;
01708 
01709     bool indicesAreAllocated_;
01710     bool indicesAreLocal_;
01711     bool indicesAreGlobal_;
01712     bool fillComplete_;
01714     bool lowerTriangular_;
01716     bool upperTriangular_;
01718     bool indicesAreSorted_;
01721     bool noRedundancies_;
01723     bool haveLocalConstants_;
01725     bool haveGlobalConstants_;
01726 
01734     std::map<GlobalOrdinal, std::vector<GlobalOrdinal> > nonlocals_;
01735 
01748     bool haveRowInfo_;
01749 
01750     bool hasRowInfo() const;
01751 
01766     bool sortGhostsAssociatedWithEachProcessor_;
01767 
01768   }; // class CrsGraph
01769 
01776   template <class LocalOrdinal, class GlobalOrdinal, class Node>
01777   Teuchos::RCP<CrsGraph<LocalOrdinal,GlobalOrdinal,Node> >
01778   createCrsGraph (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &map,
01779                    size_t maxNumEntriesPerRow = 0,
01780                    const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
01781   {
01782     using Teuchos::rcp;
01783     typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node> graph_type;
01784     return rcp (new graph_type (map, maxNumEntriesPerRow, DynamicProfile, params));
01785   }
01786 
01787 
01788 
01789 namespace Details {
01790 
01791 template<class LocalOrdinal, class GlobalOrdinal, class OutputNodeType, class InputNodeType>
01792 class CrsGraphCopier<CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType>,
01793                      CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> > {
01794 public:
01795   typedef CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> input_crs_graph_type;
01796   typedef CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType> output_crs_graph_type;
01797 
01798   static Teuchos::RCP<output_crs_graph_type>
01799   clone (const input_crs_graph_type& graphIn,
01800          const Teuchos::RCP<OutputNodeType> &nodeOut,
01801          const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
01802   {
01803     using Teuchos::arcp;
01804     using Teuchos::ArrayRCP;
01805     using Teuchos::ArrayView;
01806     using Teuchos::null;
01807     using Teuchos::outArg;
01808     using Teuchos::ParameterList;
01809     using Teuchos::RCP;
01810     using Teuchos::rcp;
01811     using Teuchos::REDUCE_MIN;
01812     using Teuchos::reduceAll;
01813     using Teuchos::sublist;
01814     using std::cerr;
01815     using std::endl;
01816     typedef LocalOrdinal LO;
01817     typedef GlobalOrdinal GO;
01818     typedef typename ArrayView<const GO>::size_type size_type;
01819     typedef ::Tpetra::Map<LO, GO, InputNodeType> input_map_type;
01820     typedef ::Tpetra::Map<LO, GO, OutputNodeType> output_map_type;
01821     const char prefix[] = "Tpetra::Details::CrsGraphCopier::clone: ";
01822     const bool debug = false;
01823 
01824     bool fillCompleteClone  = true;
01825     bool useLocalIndices    = graphIn.hasColMap ();
01826     ProfileType pftype = StaticProfile;
01827     if (! params.is_null ()) {
01828       fillCompleteClone = params->get ("fillComplete clone", fillCompleteClone);
01829       useLocalIndices = params->get ("Locally indexed clone", useLocalIndices);
01830       if (params->get ("Static profile clone", true) == false) {
01831         pftype = DynamicProfile;
01832       }
01833     }
01834 
01835     const Teuchos::Comm<int>& comm = * (graphIn.getRowMap ()->getComm ());
01836     const int myRank = comm.getRank ();
01837 
01838     TEUCHOS_TEST_FOR_EXCEPTION(
01839       ! graphIn.hasColMap () && useLocalIndices, std::runtime_error,
01840       prefix << "You asked clone() to use local indices (by setting the "
01841       "\"Locally indexed clone\" parameter to true), but the source graph "
01842       "does not yet have a column Map, so this is impossible.");
01843 
01844     if (debug) {
01845       std::ostringstream os;
01846       os << "Process " << myRank << ": Cloning row Map" << endl;
01847       cerr << os.str ();
01848     }
01849 
01850     RCP<const output_map_type> clonedRowMap =
01851       graphIn.getRowMap ()->template clone<OutputNodeType> (nodeOut);
01852 
01853     // Invoke the output graph's constructor, using the input graph's
01854     // upper bounds on the number of entries in each local row.
01855     RCP<output_crs_graph_type> clonedGraph; // returned by this function
01856     {
01857       ArrayRCP<const size_t> numEntriesPerRow;
01858       size_t numEntriesForAll = 0;
01859       bool boundSameForAllLocalRows = true;
01860 
01861       if (debug) {
01862         std::ostringstream os;
01863         os << "Process " << myRank << ": Getting per-row bounds" << endl;
01864         cerr << os.str ();
01865       }
01866       graphIn.getNumEntriesPerLocalRowUpperBound (numEntriesPerRow,
01867                                                   numEntriesForAll,
01868                                                   boundSameForAllLocalRows);
01869       if (debug) {
01870         std::ostringstream os;
01871         os << "Process " << myRank << ": numEntriesForAll = "
01872            << numEntriesForAll << endl;
01873         cerr << os.str ();
01874       }
01875 
01876       if (debug) {
01877         std::ostringstream os;
01878         os << "Process " << myRank << ": graphIn.getNodeMaxNumRowEntries() = "
01879            << graphIn.getNodeMaxNumRowEntries () << endl;
01880         cerr << os.str ();
01881       }
01882 
01883       RCP<ParameterList> graphparams = sublist (params, "CrsGraph");
01884       if (useLocalIndices) {
01885         RCP<const output_map_type> clonedColMap =
01886           graphIn.getColMap ()->template clone<OutputNodeType> (nodeOut);
01887         if (boundSameForAllLocalRows) {
01888           clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
01889                                                         numEntriesForAll, pftype,
01890                                                         graphparams));
01891         } else {
01892           clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
01893                                                         numEntriesPerRow, pftype,
01894                                                         graphparams));
01895         }
01896       } else {
01897         if (boundSameForAllLocalRows) {
01898           clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
01899                                                         numEntriesForAll, pftype,
01900                                                         graphparams));
01901         } else {
01902           clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
01903                                                         numEntriesPerRow,
01904                                                         pftype, graphparams));
01905         }
01906       }
01907 
01908       if (debug) {
01909         std::ostringstream os;
01910         os << "Process " << myRank << ": Invoked output graph's constructor" << endl;
01911         cerr << os.str ();
01912       }
01913 
01914       // done with these
01915       numEntriesPerRow = null;
01916       numEntriesForAll = 0;
01917     }
01918 
01919     const input_map_type& inputRowMap = * (graphIn.getRowMap ());
01920     const size_type numRows =
01921       static_cast<size_type> (inputRowMap.getNodeNumElements ());
01922 
01923     bool failed = false;
01924 
01925     if (useLocalIndices) {
01926       const GO localMinLID = inputRowMap.getMinLocalIndex ();
01927       const GO localMaxLID = inputRowMap.getMaxLocalIndex ();
01928 
01929       if (graphIn.isLocallyIndexed ()) {
01930         if (numRows != 0) {
01931           try {
01932             ArrayView<const LO> linds;
01933             for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
01934               graphIn.getLocalRowView (lrow, linds);
01935               if (linds.size () != 0) {
01936                 clonedGraph->insertLocalIndices (lrow, linds);
01937               }
01938             }
01939           }
01940           catch (std::exception& e) {
01941             std::ostringstream os;
01942             os << "Process " << myRank << ": copying (reading local by view, "
01943               "writing local) indices into the output graph threw an "
01944               "exception: " << e.what () << endl;
01945             cerr << os.str ();
01946             failed = true;
01947           }
01948         }
01949       }
01950       else { // graphIn.isGloballyIndexed()
01951         TEUCHOS_TEST_FOR_EXCEPTION(
01952           ! graphIn.hasColMap () && useLocalIndices, std::invalid_argument,
01953           prefix << "You asked clone() to use local indices (by setting the "
01954           "\"Locally indexed clone\" parameter to true), but the source graph "
01955           "does not yet have a column Map, so this is impossible.");
01956 
01957         // The input graph has a column Map, but is globally indexed.
01958         // That's a bit weird, but we'll run with it.  In this case,
01959         // getLocalRowView won't work, but getLocalRowCopy should
01960         // still work; it will just have to convert from global to
01961         // local indices internally.
01962 
01963         try {
01964           // Make space for getLocalRowCopy to put column indices.
01965           //
01966           // This is only a hint; we may have to resize in the loop
01967           // below.  getNodeMaxNumRowEntries() may return nonsense if
01968           // fill is active.  The key bool in CrsGraph is
01969           // haveLocalConstants_.
01970           size_t myMaxNumRowEntries =
01971             graphIn.isFillActive () ? static_cast<size_t> (0) :
01972             graphIn.getNodeMaxNumRowEntries ();
01973 
01974           Array<LO> linds (myMaxNumRowEntries);
01975 
01976           // Copy each row into the new graph, using local indices.
01977           for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
01978             size_t theNumEntries = graphIn.getNumEntriesInLocalRow (lrow);
01979             if (theNumEntries > myMaxNumRowEntries) {
01980               myMaxNumRowEntries = theNumEntries;
01981               linds.resize (myMaxNumRowEntries);
01982             }
01983             graphIn.getLocalRowCopy (lrow, linds (), theNumEntries);
01984             if (theNumEntries != 0) {
01985               clonedGraph->insertLocalIndices (lrow, linds (0, theNumEntries));
01986             }
01987           }
01988         }
01989         catch (std::exception& e) {
01990           std::ostringstream os;
01991           os << "Process " << myRank << ": copying (reading local by copy, "
01992             "writing local) indices into the output graph threw an exception: "
01993              << e.what () << endl;
01994           cerr << os.str ();
01995           failed = true;
01996         }
01997       }
01998     }
01999     else { /* useGlobalIndices */
02000       if (numRows != 0) {
02001         const GlobalOrdinal localMinGID = inputRowMap.getMinGlobalIndex ();
02002         const GlobalOrdinal localMaxGID = inputRowMap.getMaxGlobalIndex ();
02003         const bool inputRowMapIsContiguous = inputRowMap.isContiguous ();
02004 
02005         if (graphIn.isGloballyIndexed ()) {
02006           ArrayView<const GlobalOrdinal> ginds;
02007 
02008           if (inputRowMapIsContiguous) {
02009             try {
02010               for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
02011                 graphIn.getGlobalRowView (grow, ginds);
02012                 if (ginds.size () != 0) {
02013                   clonedGraph->insertGlobalIndices (grow, ginds);
02014                 }
02015               }
02016             }
02017             catch (std::exception& e) {
02018               std::ostringstream os;
02019               os << "Process " << myRank << ": copying (reading global by view, "
02020                 "writing global) indices into the output graph threw an "
02021                 "exception: " << e.what () << endl;
02022               cerr << os.str ();
02023               failed = true;
02024             }
02025           }
02026           else { // input row Map is not contiguous
02027             try {
02028               ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
02029               for (size_type k = 0; k < numRows; ++k) {
02030                 const GO grow = inputRowMapGIDs[k];
02031                 graphIn.getGlobalRowView (grow, ginds);
02032                 if (ginds.size () != 0) {
02033                   clonedGraph->insertGlobalIndices (grow, ginds);
02034                 }
02035               }
02036             }
02037             catch (std::exception& e) {
02038               std::ostringstream os;
02039               os << "Process " << myRank << ": copying (reading global by view, "
02040                 "writing global) indices into the output graph threw an "
02041                 "exception: " << e.what () << endl;
02042               cerr << os.str ();
02043               failed = true;
02044             }
02045           }
02046         }
02047         else { // graphIn.isLocallyIndexed()
02048           // Make space for getGlobalRowCopy to put column indices.
02049           //
02050           // This is only a hint; we may have to resize in the loop
02051           // below.  getNodeMaxNumRowEntries() may return nonsense if
02052           // fill is active.  The key bool in CrsGraph is
02053           // haveLocalConstants_.
02054           size_t myMaxNumRowEntries =
02055             graphIn.isFillActive () ? static_cast<size_t> (0) :
02056             graphIn.getNodeMaxNumRowEntries ();
02057 
02058           Array<GO> ginds (myMaxNumRowEntries);
02059 
02060           if (inputRowMapIsContiguous) {
02061             try {
02062               for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
02063                 size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
02064                 if (theNumEntries > myMaxNumRowEntries) {
02065                   myMaxNumRowEntries = theNumEntries;
02066                   ginds.resize (myMaxNumRowEntries);
02067                 }
02068                 graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
02069                 if (theNumEntries != 0) {
02070                   clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
02071                 }
02072               }
02073             }
02074             catch (std::exception& e) {
02075               std::ostringstream os;
02076               os << "Process " << myRank << ": copying (reading global by copy, "
02077                 "writing global) indices into the output graph threw an "
02078                 "exception: " << e.what () << endl;
02079               cerr << os.str ();
02080               failed = true;
02081             }
02082           }
02083           else { // input row Map is not contiguous
02084             try {
02085               ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
02086               for (size_type k = 0; k < numRows; ++k) {
02087                 const GO grow = inputRowMapGIDs[k];
02088 
02089                 size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
02090                 if (theNumEntries > myMaxNumRowEntries) {
02091                   myMaxNumRowEntries = theNumEntries;
02092                   ginds.resize (myMaxNumRowEntries);
02093                 }
02094                 graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
02095                 if (theNumEntries != 0) {
02096                   clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
02097                 }
02098               }
02099             }
02100             catch (std::exception& e) {
02101               std::ostringstream os;
02102               os << "Process " << myRank << ": copying (reading global by copy, "
02103                 "writing global) indices into the output graph threw an "
02104                 "exception: " << e.what () << endl;
02105               cerr << os.str ();
02106               failed = true;
02107             }
02108           }
02109         }
02110       } // numRows != 0
02111     }
02112 
02113     if (debug) {
02114       std::ostringstream os;
02115       os << "Process " << myRank << ": copied entries" << endl;
02116       cerr << os.str ();
02117     }
02118 
02119     if (fillCompleteClone) {
02120       RCP<ParameterList> fillparams = sublist (params, "fillComplete");
02121       try {
02122         RCP<const output_map_type> clonedRangeMap;
02123         RCP<const output_map_type> clonedDomainMap;
02124         if (! graphIn.getRangeMap ().is_null () &&
02125             graphIn.getRangeMap () != graphIn.getRowMap ()) {
02126           clonedRangeMap =
02127             graphIn.getRangeMap ()->template clone<OutputNodeType> (nodeOut);
02128         }
02129         else {
02130           clonedRangeMap = clonedRowMap;
02131         }
02132         if (! graphIn.getDomainMap ().is_null ()
02133             && graphIn.getDomainMap () != graphIn.getRowMap ()) {
02134           clonedDomainMap =
02135             graphIn.getDomainMap ()->template clone<OutputNodeType> (nodeOut);
02136         }
02137         else {
02138           clonedDomainMap = clonedRowMap;
02139         }
02140         clonedGraph->fillComplete (clonedDomainMap, clonedRangeMap, fillparams);
02141       }
02142       catch (std::exception &e) {
02143         failed = true;
02144         std::ostringstream os;
02145         os << prefix << "Process " << myRank << ": Caught the following "
02146           "exception while calling fillComplete() on clone of type"
02147            << endl << Teuchos::typeName (*clonedGraph) << endl;
02148       }
02149     }
02150 
02151     int lclSuccess = failed ? 0 : 1;
02152     int gblSuccess = 1;
02153     reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
02154     TEUCHOS_TEST_FOR_EXCEPTION(
02155       gblSuccess != 1, std::logic_error, prefix <<
02156       "Clone failed on at least one process.");
02157 
02158     return clonedGraph;
02159   }
02160 };
02161 
02162 } // namespace Details
02163 } // namespace Tpetra
02164 
02165 // Include KokkosRefactor partial specialisation if enabled
02166 #if defined(TPETRA_HAVE_KOKKOS_REFACTOR)
02167 #include "Tpetra_KokkosRefactor_CrsGraph_decl.hpp"
02168 #endif
02169 
02170 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines