|
Thyra Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Thyra: Interfaces and Support for Abstract Numerical Algorithms 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 00043 #include "Thyra_EpetraExtDiagScalingTransformer.hpp" 00044 #include "Thyra_MultipliedLinearOpBase.hpp" 00045 #include "Thyra_DiagonalLinearOpBase.hpp" 00046 #include "Thyra_ScaledAdjointLinearOpBase.hpp" 00047 #include "Thyra_EpetraLinearOp.hpp" 00048 #include "Thyra_get_Epetra_Operator.hpp" 00049 #include "Thyra_EpetraThyraWrappers.hpp" 00050 #include "Epetra_Map.h" 00051 #include "Epetra_LocalMap.h" 00052 #include "Epetra_SerialComm.h" 00053 #include "Epetra_CrsMatrix.h" 00054 #include "Teuchos_Assert.hpp" 00055 #include "Teuchos_RCP.hpp" 00056 00057 00058 namespace Thyra { 00059 00060 00061 // Overridden from LinearOpTransformerBase 00062 00063 00064 bool EpetraExtDiagScalingTransformer::isCompatible( 00065 const LinearOpBase<double> &op_in) const 00066 { 00067 using Thyra::unwrap; 00068 using Teuchos::rcp; 00069 using Teuchos::rcp_dynamic_cast; 00070 using Teuchos::dyn_cast; 00071 00072 const MultipliedLinearOpBase<double> &multi_op = 00073 dyn_cast<const MultipliedLinearOpBase<double> >(op_in); 00074 00075 // this operation must only have two operands 00076 if(multi_op.numOps()!=2) 00077 return false; 00078 00079 double scalar = 0.0; 00080 EOpTransp transp = NOTRANS; 00081 00082 // get properties of first operator: Transpose, scaler multiply...etc 00083 RCP<const LinearOpBase<double> > A; 00084 unwrap( multi_op.getOp(0), &scalar, &transp, &A ); 00085 if(transp!=NOTRANS) return false; 00086 00087 // get properties of second operator: Transpose, scaler multiply...etc 00088 RCP<const LinearOpBase<double> > B; 00089 unwrap( multi_op.getOp(1), &scalar, &transp, &B ); 00090 if(transp!=NOTRANS) return false; 00091 00092 // see if exactly one operator is a diagonal linear op 00093 RCP<const DiagonalLinearOpBase<double> > dA 00094 = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(A); 00095 RCP<const DiagonalLinearOpBase<double> > dB 00096 = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(B); 00097 00098 if(dA==Teuchos::null && dB!=Teuchos::null) 00099 return true; 00100 00101 if(dA!=Teuchos::null && dB==Teuchos::null) 00102 return true; 00103 00104 return false; 00105 } 00106 00107 00108 RCP<LinearOpBase<double> > 00109 EpetraExtDiagScalingTransformer::createOutputOp() const 00110 { 00111 return nonconstEpetraLinearOp(); 00112 } 00113 00114 00115 void EpetraExtDiagScalingTransformer::transform( 00116 const LinearOpBase<double> &op_in, 00117 const Ptr<LinearOpBase<double> > &op_inout) const 00118 { 00119 using Thyra::unwrap; 00120 using Teuchos::rcp; 00121 using Teuchos::rcp_dynamic_cast; 00122 using Teuchos::dyn_cast; 00123 00124 // 00125 // A) Get the component Thyra objects for M = op(A) * op(B) 00126 // 00127 00128 const MultipliedLinearOpBase<double> &multi_op = 00129 dyn_cast<const MultipliedLinearOpBase<double> >(op_in); 00130 00131 TEUCHOS_ASSERT(multi_op.numOps()==2); 00132 00133 // get properties of first operator: Transpose, scaler multiply...etc 00134 const RCP<const LinearOpBase<double> > op_A = multi_op.getOp(0); 00135 double A_scalar = 0.0; 00136 EOpTransp A_transp = NOTRANS; 00137 RCP<const LinearOpBase<double> > A; 00138 unwrap( op_A, &A_scalar, &A_transp, &A ); 00139 TEUCHOS_ASSERT(A_transp==NOTRANS || A_transp==CONJTRANS); // sanity check 00140 00141 // get properties of third operator: Transpose, scaler multiply...etc 00142 const RCP<const LinearOpBase<double> > op_B = multi_op.getOp(1); 00143 double B_scalar = 0.0; 00144 EOpTransp B_transp = NOTRANS; 00145 RCP<const LinearOpBase<double> > B; 00146 unwrap( op_B, &B_scalar, &B_transp, &B ); 00147 TEUCHOS_ASSERT(B_transp==NOTRANS || B_transp==CONJTRANS); // sanity check 00148 00149 // 00150 // B) Extract out the CrsMatrix and Diagonal objects 00151 // 00152 00153 // see if exactly one operator is a diagonal linear op 00154 RCP<const DiagonalLinearOpBase<double> > dA 00155 = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(A); 00156 RCP<const DiagonalLinearOpBase<double> > dB 00157 = rcp_dynamic_cast<const DiagonalLinearOpBase<double> >(B); 00158 00159 RCP<const Epetra_CrsMatrix> epetra_A; 00160 RCP<const Epetra_CrsMatrix> epetra_B; 00161 if(dA==Teuchos::null) { 00162 bool exactly_one_op_must_be_diagonal__dB_neq_null = dB!=Teuchos::null; 00163 TEUCHOS_ASSERT(exactly_one_op_must_be_diagonal__dB_neq_null); 00164 00165 // convert second operator to an Epetra_CrsMatrix 00166 epetra_A = rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*A), true); 00167 } 00168 else if(dB==Teuchos::null) { 00169 bool exactly_one_op_must_be_diagonal__dA_neq_null = dA!=Teuchos::null; 00170 TEUCHOS_ASSERT(exactly_one_op_must_be_diagonal__dA_neq_null); 00171 00172 // convert second operator to an Epetra_CrsMatrix 00173 epetra_B = rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*B), true); 00174 } 00175 else { 00176 bool exactly_one_op_must_be_diagonal=false; 00177 TEUCHOS_ASSERT(exactly_one_op_must_be_diagonal); 00178 } 00179 00180 TEUCHOS_ASSERT( A_transp == NOTRANS ); // ToDo: Handle the transpose 00181 TEUCHOS_ASSERT( B_transp == NOTRANS ); // ToDo: Handle the transpose 00182 00183 00184 // get or allocate an object to use as the destination 00185 EpetraLinearOp & thyra_epetra_op_inout = dyn_cast<EpetraLinearOp>(*op_inout); 00186 RCP<Epetra_CrsMatrix> epetra_op = 00187 rcp_dynamic_cast<Epetra_CrsMatrix>(thyra_epetra_op_inout.epetra_op()); 00188 00189 bool rightScale = dB!=Teuchos::null; 00190 00191 if(rightScale) { 00192 RCP<const Epetra_Vector> v = get_Epetra_Vector(epetra_A->OperatorDomainMap(),dB->getDiag()); 00193 00194 // if needed allocate a new operator, otherwise use old one assuming 00195 // constant sparsity 00196 if(epetra_op==Teuchos::null) 00197 epetra_op = Teuchos::rcp(new Epetra_CrsMatrix(*epetra_A)); 00198 else 00199 *epetra_op = *epetra_A; 00200 epetra_op->RightScale(*v); 00201 } 00202 else { 00203 RCP<const Epetra_Vector> v = get_Epetra_Vector(epetra_B->OperatorRangeMap(),dA->getDiag()); 00204 00205 // if needed allocate a new operator, otherwise use old one assuming 00206 // constant sparsity 00207 if(epetra_op==Teuchos::null) 00208 epetra_op = Teuchos::rcp(new Epetra_CrsMatrix(*epetra_B)); 00209 else 00210 *epetra_op = *epetra_B; 00211 epetra_op->LeftScale(*v); 00212 } 00213 00214 epetra_op->Scale(A_scalar*B_scalar); 00215 00216 // set output operator to use newly create epetra_op 00217 thyra_epetra_op_inout.initialize(epetra_op); 00218 } 00219 00220 00221 } // namespace Thyra
1.7.6.1