Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_EpetraExtDiagScaledMatProdTransformer.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_EpetraExtDiagScaledMatProdTransformer.hpp"
11#include "Thyra_MultipliedLinearOpBase.hpp"
12#include "Thyra_DiagonalLinearOpBase.hpp"
13#include "Thyra_ScaledAdjointLinearOpBase.hpp"
14#include "Thyra_EpetraLinearOp.hpp"
15#include "Thyra_get_Epetra_Operator.hpp"
17#include "Epetra_Map.h"
18#include "Epetra_LocalMap.h"
19#include "Epetra_SerialComm.h"
20#include "Epetra_CrsMatrix.h"
21#include "EpetraExt_MatrixMatrix.h"
22#include "Teuchos_Assert.hpp"
23
24
25namespace Thyra {
26
27
28// Overridden from LinearOpTransformerBase
29
30
37
38
41{
42 return nonconstEpetraLinearOp();
43}
44
45
47 const LinearOpBase<double> &op_in,
48 const Ptr<LinearOpBase<double> > &op_inout) const
49{
50 using Thyra::unwrap;
51 using EpetraExt::MatrixMatrix;
52 using Teuchos::rcp;
53 using Teuchos::rcp_dynamic_cast;
55
56 //
57 // A) Get the component Thyra objects for M = op(B) * D * G
58 //
59
60 const MultipliedLinearOpBase<double> &multi_op =
61 dyn_cast<const MultipliedLinearOpBase<double> >(op_in);
62
63 bool haveDiagScaling = (multi_op.numOps()==3);
64
65 // get properties of first operator: Transpose, scaler multiply...etc
66 const RCP<const LinearOpBase<double> > op_B = multi_op.getOp(0);
67 double B_scalar = 0.0;
68 EOpTransp B_transp = NOTRANS;
70 unwrap( op_B, &B_scalar, &B_transp, &B );
71 TEUCHOS_ASSERT(B_transp==NOTRANS || B_transp==CONJTRANS); // sanity check
72
73 // get diagonal scaling
75 double D_scalar = 1.0;
76 if(haveDiagScaling) {
77 const RCP<const LinearOpBase<double> > op_D = multi_op.getOp(1);
78 EOpTransp D_transp = NOTRANS;
80 unwrap( op_D, &D_scalar, &D_transp, &D );
81 d = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(D, true)->getDiag();
82 }
83
84 // get properties of third operator: Transpose, scaler multiply...etc
85 const RCP<const LinearOpBase<double> > op_G = multi_op.getOp(haveDiagScaling ? 2 : 1);
86 double G_scalar = 0.0;
87 EOpTransp G_transp = NOTRANS;
89 unwrap( op_G, &G_scalar, &G_transp, &G );
90 TEUCHOS_ASSERT(G_transp==NOTRANS || G_transp==CONJTRANS); // sanity check
91
92 //
93 // B) Extract out the Epetra_CrsMatrix objects and the vector
94 //
95
96 // convert second operator to an Epetra_CrsMatrix
97 const RCP<const Epetra_CrsMatrix> epetra_B =
98 rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*B), true);
99 // TEUCHOS_ASSERT( B_transp == NOTRANS ); // ToDo: Handle the transpose
100
101 // extract dagonal
103 if(haveDiagScaling) {
104 epetra_d = (B_transp==CONJTRANS ? get_Epetra_Vector(epetra_B->OperatorRangeMap(), d)
105 : get_Epetra_Vector(epetra_B->OperatorDomainMap(), d));
106 }
107
108 // convert third operator to an Epetra_CrsMatrix
109 const RCP<const Epetra_CrsMatrix> epetra_G =
110 rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*G), true);
111
112 // determine row map for final operator
113 const Epetra_Map op_inout_row_map
114 = (B_transp==CONJTRANS ? epetra_B->ColMap() : epetra_B->RowMap());
115 const Epetra_Map op_inout_col_map
116 = (G_transp==CONJTRANS ? epetra_B->RowMap() : epetra_B->ColMap());
117
118 //
119 // C) Do the explicit multiplication
120 //
121
122 // allocate space for final product: 3 steps
123 // 1. Get destination EpetraLinearOp
124 // 2. Extract RCP to destination Epetra_CrsMatrix
125 // 3. If neccessary, allocate new Epetra_CrsMatrix
126 EpetraLinearOp &thyra_epetra_op_inout = dyn_cast<EpetraLinearOp>(*op_inout);
127 RCP<Epetra_CrsMatrix> epetra_op =
128 rcp_dynamic_cast<Epetra_CrsMatrix>(thyra_epetra_op_inout.epetra_op());
129 if(is_null(epetra_op)) {
130 epetra_op = Teuchos::rcp(
131 new Epetra_CrsMatrix(::Copy, op_inout_row_map, 0));
132 }
133
134 // if necessary scale B by diagonal vector
136 if(haveDiagScaling) {
137 // create a temporary to get around const issue
138 RCP<Epetra_CrsMatrix> epetra_BD_temp = rcp(new Epetra_CrsMatrix(*epetra_B));
139
140 // scale matrix depending on properties of B
141 if(B_transp==CONJTRANS)
142 epetra_BD_temp->LeftScale(*epetra_d);
143 else
144 epetra_BD_temp->RightScale(*epetra_d);
145
146 epetra_BD = epetra_BD_temp;
147 }
148 else
149 epetra_BD = epetra_B;
150
151 // perform multiply
152 int mm_error = MatrixMatrix::Multiply( *epetra_BD, B_transp==CONJTRANS,
153 *epetra_G, G_transp==CONJTRANS, *epetra_op);
154 TEUCHOS_TEST_FOR_EXCEPTION(mm_error!=0,std::invalid_argument,
155 "EpetraExt::MatrixMatrix::Multiply failed returning error code " << mm_error << ".");
156
157 // scale the whole thing if neccessary
158 if(B_scalar*G_scalar*D_scalar!=1.0)
159 epetra_op->Scale(B_scalar*G_scalar*D_scalar);
160
161 // set output operator to use newly create epetra_op
162 thyra_epetra_op_inout.initialize(epetra_op);
163}
164
165
166} // namespace Thyra
virtual bool isCompatible(const LinearOpBase< double > &op_in) const
virtual void transform(const LinearOpBase< double > &op_in, const Ptr< LinearOpBase< double > > &op_inout) 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()
Base class for all linear operators.
Interface class for implicitly multiplied linear operators.
virtual int numOps() const =0
Returns the number of constituent operators.
virtual Teuchos::RCP< const LinearOpBase< Scalar > > getOp(const int k) const =0
Return the kth constant constituent operator.
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)
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)