Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_CrsMatrixSolveOp.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #ifndef TPETRA_CRSMATRIXSOLVEOP_HPP
43 #define TPETRA_CRSMATRIXSOLVEOP_HPP
44 
49 
50 #include <Tpetra_CrsMatrix.hpp>
51 
52 namespace Tpetra {
53 
90  template <class Scalar,
91  class MatScalar = Scalar,
93  class GlobalOrdinal = ::Tpetra::Details::DefaultTypes::global_ordinal_type,
95  class CrsMatrixSolveOp TPETRA_DEPRECATED :
96  public Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
97  public:
99  typedef CrsMatrix<MatScalar, LocalOrdinal, GlobalOrdinal, Node> crs_matrix_type;
101  typedef Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
102 
104 
105 
107  CrsMatrixSolveOp (const Teuchos::RCP<const crs_matrix_type>& A) :
108  matrix_ (A)
109  {}
110 
112  virtual ~CrsMatrixSolveOp () {}
113 
115 
117 
120  void
121  apply (const MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> & X,
122  MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &Y,
123  Teuchos::ETransp mode = Teuchos::NO_TRANS,
124  Scalar alpha = Teuchos::ScalarTraits<Scalar>::one (),
125  Scalar beta = Teuchos::ScalarTraits<Scalar>::zero ()) const
126  {
127  typedef Teuchos::ScalarTraits<Scalar> STOS;
128  const char prefix[] = "Tpetra::CrsMatrixSolveOp::apply: ";
129 
130  TEUCHOS_TEST_FOR_EXCEPTION
131  (! matrix_->isFillComplete (), std::runtime_error,
132  prefix << "Underlying matrix is not fill complete.");
133  TEUCHOS_TEST_FOR_EXCEPTION
134  (! matrix_->isLowerTriangular () && ! matrix_->isUpperTriangular (),
135  std::runtime_error, prefix << "The matrix is neither lower nor upper "
136  "triangular. Remember that in Tpetra, triangular-ness is a local "
137  "(per MPI process) property.");
138  TEUCHOS_TEST_FOR_EXCEPTION
139  (X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
140  prefix << "X and Y must have the same number of columns (vectors). "
141  "X.getNumVectors() = " << X.getNumVectors ()
142  << " != Y.getNumVectors() = " << Y.getNumVectors () << ".");
143  TEUCHOS_TEST_FOR_EXCEPTION
144  (alpha != STOS::one () || beta != STOS::zero (), std::logic_error,
145  prefix << "The case alpha != 1 or beta != 0 has not yet been "
146  "implemented. Please speak with the Tpetra developers.");
147  if (mode == Teuchos::NO_TRANS) {
148  applyNonTranspose (X,Y);
149  } else if (mode == Teuchos::TRANS || mode == Teuchos::CONJ_TRANS) {
150  applyTranspose (X, Y, mode);
151  } else {
152  TEUCHOS_TEST_FOR_EXCEPTION
153  (true, std::invalid_argument, prefix << "The 'mode' argument has an "
154  "invalid value " << mode << ". Valid values are Teuchos::NO_TRANS="
155  << Teuchos::NO_TRANS << ", Teuchos::TRANS=" << Teuchos::TRANS << ", "
156  "and Teuchos::CONJ_TRANS=" << Teuchos::CONJ_TRANS << ".");
157  }
158  }
159 
161  bool hasTransposeApply () const {
162  return true;
163  }
164 
167  Teuchos::RCP<const map_type> getDomainMap () const
168  {
169  return matrix_->getRangeMap ();
170  }
171 
174  Teuchos::RCP<const map_type> getRangeMap () const {
175  return matrix_->getDomainMap ();
176  }
177 
179  protected:
180  typedef MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> MV;
181 
183  const Teuchos::RCP<const crs_matrix_type> matrix_;
184 
186  mutable Teuchos::RCP<MV> importMV_;
188  mutable Teuchos::RCP<MV> exportMV_;
189 
191  void applyNonTranspose (const MV& X_in, MV& Y_in) const
192  {
193  using Teuchos::NO_TRANS;
194  using Teuchos::null;
195  typedef Teuchos::ScalarTraits<Scalar> ST;
196 
197  // Solve U X = Y or L X = Y
198  // X belongs to domain map, while Y belongs to range map
199 
200  const size_t numVectors = X_in.getNumVectors();
201  Teuchos::RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > importer =
202  matrix_->getGraph ()->getImporter ();
203  Teuchos::RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > exporter =
204  matrix_->getGraph ()->getExporter ();
205  Teuchos::RCP<const MV> X;
206 
207  // it is okay if X and Y reference the same data, because we can
208  // perform a triangular solve in-situ. however, we require that
209  // column access to each is strided.
210 
211  // set up import/export temporary multivectors
212  if (importer != null) {
213  if (importMV_ != null && importMV_->getNumVectors () != numVectors) {
214  importMV_ = null;
215  }
216  if (importMV_ == null) {
217  importMV_ = Teuchos::rcp (new MV (matrix_->getColMap (), numVectors));
218  }
219  }
220  if (exporter != null) {
221  if (exportMV_ != null && exportMV_->getNumVectors () != numVectors) {
222  exportMV_ = null;
223  }
224  if (exportMV_ == null) {
225  exportMV_ = Teuchos::rcp (new MV (matrix_->getRowMap (), numVectors));
226  }
227  }
228 
229  // solve(NO_TRANS): RangeMap -> DomainMap
230  // lclMatSolve_: RowMap -> ColMap
231  // importer: DomainMap -> ColMap
232  // exporter: RowMap -> RangeMap
233  //
234  // solve = reverse(exporter) o lclMatSolve_ o reverse(importer)
235  // RangeMap -> RowMap -> ColMap -> DomainMap
236  //
237  // If we have a non-trivial exporter, we must import elements that
238  // are permuted or are on other processors
239  if (exporter != null) {
240  exportMV_->doImport (X_in, *exporter, INSERT);
241  X = exportMV_;
242  }
243  else if (! X_in.isConstantStride ()) {
244  // cannot handle non-constant stride right now
245  // generate a copy of X_in
246  X = Teuchos::rcp (new MV (X_in));
247  }
248  else {
249  // just temporary, so this non-owning RCP is okay
250  X = Teuchos::rcpFromRef (X_in);
251  }
252 
253  // If we have a non-trivial importer, we must export elements that
254  // are permuted or belong to other processes. We will compute
255  // solution into the to-be-exported MV.
256  if (importer != null) {
257  matrix_->template localSolve<Scalar, Scalar> (*X, *importMV_, NO_TRANS);
258  // Make sure target is zero: necessary because we are adding.
259  Y_in.putScalar (ST::zero ());
260  Y_in.doExport (*importMV_, *importer, ADD);
261  }
262  // otherwise, solve into Y
263  else {
264  // can't solve into non-strided multivector
265  if (! Y_in.isConstantStride ()) {
266  // generate a strided copy of Y
267  MV Y (Y_in);
268  matrix_->template localSolve<Scalar, Scalar> (*X, Y, NO_TRANS);
269  Tpetra::deep_copy (Y_in, Y);
270  }
271  else {
272  matrix_->template localSolve<Scalar, Scalar> (*X, Y_in, NO_TRANS);
273  }
274  }
275  }
276 
278  void applyTranspose (const MV& X_in, MV& Y_in, const Teuchos::ETransp mode) const
279  {
280  typedef Teuchos::ScalarTraits<Scalar> ST;
281  using Teuchos::null;
282 
283  TEUCHOS_TEST_FOR_EXCEPTION
284  (mode != Teuchos::TRANS && mode != Teuchos::CONJ_TRANS, std::logic_error,
285  "Tpetra::CrsMatrixSolveOp::applyTranspose: mode is neither TRANS nor "
286  "CONJ_TRANS. Should never get here! Please report this bug to the "
287  "Tpetra developers.");
288 
289  const size_t numVectors = X_in.getNumVectors();
290  Teuchos::RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > importer =
291  matrix_->getGraph ()->getImporter ();
292  Teuchos::RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > exporter =
293  matrix_->getGraph ()->getExporter ();
294  Teuchos::RCP<const MV> X;
295 
296  // it is okay if X and Y reference the same data, because we can
297  // perform a triangular solve in-situ. however, we require that
298  // column access to each is strided.
299 
300  // set up import/export temporary multivectors
301  if (importer != null) {
302  if (importMV_ != null && importMV_->getNumVectors() != numVectors) {
303  importMV_ = null;
304  }
305  if (importMV_ == null) {
306  importMV_ = Teuchos::rcp( new MV(matrix_->getColMap(),numVectors) );
307  }
308  }
309  if (exporter != null) {
310  if (exportMV_ != null && exportMV_->getNumVectors() != numVectors) {
311  exportMV_ = null;
312  }
313  if (exportMV_ == null) {
314  exportMV_ = Teuchos::rcp( new MV(matrix_->getRowMap(),numVectors) );
315  }
316  }
317 
318  // solve(TRANS): DomainMap -> RangeMap
319  // lclMatSolve_(TRANS): ColMap -> RowMap
320  // importer: DomainMap -> ColMap
321  // exporter: RowMap -> RangeMap
322  //
323  // solve = importer o lclMatSolve_ o exporter
324  // Domainmap -> ColMap -> RowMap -> RangeMap
325  //
326  // If we have a non-trivial importer, we must import elements that
327  // are permuted or are on other processes.
328  if (importer != null) {
329  importMV_->doImport(X_in,*importer,INSERT);
330  X = importMV_;
331  }
332  else if (X_in.isConstantStride() == false) {
333  // cannot handle non-constant stride right now
334  // generate a copy of X_in
335  X = Teuchos::rcp(new MV(X_in));
336  }
337  else {
338  // just temporary, so this non-owning RCP is okay
339  X = Teuchos::rcpFromRef (X_in);
340  }
341 
342 
343  // If we have a non-trivial exporter, we must export elements that
344  // are permuted or belong to other processes. We will compute
345  // solution into the to-be-exported MV; get a view.
346  if (exporter != null) {
347  matrix_->template localSolve<Scalar, Scalar> (*X, *exportMV_,
348  Teuchos::CONJ_TRANS);
349  // Make sure target is zero: necessary because we are adding
350  Y_in.putScalar(ST::zero());
351  Y_in.doExport(*importMV_, *importer, ADD);
352  }
353  // otherwise, solve into Y
354  else {
355  if (Y_in.isConstantStride() == false) {
356  // generate a strided copy of Y
357  MV Y(Y_in);
358  matrix_->template localSolve<Scalar, Scalar> (*X, Y, Teuchos::CONJ_TRANS);
359  Y_in = Y;
360  }
361  else {
362  matrix_->template localSolve<Scalar, Scalar> (*X, Y_in, Teuchos::CONJ_TRANS);
363  }
364  }
365  }
366  };
367 
375  template<class OpScalar,
376  class MatScalar,
377  class LocalOrdinal,
378  class GlobalOrdinal,
379  class Node>
380  Teuchos::RCP<CrsMatrixSolveOp<OpScalar, MatScalar, LocalOrdinal, GlobalOrdinal, Node> >
382  {
384  }
385 
386 } // namespace Tpetra
387 
388 #endif // TPETRA_CRSMATRIXSOLVEOP_HPP
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
KokkosClassic::DefaultNode::DefaultNodeType node_type
Default value of Node template parameter.
int local_ordinal_type
Default value of LocalOrdinal template parameter.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
Insert new values that don't currently exist.
Sum new values into existing values.
Teuchos::RCP< CrsMatrixSolveOp< OpScalar, MatScalar, LocalOrdinal, GlobalOrdinal, Node > > createCrsMatrixSolveOp(const Teuchos::RCP< const CrsMatrix< MatScalar, LocalOrdinal, GlobalOrdinal, Node > > &A)
Nonmember function that wraps a CrsMatrix in a CrsMatrixSolveOp.
Wrap a CrsMatrix instance's triangular solve in an Operator.