Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_EpetraExtAddTransformer.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Thyra: Interfaces and Support for Abstract Numerical Algorithms
4 //
5 // Copyright 2004 NTESS and the Thyra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Thyra_EpetraExtAddTransformer.hpp"
11 #include "Thyra_AddedLinearOpBase.hpp"
12 #include "Thyra_ScaledAdjointLinearOpBase.hpp"
13 #include "Thyra_EpetraLinearOp.hpp"
14 #include "Thyra_get_Epetra_Operator.hpp"
16 #include "Thyra_DiagonalLinearOpBase.hpp"
17 #include "Thyra_DefaultDiagonalLinearOp.hpp"
18 #include "Thyra_IdentityLinearOpBase.hpp"
19 #include "Thyra_VectorStdOps.hpp"
20 #include "Epetra_Map.h"
21 #include "Epetra_LocalMap.h"
22 #include "Epetra_SerialComm.h"
23 #include "Epetra_Vector.h"
24 #include "Epetra_CrsMatrix.h"
25 #include "Teuchos_Assert.hpp"
26 #include "EpetraExt_ConfigDefs.h"
27 #include "EpetraExt_MatrixMatrix.h"
28 #include "EpetraExt_MMHelpers.h"
29 #include "EpetraExt_Transpose_RowMatrix.h"
30 
31 
32 #include "EpetraExt_RowMatrixOut.h"
33 
34 
35 namespace Thyra {
36 
37 
38 // Overridden from LinearOpTransformerBase
39 
40 
42  const LinearOpBase<double> &/* op_in */) const
43 {
46 }
47 
48 
51 {
52  return nonconstEpetraLinearOp();
53 }
54 
55 
57  const LinearOpBase<double> &op_in,
58  const Ptr<LinearOpBase<double> > &op_inout) const
59 {
60  using Thyra::unwrap;
61  using EpetraExt::MatrixMatrix;
62  using Teuchos::rcp;
63  using Teuchos::rcp_dynamic_cast;
64  using Teuchos::dyn_cast;
65 
66  //
67  // A) Get the component Thyra objects
68  //
69 
70  const AddedLinearOpBase<double> & add_op =
71  dyn_cast<const AddedLinearOpBase<double> >(op_in);
72 
73 #ifdef TEUCHOS_DEBUG
74  TEUCHOS_ASSERT_EQUALITY( add_op.numOps(), 2 );
75 #endif
76 
77 
78  // get properties of first operator: Transpose, scaler multiply...etc
79  const RCP<const LinearOpBase<double> > op_A = add_op.getOp(0);
80  double A_scalar = 0.0;
81  EOpTransp A_transp = NOTRANS;
83  unwrap( op_A, &A_scalar, &A_transp, &A );
84  TEUCHOS_ASSERT(A_transp==NOTRANS || A_transp==CONJTRANS); // sanity check
85 
86  // get properties of third operator: Transpose, scaler multiply...etc
87  const RCP<const LinearOpBase<double> > op_B = add_op.getOp(1);
88  double B_scalar = 0.0;
89  EOpTransp B_transp = NOTRANS;
91  unwrap( op_B, &B_scalar, &B_transp, &B );
92  TEUCHOS_ASSERT(B_transp==NOTRANS || B_transp==CONJTRANS); // sanity check
93 
94  //
95  // B) Extract out the Epetra_CrsMatrix objects and the vector
96  //
97 
98  // first makre sure identity operators are represented as digaonal vectors
99  if(rcp_dynamic_cast<const Thyra::IdentityLinearOpBase<double> >(A)!=Teuchos::null) {
100  RCP<Thyra::VectorBase<double> > d = Thyra::createMember(A->domain(), "d");
101  Thyra::V_S( d.ptr(), 1.0 ); // ToDo: Set ton != 1.0 and generalize
102  A = Thyra::diagonal(d);
103  }
104  if(rcp_dynamic_cast<const Thyra::IdentityLinearOpBase<double> >(B)!=Teuchos::null) {
105  RCP<Thyra::VectorBase<double> > d = Thyra::createMember(B->domain(), "d");
106  Thyra::V_S( d.ptr(), 1.0 ); // ToDo: Set ton != 1.0 and generalize
107  B = Thyra::diagonal(d);
108  }
109 
110 
111  // see if exactly one operator is a diagonal linear op
113  = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(A);
115  = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(B);
116 
117  // convert operators to Epetra_CrsMatrix
120  if(dA==Teuchos::null)
121  epetra_A = rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*A), true);
122  if(dB==Teuchos::null)
123  epetra_B = rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*B), true);
124 
125  //
126  // C) Do the explicit addition
127  //
128 
129  if(epetra_A!=Teuchos::null && epetra_B!=Teuchos::null) {
130 
131  // allocate space for final addition: 3 steps
132  // 1. Get destination EpetraLinearOp
133  // 2. Extract RCP to destination Epetra_CrsMatrix
134  // 3. If neccessary, allocate new Epetra_CrsMatrix
135  EpetraLinearOp &thyra_epetra_op_inout = dyn_cast<EpetraLinearOp>(*op_inout);
136  RCP<Epetra_CrsMatrix> epetra_op =
137  rcp_dynamic_cast<Epetra_CrsMatrix>(thyra_epetra_op_inout.epetra_op());
138  Epetra_CrsMatrix * epetra_op_raw = epetra_op.get();
139 
140  // perform addition
141  const int add_epetra_B_err
142  = EpetraExt::MatrixMatrix::Add(*epetra_A,A_transp==CONJTRANS,A_scalar,*epetra_B,B_transp==CONJTRANS,B_scalar,epetra_op_raw);
143  if(epetra_op==Teuchos::null)
144  epetra_op = Teuchos::rcp(epetra_op_raw);
145 
146  TEUCHOS_ASSERT_EQUALITY( add_epetra_B_err, 0 );
147 
148  epetra_op->FillComplete(epetra_A->DomainMap(),epetra_A->RangeMap());
149 
150  // set output operator to use newly create epetra_op
151  thyra_epetra_op_inout.initialize(epetra_op);
152  }
153  else if((dA!=Teuchos::null && epetra_B!=Teuchos::null) ||
154  (dB!=Teuchos::null && epetra_A!=Teuchos::null)) {
155 
156  // get unique addition values
157  RCP<const Epetra_CrsMatrix> crsMat = (dA!=Teuchos::null) ? epetra_B : epetra_A;
158  double matScalar = (dA!=Teuchos::null) ? B_scalar : A_scalar;
159  RCP<const DiagonalLinearOpBase<double> > diag = (dA!=Teuchos::null) ? dA : dB;
160  double diagScalar = (dA!=Teuchos::null) ? A_scalar : B_scalar;
161 
162  TEUCHOS_ASSERT(crsMat!=Teuchos::null);
163  TEUCHOS_ASSERT(diag!=Teuchos::null);
164 
165  // get or allocate an object to use as the destination
166  EpetraLinearOp & thyra_epetra_op_inout = dyn_cast<EpetraLinearOp>(*op_inout);
167  RCP<Epetra_CrsMatrix> epetra_op =
168  rcp_dynamic_cast<Epetra_CrsMatrix>(thyra_epetra_op_inout.epetra_op());
169 
170  if(epetra_op==Teuchos::null)
171  epetra_op = Teuchos::rcp(new Epetra_CrsMatrix(*crsMat));
172  else
173  *epetra_op = *crsMat;
174 
175  // grab vector to add to diagonal
176  RCP<const Epetra_Vector> v = get_Epetra_Vector(epetra_op->OperatorDomainMap(),diag->getDiag());
177 
178  if(matScalar!=1.0)
179  epetra_op->Scale(matScalar);
180 
181  // grab digaonal from matrix, do summation, then replace the values
182  RCP<Epetra_Vector> diagonal = rcp(new Epetra_Vector(epetra_op->OperatorDomainMap()));
183  TEUCHOS_TEST_FOR_EXCEPTION(epetra_op->ExtractDiagonalCopy(*diagonal),std::runtime_error,
184  "Thyra::EpetraExtractAddTransformer::transform ExtractDiagonalCopy failed!");;
185  diagonal->Update(diagScalar,*v,1.0); // no need to scale matrix, already scaled
186  TEUCHOS_TEST_FOR_EXCEPTION(epetra_op->ReplaceDiagonalValues(*diagonal),std::runtime_error,
187  "Thyra::EpetraExtractAddTransformer::transform ReplaceDiagonalValues failed!");;
188 
189  // set output operator to use newly create epetra_op
190  thyra_epetra_op_inout.initialize(epetra_op);
191  }
192  else {
193  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
194  "Your case of adding Epetra operators is not yet implemented! Contact the Thyra developers.");
195  }
196 }
197 
198 
199 } // namespace Thyra
int ReplaceDiagonalValues(const Epetra_Vector &Diagonal)
Concrete LinearOpBase adapter subclass for Epetra_Operator object.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
virtual void transform(const LinearOpBase< double > &op_in, const Ptr< LinearOpBase< double > > &op_inout) const
void unwrap(const LinearOpBase< Scalar > &Op, Scalar *scalar, EOpTransp *transp, const LinearOpBase< Scalar > **origOp)
Extract the overallScalar, overallTransp and const origOp from a const LinearOpBase object...
int ExtractDiagonalCopy(Epetra_Vector &Diagonal) const
Interface class for implicitly added linear operators.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Use the non-transposed operator.
T_To & dyn_cast(T_From &from)
Interface class for identity linear operators.
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types)...
T * get() const
const Epetra_Map & OperatorDomainMap() const
virtual int numOps() const =0
Returns the number of constituent operators.
int FillComplete(bool OptimizeDataStorage=true)
void initialize(const RCP< Epetra_Operator > &op, EOpTransp opTrans=NOTRANS, EApplyEpetraOpAs applyAs=EPETRA_OP_APPLY_APPLY, EAdjointEpetraOp adjointSupport=EPETRA_OP_ADJOINT_SUPPORTED, const RCP< const VectorSpaceBase< double > > &range=Teuchos::null, const RCP< const VectorSpaceBase< double > > &domain=Teuchos::null)
Fully initialize.
virtual bool isCompatible(const LinearOpBase< double > &op_in) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Ptr< T > ptr() const
RCP< Epetra_Vector > get_Epetra_Vector(const Epetra_Map &map, const RCP< VectorBase< double > > &v)
Get a non-const Epetra_Vector view from a non-const VectorBase object if possible.
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
Teuchos::RCP< Epetra_Operator > get_Epetra_Operator(LinearOpBase< Scalar > &)
Get smart pointer to non-const Epetra_Operator object from reference to a non-const EpetraLinearOp ac...
virtual Teuchos::RCP< const LinearOpBase< Scalar > > getOp(const int k) const =0
Return the kth constant constituent operator.
#define TEUCHOS_ASSERT(assertion_test)
int Scale(double ScalarConstant)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
virtual RCP< LinearOpBase< double > > createOutputOp() const
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
Interface class for for diagonal linear operators.
RCP< Epetra_Operator > epetra_op()