All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Xpetra_Operator.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //             Xpetra: A linear algebra interface package
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
00039 //                    Jeremie Gaidamour (jngaida@sandia.gov)
00040 //                    Jonathan Hu       (jhu@sandia.gov)
00041 //                    Ray Tuminaro      (rstumin@sandia.gov)
00042 //
00043 // ***********************************************************************
00044 //
00045 // @HEADER
00046 
00047 // WARNING: This code is experimental. Backwards compatibility should not be expected.
00048 
00049 #ifndef XPETRA_OPERATOR_HPP
00050 #define XPETRA_OPERATOR_HPP
00051 
00052 #include <Kokkos_DefaultNode.hpp>
00053 #include <Kokkos_DefaultKernels.hpp>
00054 
00055 #include "Xpetra_ConfigDefs.hpp"
00056 #include "Xpetra_Exceptions.hpp"
00057 
00058 #include "Xpetra_MultiVector.hpp"
00059 #include "Xpetra_CrsGraph.hpp"
00060 #include "Xpetra_CrsMatrix.hpp"
00061 #include "Xpetra_CrsMatrixFactory.hpp"
00062 #include "Xpetra_OperatorView.hpp"
00063 #include "Xpetra_StridedMap.hpp"
00064 #include "Xpetra_StridedMapFactory.hpp"
00065 
00066 #include <Teuchos_SerialDenseMatrix.hpp>
00067 #include <Teuchos_Hashtable.hpp>
00068 
00073 namespace Xpetra {
00074 
00075   typedef std::string viewLabel_t;
00076 
00077   template <class Scalar, 
00078             class LocalOrdinal  = int, 
00079             class GlobalOrdinal = LocalOrdinal, 
00080             class Node          = Kokkos::DefaultNode::DefaultNodeType, 
00081             class LocalMatOps   = typename Kokkos::DefaultKernels<Scalar,LocalOrdinal,Node>::SparseOps > //TODO: or BlockSparseOp ?
00082   class Operator : virtual public Teuchos::Describable {
00083     
00084     typedef Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> Map;
00085     typedef Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrix;
00086     typedef Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsGraph;
00087 #ifdef HAVE_XPETRA_TPETRA
00088     typedef Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> TpetraCrsMatrix;
00089 #endif
00090     typedef Xpetra::CrsMatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrixFactory;
00091     typedef Xpetra::OperatorView<LocalOrdinal, GlobalOrdinal, Node> OperatorView;
00092 
00093   public:
00094   
00096 
00097 
00098     Operator() { }
00099 
00101     virtual ~Operator() { }
00102 
00104 
00106 
00107     void CreateView(viewLabel_t viewLabel, const RCP<const Map> & rowMap, const RCP<const Map> & colMap) {
00108       TEUCHOS_TEST_FOR_EXCEPTION(operatorViewTable_.containsKey(viewLabel) == true, Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.CreateView(): a view labeled '" + viewLabel + "' already exist.");
00109       RCP<OperatorView> view = rcp(new OperatorView(rowMap, colMap));
00110       operatorViewTable_.put(viewLabel, view);
00111     }
00112     
00113     void CreateView(const viewLabel_t viewLabel, const RCP<Operator> & A, bool transposeA = false, const RCP<Operator> & B = Teuchos::null, bool transposeB = false) {
00114             
00115       RCP<const Map> domainMap = Teuchos::null;
00116       RCP<const Map> rangeMap  = Teuchos::null;
00117 
00118       // A has strided Maps
00119       if(A->IsView(viewLabel)) {
00120         Xpetra::viewLabel_t oldView = A->SwitchToView(viewLabel); // note: "stridedMaps are always non-overlapping (correspond to range and domain maps!)
00121         rangeMap = (transposeA) ? A->getColMap() : A->getRowMap();
00122         domainMap = (transposeA) ? A->getRowMap() : A->getColMap(); // overwrite if B != Teuchos::null
00123         oldView = A->SwitchToView(oldView);
00124       } else rangeMap = (transposeA) ? A->getDomainMap() : A->getRangeMap();
00125       
00126       // B has strided Maps
00127       if(B != Teuchos::null ) {
00128         if(B->IsView(viewLabel)) {
00129           Xpetra::viewLabel_t oldView = B->SwitchToView(viewLabel); // note: "stridedMaps are always non-overlapping (correspond to range and domain maps!)
00130           domainMap = (transposeB) ? B->getRowMap() : B->getColMap();
00131           oldView = B->SwitchToView(oldView);
00132         } else domainMap = (transposeB) ? B->getRangeMap() : B->getDomainMap();
00133       }
00134       
00135       
00136       if(IsView(viewLabel)) RemoveView(viewLabel);
00137       
00138       CreateView(viewLabel, rangeMap, domainMap);   
00139     }
00140 
00142     void PrintViews(Teuchos::FancyOStream &out) const {
00143       int last = out.getOutputToRootOnly();
00144       Teuchos::OSTab tab(out);
00145       out.setOutputToRootOnly(0);
00146       Teuchos::Array<viewLabel_t> viewLabels;
00147       Teuchos::Array<RCP<OperatorView> > viewList;
00148       operatorViewTable_.arrayify(viewLabels,viewList);
00149       out << "views associated with this operator" << std::endl;
00150       for (int i=0; i<viewLabels.size(); ++i)
00151         out << viewLabels[i] << std::endl;
00152       out.setOutputToRootOnly(last);
00153     }
00154 
00155     
00156     void RemoveView(const viewLabel_t viewLabel) {
00157       TEUCHOS_TEST_FOR_EXCEPTION(operatorViewTable_.containsKey(viewLabel) == false, Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.RemoveView(): view '" + viewLabel + "' does not exist.");
00158       TEUCHOS_TEST_FOR_EXCEPTION(viewLabel == GetDefaultViewLabel(), Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.RemoveView(): view '" + viewLabel + "' is the default view and cannot be removed.");
00159       operatorViewTable_.remove(viewLabel);
00160     }
00161     
00162     const viewLabel_t SwitchToView(const viewLabel_t viewLabel) {
00163       TEUCHOS_TEST_FOR_EXCEPTION(operatorViewTable_.containsKey(viewLabel) == false, Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.SwitchToView(): view '" + viewLabel + "' does not exist.");
00164       viewLabel_t oldViewLabel = GetCurrentViewLabel();
00165       currentViewLabel_ = viewLabel;
00166       return oldViewLabel;
00167     }
00168 
00169     bool IsView(const viewLabel_t viewLabel) const {
00170       return operatorViewTable_.containsKey(viewLabel);
00171     }
00172 
00173     const viewLabel_t SwitchToDefaultView() { return SwitchToView(GetDefaultViewLabel()); }
00174 
00175     const viewLabel_t & GetDefaultViewLabel() const { return defaultViewLabel_; }
00176 
00177     const viewLabel_t & GetCurrentViewLabel() const { return currentViewLabel_; }
00178     
00180 
00182 
00183 
00185 
00196     virtual void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView<const GlobalOrdinal> &cols, const ArrayView<const Scalar> &vals) = 0;
00197 
00199 
00206     virtual void insertLocalValues(LocalOrdinal localRow, const ArrayView<const LocalOrdinal> &cols, const ArrayView<const Scalar> &vals) = 0;
00207 
00209 
00211 
00212 
00224     virtual void fillComplete(const RCP<const Map> &domainMap, const RCP<const Map> &rangeMap, const RCP<ParameterList> &params = null) =0;
00225 
00239     //TODO : Get ride of "Tpetra"::OptimizeOption
00240     virtual void fillComplete(const RCP<ParameterList> &params=null) =0;
00241 
00243 
00245 
00246 
00248     virtual const RCP<const Map> & getRowMap() const { return getRowMap(GetCurrentViewLabel()); }
00249 
00251     virtual const RCP<const Map> & getRowMap(viewLabel_t viewLabel) const { 
00252       TEUCHOS_TEST_FOR_EXCEPTION(operatorViewTable_.containsKey(viewLabel) == false, Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.GetRowMap(): view '" + viewLabel + "' does not exist.");
00253       return operatorViewTable_.get(viewLabel)->GetRowMap(); 
00254     }
00255 
00258     virtual const RCP<const Map> & getColMap() const { return getColMap(GetCurrentViewLabel()); }
00259 
00261     virtual const RCP<const Map> & getColMap(viewLabel_t viewLabel) const { 
00262       TEUCHOS_TEST_FOR_EXCEPTION(operatorViewTable_.containsKey(viewLabel) == false, Xpetra::Exceptions::RuntimeError, "Xpetra::Operator.GetColMap(): view '" + viewLabel + "' does not exist.");
00263       return operatorViewTable_.get(viewLabel)->GetColMap(); 
00264     }
00265 
00267 
00269     virtual global_size_t getGlobalNumRows() const =0;
00270 
00272 
00274     virtual global_size_t getGlobalNumCols() const =0;
00275 
00277     virtual size_t getNodeNumRows() const =0;
00278 
00280     virtual global_size_t getGlobalNumEntries() const =0;
00281 
00283     virtual size_t getNodeNumEntries() const =0;
00284 
00286 
00287     virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0;
00288 
00290 
00292     virtual global_size_t getGlobalNumDiags() const =0;
00293 
00295 
00297     virtual size_t getNodeNumDiags() const =0;
00298 
00300 
00302     virtual size_t getGlobalMaxNumRowEntries() const =0;
00303 
00305 
00307     virtual size_t getNodeMaxNumRowEntries() const =0;
00308 
00310     virtual bool isLocallyIndexed() const =0;
00311 
00313     virtual bool isGloballyIndexed() const =0;
00314 
00316     virtual bool isFillComplete() const =0;
00317 
00319 
00331     virtual void getLocalRowCopy(LocalOrdinal LocalRow, 
00332                                  const ArrayView<LocalOrdinal> &Indices, 
00333                                  const ArrayView<Scalar> &Values,
00334                                  size_t &NumEntries
00335                                  ) const =0;
00336 
00338 
00347     virtual void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal> &indices, ArrayView<const Scalar> &values) const =0;
00348 
00350 
00359     virtual void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal> &indices, ArrayView<const Scalar> &values) const =0;
00360 
00362 
00364     virtual void getLocalDiagCopy(Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &diag) const =0;
00365 
00367     virtual typename ScalarTraits<Scalar>::magnitudeType getFrobeniusNorm() const = 0;
00368 
00370 
00372 
00373 
00375 
00384     //TODO virtual=0 // TODO: Add default parameters ?
00385 //     virtual void multiply(const MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> & X, MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &Y, Teuchos::ETransp trans, Scalar alpha, Scalar beta) const=0;
00386 
00388 
00390 
00391 
00393 
00396     virtual void apply(const MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> & X, MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &Y, 
00397                        Teuchos::ETransp mode = Teuchos::NO_TRANS,
00398                        Scalar alpha = ScalarTraits<Scalar>::one(),
00399                        Scalar beta = ScalarTraits<Scalar>::zero()) const =0;
00400 
00403     virtual const RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > getDomainMap() const =0;
00404 
00407     virtual const RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > getRangeMap() const =0;
00408 
00410 
00412 
00413 
00414     // TODO: describe of views can be done here
00415 
00416     //   /** \brief Return a simple one-line description of this object. */
00417     //   virtual std::string description() const =0;
00418 
00419     //   /** \brief Print the object with some verbosity level to an FancyOStream object. */
00420     //   virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const =0;
00421 
00423 
00424 
00426 
00427 
00429     virtual std::string description() const =0;
00430 
00432     virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const =0;
00434 
00435     // JG: Added:
00436 
00438     virtual RCP<const CrsGraph> getCrsGraph() const =0;
00439 
00440     // ----------------------------------------------------------------------------------
00441     // "TEMPORARY" VIEW MECHANISM
00442     // TODO: the view mechanism should be implemented as in MueMat.
00443     void SetFixedBlockSize(LocalOrdinal blksize) {
00444 
00445       TEUCHOS_TEST_FOR_EXCEPTION(isFillComplete() == false, Exceptions::RuntimeError, "Xpetra::Operator::SetFixedBlockSize(): operator is not filled and completed."); // TODO: do we need this? we just wanna "copy" the domain and range map
00446 
00447       std::vector<size_t> stridingInfo;
00448       stridingInfo.push_back(Teuchos::as<size_t>(blksize));
00449       LocalOrdinal stridedBlockId = -1;
00450             
00451       RCP<const Xpetra::StridedMap<LocalOrdinal, GlobalOrdinal, Node> > stridedRangeMap = Xpetra::StridedMapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(getRangeMap()->lib(),
00452                                                     getRangeMap(),
00453                                                     stridingInfo,
00454                                                     stridedBlockId
00455                                                     );
00456       RCP<const Map> stridedDomainMap = Xpetra::StridedMapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(getDomainMap()->lib(),
00457                 getDomainMap(),
00458                 stridingInfo,
00459                 stridedBlockId
00460                 );
00461 
00462       if(IsView("stridedMaps") == true) RemoveView("stridedMaps");
00463       CreateView("stridedMaps", stridedRangeMap, stridedDomainMap); 
00464     }
00465 
00466     //==========================================================================
00467 
00468     LocalOrdinal GetFixedBlockSize() const {
00469       if(IsView("stridedMaps")==true) {
00470         Teuchos::RCP<const StridedMap<LocalOrdinal, GlobalOrdinal, Node> > rangeMap = Teuchos::rcp_dynamic_cast<const StridedMap<LocalOrdinal, GlobalOrdinal, Node> >(getRowMap("stridedMaps"));
00471         Teuchos::RCP<const StridedMap<LocalOrdinal, GlobalOrdinal, Node> > domainMap = Teuchos::rcp_dynamic_cast<const StridedMap<LocalOrdinal, GlobalOrdinal, Node> >(getColMap("stridedMaps"));
00472         TEUCHOS_TEST_FOR_EXCEPTION(rangeMap  == Teuchos::null, Exceptions::BadCast, "Xpetra::Operator::GetFixedBlockSize(): rangeMap is not of type StridedMap");
00473         TEUCHOS_TEST_FOR_EXCEPTION(domainMap == Teuchos::null, Exceptions::BadCast, "Xpetra::Operator::GetFixedBlockSize(): domainMap is not of type StridedMap");
00474         TEUCHOS_TEST_FOR_EXCEPTION(domainMap->getFixedBlockSize() != rangeMap->getFixedBlockSize(), Exceptions::RuntimeError, "Xpetra::Operator::GetFixedBlockSize(): block size of rangeMap and domainMap are different.");
00475         return Teuchos::as<LocalOrdinal>(domainMap->getFixedBlockSize()); // TODO: why LocalOrdinal?
00476       } else
00477         //TEUCHOS_TEST_FOR_EXCEPTION(false, Exceptions::RuntimeError, "Xpetra::Operator::GetFixedBlockSize(): no strided maps available."); // TODO remove this
00478         return 1;
00479     }; //TODO: why LocalOrdinal?
00480 
00481     // ----------------------------------------------------------------------------------
00482 
00483     protected:
00484       Teuchos::Hashtable<viewLabel_t, RCP<OperatorView> > operatorViewTable_; // hashtable storing the operator views (keys = view names, values = views).
00485 
00486       viewLabel_t defaultViewLabel_;  // label of the view associated with inital Operator construction
00487       viewLabel_t currentViewLabel_;  // label of the current view
00488 
00489   }; //class Operator
00490 
00491 } //namespace Xpetra
00492 
00493 #define XPETRA_OPERATOR_SHORT
00494 #endif //XPETRA_OPERATOR_DECL_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines