Thyra Version of the Day
Loading...
Searching...
No Matches
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
35namespace Thyra {
36
37
38// Overridden from LinearOpTransformerBase
39
40
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;
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;
160 double diagScalar = (dA!=Teuchos::null) ? A_scalar : B_scalar;
161
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
Ptr< T > ptr() const
T * get() const
Interface class for implicitly added linear operators.
virtual Teuchos::RCP< const LinearOpBase< Scalar > > getOp(const int k) const =0
Return the kth constant constituent operator.
virtual int numOps() const =0
Returns the number of constituent operators.
virtual void transform(const LinearOpBase< double > &op_in, const Ptr< LinearOpBase< double > > &op_inout) const
virtual RCP< LinearOpBase< double > > createOutputOp() const
virtual bool isCompatible(const LinearOpBase< double > &op_in) const
Concrete LinearOpBase adapter subclass for Epetra_Operator object.
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.
RCP< Epetra_Operator > epetra_op()
Interface class for identity linear operators.
Base class for all linear operators.
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_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
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.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
@ NOTRANS
Use the non-transposed operator.
@ CONJTRANS
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types).
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
T_To & dyn_cast(T_From &from)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)