|
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 #include "Thyra_EpetraLinearOp.hpp" 00043 #include "Thyra_EpetraThyraWrappers.hpp" 00044 #include "Thyra_SpmdMultiVectorBase.hpp" 00045 #include "Thyra_MultiVectorStdOps.hpp" 00046 #include "Thyra_AssertOp.hpp" 00047 #include "Teuchos_dyn_cast.hpp" 00048 #include "Teuchos_Assert.hpp" 00049 #include "Teuchos_getConst.hpp" 00050 #include "Teuchos_as.hpp" 00051 #include "Teuchos_TimeMonitor.hpp" 00052 00053 #include "Epetra_Map.h" 00054 #include "Epetra_Vector.h" 00055 #include "Epetra_Operator.h" 00056 #include "Epetra_CrsMatrix.h" // Printing and absolute row sums only! 00057 00058 00059 namespace Thyra { 00060 00061 00062 // Constructors / initializers / accessors 00063 00064 00065 EpetraLinearOp::EpetraLinearOp() 00066 :isFullyInitialized_(false), 00067 opTrans_(NOTRANS), 00068 applyAs_(EPETRA_OP_APPLY_APPLY), 00069 adjointSupport_(EPETRA_OP_ADJOINT_UNSUPPORTED) 00070 {} 00071 00072 00073 void EpetraLinearOp::initialize( 00074 const RCP<Epetra_Operator> &op, 00075 EOpTransp opTrans, 00076 EApplyEpetraOpAs applyAs, 00077 EAdjointEpetraOp adjointSupport, 00078 const RCP< const VectorSpaceBase<double> > &range_in, 00079 const RCP< const VectorSpaceBase<double> > &domain_in 00080 ) 00081 { 00082 00083 using Teuchos::rcp_dynamic_cast; 00084 typedef SpmdVectorSpaceBase<double> SPMDVSB; 00085 00086 // Validate input, allocate spaces, validate ... 00087 #ifdef TEUCHOS_DEBUG 00088 TEUCHOS_TEST_FOR_EXCEPTION( is_null(op), std::invalid_argument, 00089 "Thyra::EpetraLinearOp::initialize(...): Error!" ); 00090 // ToDo: Validate spmdRange, spmdDomain against op maps! 00091 #endif 00092 00093 RCP<const SPMDVSB> l_spmdRange; 00094 if(!is_null(range_in)) 00095 l_spmdRange = rcp_dynamic_cast<const SPMDVSB>(range_in,true); 00096 else 00097 l_spmdRange = ( applyAs==EPETRA_OP_APPLY_APPLY 00098 ? allocateRange(op,opTrans) : allocateDomain(op,opTrans) ); 00099 00100 RCP<const SPMDVSB> l_spmdDomain; 00101 if(!is_null(domain_in)) 00102 l_spmdDomain = rcp_dynamic_cast<const SPMDVSB>(domain_in,true); 00103 else 00104 l_spmdDomain = ( applyAs==EPETRA_OP_APPLY_APPLY 00105 ? allocateDomain(op,opTrans) : allocateRange(op,opTrans) ); 00106 00107 // Set data (no exceptions should be thrown now) 00108 isFullyInitialized_ = true; 00109 op_ = op; 00110 rowMatrix_ = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(op_); 00111 opTrans_ = opTrans; 00112 applyAs_ = applyAs; 00113 adjointSupport_ = adjointSupport; 00114 range_ = l_spmdRange; 00115 domain_ = l_spmdDomain; 00116 00117 } 00118 00119 00120 void EpetraLinearOp::partiallyInitialize( 00121 const RCP<const VectorSpaceBase<double> > &range_in, 00122 const RCP<const VectorSpaceBase<double> > &domain_in, 00123 const RCP<Epetra_Operator> &op, 00124 EOpTransp opTrans, 00125 EApplyEpetraOpAs applyAs, 00126 EAdjointEpetraOp adjointSupport 00127 ) 00128 { 00129 00130 using Teuchos::rcp_dynamic_cast; 00131 typedef SpmdVectorSpaceBase<double> SPMDVSB; 00132 00133 // Validate input, allocate spaces, validate ... 00134 #ifdef TEUCHOS_DEBUG 00135 TEUCHOS_TEST_FOR_EXCEPTION( is_null(range_in), std::invalid_argument, 00136 "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" ); 00137 TEUCHOS_TEST_FOR_EXCEPTION( is_null(domain_in), std::invalid_argument, 00138 "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" ); 00139 TEUCHOS_TEST_FOR_EXCEPTION( is_null(op), std::invalid_argument, 00140 "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" ); 00141 #endif 00142 00143 RCP<const SPMDVSB> 00144 l_spmdRange = rcp_dynamic_cast<const SPMDVSB>(range_in,true); 00145 RCP<const SPMDVSB> 00146 l_spmdDomain = rcp_dynamic_cast<const SPMDVSB>(domain_in,true); 00147 00148 // Set data (no exceptions should be thrown now) 00149 isFullyInitialized_ = false; 00150 op_ = op; 00151 rowMatrix_ = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(op_); 00152 opTrans_ = opTrans; 00153 applyAs_ = applyAs; 00154 adjointSupport_ = adjointSupport; 00155 range_ = l_spmdRange; 00156 domain_ = l_spmdDomain; 00157 00158 } 00159 00160 00161 void EpetraLinearOp::setFullyInitialized(bool isFullyInitialized) 00162 { 00163 // ToDo: Validate that everything matches up! 00164 isFullyInitialized_ = true; 00165 } 00166 00167 00168 void EpetraLinearOp::uninitialize( 00169 RCP<Epetra_Operator> *op, 00170 EOpTransp *opTrans, 00171 EApplyEpetraOpAs *applyAs, 00172 EAdjointEpetraOp *adjointSupport, 00173 RCP<const VectorSpaceBase<double> > *range_out, 00174 RCP<const VectorSpaceBase<double> > *domain_out 00175 ) 00176 { 00177 00178 if(op) *op = op_; 00179 if(opTrans) *opTrans = opTrans_; 00180 if(applyAs) *applyAs = applyAs_; 00181 if(adjointSupport) *adjointSupport = adjointSupport_; 00182 if(range_out) *range_out = range_; 00183 if(domain_out) *domain_out = domain_; 00184 00185 isFullyInitialized_ = false; 00186 op_ = Teuchos::null; 00187 rowMatrix_ = Teuchos::null; 00188 opTrans_ = NOTRANS; 00189 applyAs_ = EPETRA_OP_APPLY_APPLY; 00190 adjointSupport_ = EPETRA_OP_ADJOINT_SUPPORTED; 00191 range_ = Teuchos::null; 00192 domain_ = Teuchos::null; 00193 00194 } 00195 00196 00197 RCP< const SpmdVectorSpaceBase<double> > 00198 EpetraLinearOp::spmdRange() const 00199 { 00200 return range_; 00201 } 00202 00203 00204 RCP< const SpmdVectorSpaceBase<double> > 00205 EpetraLinearOp::spmdDomain() const 00206 { 00207 return domain_; 00208 } 00209 00210 00211 RCP<Epetra_Operator> 00212 EpetraLinearOp::epetra_op() 00213 { 00214 return op_; 00215 } 00216 00217 00218 RCP<const Epetra_Operator> 00219 EpetraLinearOp::epetra_op() const 00220 { 00221 return op_; 00222 } 00223 00224 00225 // Overridden from EpetraLinearOpBase 00226 00227 00228 void EpetraLinearOp::getNonconstEpetraOpView( 00229 const Ptr<RCP<Epetra_Operator> > &epetraOp, 00230 const Ptr<EOpTransp> &epetraOpTransp, 00231 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs, 00232 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport 00233 ) 00234 { 00235 *epetraOp = op_; 00236 *epetraOpTransp = opTrans_; 00237 *epetraOpApplyAs = applyAs_; 00238 *epetraOpAdjointSupport = adjointSupport_; 00239 } 00240 00241 00242 void EpetraLinearOp::getEpetraOpView( 00243 const Ptr<RCP<const Epetra_Operator> > &epetraOp, 00244 const Ptr<EOpTransp> &epetraOpTransp, 00245 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs, 00246 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport 00247 ) const 00248 { 00249 *epetraOp = op_; 00250 *epetraOpTransp = opTrans_; 00251 *epetraOpApplyAs = applyAs_; 00252 *epetraOpAdjointSupport = adjointSupport_; 00253 } 00254 00255 00256 // Overridden from LinearOpBase 00257 00258 00259 RCP<const VectorSpaceBase<double> > 00260 EpetraLinearOp::range() const 00261 { 00262 return range_; 00263 } 00264 00265 00266 RCP<const VectorSpaceBase<double> > 00267 EpetraLinearOp::domain() const 00268 { 00269 return domain_; 00270 } 00271 00272 00273 RCP<const LinearOpBase<double> > 00274 EpetraLinearOp::clone() const 00275 { 00276 assert(0); // ToDo: Implement when needed 00277 return Teuchos::null; 00278 } 00279 00280 00281 // Overridden from Teuchos::Describable 00282 00283 00284 std::string EpetraLinearOp::description() const 00285 { 00286 std::ostringstream oss; 00287 oss << Teuchos::Describable::description() << "{"; 00288 if(op_.get()) { 00289 oss << "op=\'"<<typeName(*op_)<<"\'"; 00290 oss << ",rangeDim="<<this->range()->dim(); 00291 oss << ",domainDim="<<this->domain()->dim(); 00292 } 00293 else { 00294 oss << "op=NULL"; 00295 } 00296 oss << "}"; 00297 return oss.str(); 00298 } 00299 00300 00301 void EpetraLinearOp::describe( 00302 FancyOStream &out, 00303 const Teuchos::EVerbosityLevel verbLevel 00304 ) const 00305 { 00306 using Teuchos::includesVerbLevel; 00307 using Teuchos::as; 00308 using Teuchos::rcp_dynamic_cast; 00309 using Teuchos::OSTab; 00310 using Teuchos::describe; 00311 OSTab tab(out); 00312 if ( as<int>(verbLevel) == as<int>(Teuchos::VERB_LOW) || is_null(op_)) { 00313 out << this->description() << std::endl; 00314 } 00315 else if (includesVerbLevel(verbLevel,Teuchos::VERB_MEDIUM)) { 00316 out 00317 << Teuchos::Describable::description() 00318 << "{" 00319 << "rangeDim=" << this->range()->dim() 00320 << ",domainDim=" << this->domain()->dim() 00321 << "}\n"; 00322 OSTab tab2(out); 00323 if (op_.get()) { 00324 if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) { 00325 out << "opTrans="<<toString(opTrans_)<<"\n"; 00326 out << "applyAs="<<toString(applyAs_)<<"\n"; 00327 out << "adjointSupport="<<toString(adjointSupport_)<<"\n"; 00328 out << "op="<<typeName(*op_)<<"\n"; 00329 } 00330 if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME) ) { 00331 OSTab tab3(out); 00332 RCP<const Epetra_CrsMatrix> 00333 csr_op = rcp_dynamic_cast<const Epetra_CrsMatrix>(op_); 00334 if (!is_null(csr_op)) { 00335 csr_op->Print(out); 00336 } 00337 } 00338 } 00339 else { 00340 out << "op=NULL"<<"\n"; 00341 } 00342 } 00343 } 00344 00345 00346 // protected 00347 00348 00349 // Protected member functions overridden from LinearOpBase 00350 00351 00352 bool EpetraLinearOp::opSupportedImpl(EOpTransp M_trans) const 00353 { 00354 if (!isFullyInitialized_) 00355 return false; 00356 return ( M_trans == NOTRANS 00357 ? true : adjointSupport_==EPETRA_OP_ADJOINT_SUPPORTED ); 00358 } 00359 00360 00361 void EpetraLinearOp::applyImpl( 00362 const EOpTransp M_trans, 00363 const MultiVectorBase<double> &X_in, 00364 const Ptr<MultiVectorBase<double> > &Y_inout, 00365 const double alpha, 00366 const double beta 00367 ) const 00368 { 00369 00370 THYRA_FUNC_TIME_MONITOR("Thyra::EpetraLinearOp::euclideanApply"); 00371 00372 const EOpTransp real_M_trans = real_trans(M_trans); 00373 00374 #ifdef TEUCHOS_DEBUG 00375 TEUCHOS_TEST_FOR_EXCEPT(!isFullyInitialized_); 00376 THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES( 00377 "EpetraLinearOp::euclideanApply(...)", *this, M_trans, X_in, Y_inout 00378 ); 00379 TEUCHOS_TEST_FOR_EXCEPTION( 00380 real_M_trans==TRANS && adjointSupport_==EPETRA_OP_ADJOINT_UNSUPPORTED, 00381 Exceptions::OpNotSupported, 00382 "EpetraLinearOp::apply(...): *this was informed that adjoints " 00383 "are not supported when initialized." 00384 ); 00385 #endif 00386 00387 const RCP<const VectorSpaceBase<double> > XY_domain = X_in.domain(); 00388 const int numCols = XY_domain->dim(); 00389 00390 // 00391 // Get Epetra_MultiVector objects for the arguments 00392 // 00393 // 2007/08/18: rabartl: Note: After profiling, I found that calling the more 00394 // general functions get_Epetra_MultiVector(...) was too slow. These 00395 // functions must ensure that memory is being remembered efficiently and the 00396 // use of extra data with the RCP and other things is slow. 00397 // 00398 RCP<const Epetra_MultiVector> X; 00399 RCP<Epetra_MultiVector> Y; 00400 { 00401 THYRA_FUNC_TIME_MONITOR_DIFF( 00402 "Thyra::EpetraLinearOp::euclideanApply: Convert MultiVectors", MultiVectors); 00403 // X 00404 X = get_Epetra_MultiVector( 00405 real_M_trans==NOTRANS ? getDomainMap() : getRangeMap(), X_in ); 00406 // Y 00407 if( beta == 0 ) { 00408 Y = get_Epetra_MultiVector( 00409 real_M_trans==NOTRANS ? getRangeMap() : getDomainMap(), *Y_inout ); 00410 } 00411 } 00412 00413 // 00414 // Set the operator mode 00415 // 00416 00417 /* We need to save the transpose state here, and then reset it after 00418 * application. The reason for this is that if we later apply the 00419 * operator outside Thyra (in Aztec, for instance), it will remember 00420 * the transpose flag set here. */ 00421 bool oldState = op_->UseTranspose(); 00422 op_->SetUseTranspose( 00423 real_trans(trans_trans(opTrans_,M_trans)) == NOTRANS ? false : true ); 00424 00425 // 00426 // Perform the apply operation 00427 // 00428 { 00429 THYRA_FUNC_TIME_MONITOR_DIFF( 00430 "Thyra::EpetraLinearOp::euclideanApply: Apply", Apply); 00431 if( beta == 0.0 ) { 00432 // Y = M * X 00433 if( applyAs_ == EPETRA_OP_APPLY_APPLY ) { 00434 THYRA_FUNC_TIME_MONITOR_DIFF( 00435 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): Apply", 00436 ApplyApply); 00437 op_->Apply( *X, *Y ); 00438 } 00439 else if( applyAs_ == EPETRA_OP_APPLY_APPLY_INVERSE ) { 00440 THYRA_FUNC_TIME_MONITOR_DIFF( 00441 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): ApplyInverse", 00442 ApplyApplyInverse); 00443 op_->ApplyInverse( *X, *Y ); 00444 } 00445 else { 00446 #ifdef TEUCHOS_DEBUG 00447 TEUCHOS_TEST_FOR_EXCEPT(true); 00448 #endif 00449 } 00450 // Y = alpha * Y 00451 if( alpha != 1.0 ) { 00452 THYRA_FUNC_TIME_MONITOR_DIFF( 00453 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): Scale Y", 00454 Scale); 00455 Y->Scale(alpha); 00456 } 00457 } 00458 else { // beta != 0.0 00459 // Y_inout = beta * Y_inout 00460 if(beta != 0.0) { 00461 THYRA_FUNC_TIME_MONITOR_DIFF( 00462 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Scale Y", 00463 Scale); 00464 scale( beta, Y_inout ); 00465 } 00466 else { 00467 THYRA_FUNC_TIME_MONITOR_DIFF( 00468 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Y=0", 00469 Apply2); 00470 assign( Y_inout, 0.0 ); 00471 } 00472 // T = M * X 00473 Epetra_MultiVector T(op_->OperatorRangeMap(), numCols, false); 00474 // NOTE: Above, op_->OperatorRange() will be right for either 00475 // non-transpose or transpose because we have already set the 00476 // UseTranspose flag correctly. 00477 if( applyAs_ == EPETRA_OP_APPLY_APPLY ) { 00478 THYRA_FUNC_TIME_MONITOR_DIFF( 00479 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Apply", 00480 Apply2); 00481 op_->Apply( *X, T ); 00482 } 00483 else if( applyAs_ == EPETRA_OP_APPLY_APPLY_INVERSE ) { 00484 THYRA_FUNC_TIME_MONITOR_DIFF( 00485 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): ApplyInverse", 00486 ApplyInverse); 00487 op_->ApplyInverse( *X, T ); 00488 } 00489 else { 00490 #ifdef TEUCHOS_DEBUG 00491 TEUCHOS_TEST_FOR_EXCEPT(true); 00492 #endif 00493 } 00494 // Y_inout += alpha * T 00495 { 00496 THYRA_FUNC_TIME_MONITOR_DIFF( 00497 "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Update Y", 00498 Update); 00499 update( 00500 alpha, 00501 *create_MultiVector( 00502 Teuchos::rcp(&Teuchos::getConst(T),false), 00503 Y_inout->range(), 00504 XY_domain 00505 ), 00506 Y_inout 00507 ); 00508 } 00509 } 00510 } 00511 00512 // Reset the transpose state 00513 op_->SetUseTranspose(oldState); 00514 00515 // 2009/04/14: ToDo: This will not reset the transpose flag correctly if an 00516 // exception is thrown! 00517 00518 } 00519 00520 00521 // Protected member functions overridden from ScaledLinearOpBase 00522 00523 00524 bool EpetraLinearOp::supportsScaleLeftImpl() const 00525 { 00526 return nonnull(rowMatrix_); 00527 } 00528 00529 00530 bool EpetraLinearOp::supportsScaleRightImpl() const 00531 { 00532 return nonnull(rowMatrix_); 00533 } 00534 00535 00536 void EpetraLinearOp::scaleLeftImpl(const VectorBase<double> &row_scaling_in) 00537 { 00538 using Teuchos::rcpFromRef; 00539 const RCP<const Epetra_Vector> row_scaling = 00540 get_Epetra_Vector(getRangeMap(), rcpFromRef(row_scaling_in)); 00541 rowMatrix_->LeftScale(*row_scaling); 00542 } 00543 00544 00545 void EpetraLinearOp::scaleRightImpl(const VectorBase<double> &col_scaling_in) 00546 { 00547 using Teuchos::rcpFromRef; 00548 const RCP<const Epetra_Vector> col_scaling = 00549 get_Epetra_Vector(getDomainMap(), rcpFromRef(col_scaling_in)); 00550 rowMatrix_->RightScale(*col_scaling); 00551 } 00552 00553 00554 // Protected member functions overridden from RowStatLinearOpBase 00555 00556 00557 bool EpetraLinearOp::rowStatIsSupportedImpl( 00558 const RowStatLinearOpBaseUtils::ERowStat rowStat) const 00559 { 00560 if (is_null(rowMatrix_)) { 00561 return false; 00562 } 00563 switch (rowStat) { 00564 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM: 00565 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM: 00566 return true; 00567 default: 00568 TEUCHOS_TEST_FOR_EXCEPT(true); 00569 } 00570 return false; // Will never be called! 00571 } 00572 00573 00574 void EpetraLinearOp::getRowStatImpl( 00575 const RowStatLinearOpBaseUtils::ERowStat rowStat, 00576 const Ptr<VectorBase<double> > &rowStatVec_in 00577 ) const 00578 { 00579 using Teuchos::rcpFromPtr; 00580 const RCP<Epetra_Vector> rowStatVec = 00581 get_Epetra_Vector(getRangeMap(), rcpFromPtr(rowStatVec_in)); 00582 switch (rowStat) { 00583 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM: 00584 rowMatrix_->InvRowSums(*rowStatVec); 00585 break; 00586 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM: 00587 // compute absolute row sum 00588 computeAbsRowSum(*rowStatVec); 00589 break; 00590 default: 00591 TEUCHOS_TEST_FOR_EXCEPT(true); 00592 } 00593 } 00594 00595 00596 // Allocators for domain and range spaces 00597 00598 00599 RCP< const SpmdVectorSpaceBase<double> > 00600 EpetraLinearOp::allocateDomain( 00601 const RCP<Epetra_Operator> &op, 00602 EOpTransp op_trans 00603 ) const 00604 { 00605 return Teuchos::rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >( 00606 create_VectorSpace(Teuchos::rcp(&op->OperatorDomainMap(),false)) 00607 ); 00608 // ToDo: What about the transpose argument???, test this!!! 00609 } 00610 00611 00612 RCP<const SpmdVectorSpaceBase<double> > 00613 EpetraLinearOp::allocateRange( 00614 const RCP<Epetra_Operator> &op, 00615 EOpTransp op_trans 00616 ) const 00617 { 00618 return Teuchos::rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >( 00619 create_VectorSpace(Teuchos::rcp(&op->OperatorRangeMap(),false)) 00620 ); 00621 // ToDo: What about the transpose argument???, test this!!! 00622 } 00623 00624 // private 00625 00626 00627 const Epetra_Map& EpetraLinearOp::getRangeMap() const 00628 { 00629 return ( applyAs_ == EPETRA_OP_APPLY_APPLY 00630 ? op_->OperatorRangeMap() : op_->OperatorDomainMap() ); 00631 // ToDo: What about the transpose argument???, test this!!! 00632 } 00633 00634 00635 const Epetra_Map& EpetraLinearOp::getDomainMap() const 00636 { 00637 return ( applyAs_ == EPETRA_OP_APPLY_APPLY 00638 ? op_->OperatorDomainMap() : op_->OperatorRangeMap() ); 00639 // ToDo: What about the transpose argument???, test this!!! 00640 } 00641 00642 void EpetraLinearOp::computeAbsRowSum(Epetra_Vector & x) const 00643 { 00644 TEUCHOS_ASSERT(!is_null(rowMatrix_)); 00645 00646 RCP<Epetra_CrsMatrix> crsMatrix 00647 = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(rowMatrix_); 00648 00649 TEUCHOS_TEST_FOR_EXCEPTION(is_null(crsMatrix), 00650 Exceptions::OpNotSupported, 00651 "EpetraLinearOp::computeAbsRowSum(...): wrapped matrix must be of type " 00652 "Epetra_CrsMatrix for this method. Other operator types are not supported." 00653 ); 00654 00655 // 00656 // Put inverse of the sum of absolute values of the ith row of A in x[i]. 00657 // (this is a modified copy of Epetra_CrsMatrix::InvRowSums) 00658 // 00659 00660 if (crsMatrix->Filled()) { 00661 TEUCHOS_TEST_FOR_EXCEPTION(is_null(crsMatrix), 00662 std::invalid_argument, 00663 "EpetraLinearOp::computeAbsRowSum(...): Epetra_CrsMatrix must be filled" 00664 ); 00665 } 00666 int i, j; 00667 x.PutScalar(0.0); // Make sure we sum into a vector of zeros. 00668 double * xp = (double*)x.Values(); 00669 if (crsMatrix->Graph().RangeMap().SameAs(x.Map()) && crsMatrix->Exporter() != 0) { 00670 Epetra_Vector x_tmp(crsMatrix->RowMap()); 00671 x_tmp.PutScalar(0.0); 00672 double * x_tmp_p = (double*)x_tmp.Values(); 00673 for (i=0; i < crsMatrix->NumMyRows(); i++) { 00674 int NumEntries = 0; 00675 double * RowValues = 0; 00676 crsMatrix->ExtractMyRowView(i,NumEntries,RowValues); 00677 for (j=0; j < NumEntries; j++) x_tmp_p[i] += std::abs(RowValues[j]); 00678 } 00679 TEUCHOS_TEST_FOR_EXCEPT(0!=x.Export(x_tmp, *crsMatrix->Exporter(), Add)); //Export partial row sums to x. 00680 } 00681 else if (crsMatrix->Graph().RowMap().SameAs(x.Map())) { 00682 for (i=0; i < crsMatrix->NumMyRows(); i++) { 00683 int NumEntries = 0; 00684 double * RowValues = 0; 00685 crsMatrix->ExtractMyRowView(i,NumEntries,RowValues); 00686 double scale = 0.0; 00687 for (j=0; j < NumEntries; j++) scale += std::abs(RowValues[j]); 00688 xp[i] = scale; 00689 } 00690 } 00691 else { // x.Map different than both crsMatrix->Graph().RowMap() and crsMatrix->Graph().RangeMap() 00692 TEUCHOS_TEST_FOR_EXCEPT(true); // The map of x must be the RowMap or RangeMap of A. 00693 } 00694 } 00695 00696 } // end namespace Thyra 00697 00698 00699 // Nonmembers 00700 00701 00702 Teuchos::RCP<Thyra::EpetraLinearOp> 00703 Thyra::nonconstEpetraLinearOp() 00704 { 00705 return Teuchos::rcp(new EpetraLinearOp()); 00706 } 00707 00708 00709 Teuchos::RCP<Thyra::EpetraLinearOp> 00710 Thyra::partialNonconstEpetraLinearOp( 00711 const RCP<const VectorSpaceBase<double> > &range, 00712 const RCP<const VectorSpaceBase<double> > &domain, 00713 const RCP<Epetra_Operator> &op, 00714 EOpTransp opTrans, 00715 EApplyEpetraOpAs applyAs, 00716 EAdjointEpetraOp adjointSupport 00717 ) 00718 { 00719 RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp()); 00720 thyraEpetraOp->partiallyInitialize( 00721 range, domain,op,opTrans, applyAs, adjointSupport 00722 ); 00723 return thyraEpetraOp; 00724 } 00725 00726 00727 Teuchos::RCP<Thyra::EpetraLinearOp> 00728 Thyra::nonconstEpetraLinearOp( 00729 const RCP<Epetra_Operator> &op, 00730 EOpTransp opTrans, 00731 EApplyEpetraOpAs applyAs, 00732 EAdjointEpetraOp adjointSupport, 00733 const RCP< const VectorSpaceBase<double> > &range, 00734 const RCP< const VectorSpaceBase<double> > &domain 00735 ) 00736 { 00737 RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp()); 00738 thyraEpetraOp->initialize( 00739 op,opTrans, applyAs, adjointSupport, range, domain 00740 ); 00741 return thyraEpetraOp; 00742 } 00743 00744 00745 Teuchos::RCP<const Thyra::EpetraLinearOp> 00746 Thyra::epetraLinearOp( 00747 const RCP<const Epetra_Operator> &op, 00748 EOpTransp opTrans, 00749 EApplyEpetraOpAs applyAs, 00750 EAdjointEpetraOp adjointSupport, 00751 const RCP<const VectorSpaceBase<double> > &range, 00752 const RCP<const VectorSpaceBase<double> > &domain 00753 ) 00754 { 00755 RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp()); 00756 thyraEpetraOp->initialize( 00757 Teuchos::rcp_const_cast<Epetra_Operator>(op), // Safe cast due to return type! 00758 opTrans, applyAs, adjointSupport, range, domain 00759 ); 00760 return thyraEpetraOp; 00761 } 00762 00763 00764 Teuchos::RCP<Thyra::EpetraLinearOp> 00765 Thyra::nonconstEpetraLinearOp( 00766 const RCP<Epetra_Operator> &op, 00767 const std::string &label, 00768 EOpTransp opTrans, 00769 EApplyEpetraOpAs applyAs, 00770 EAdjointEpetraOp adjointSupport, 00771 const RCP<const VectorSpaceBase<double> > &range, 00772 const RCP<const VectorSpaceBase<double> > &domain 00773 ) 00774 { 00775 RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp()); 00776 thyraEpetraOp->initialize( 00777 op,opTrans, applyAs, adjointSupport, range, domain 00778 ); 00779 thyraEpetraOp->setObjectLabel(label); 00780 return thyraEpetraOp; 00781 } 00782 00783 00784 Teuchos::RCP<const Thyra::EpetraLinearOp> 00785 Thyra::epetraLinearOp( 00786 const RCP<const Epetra_Operator> &op, 00787 const std::string &label, 00788 EOpTransp opTrans, 00789 EApplyEpetraOpAs applyAs, 00790 EAdjointEpetraOp adjointSupport, 00791 const RCP< const SpmdVectorSpaceBase<double> > &range, 00792 const RCP< const SpmdVectorSpaceBase<double> > &domain 00793 ) 00794 { 00795 RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp()); 00796 thyraEpetraOp->initialize( 00797 Teuchos::rcp_const_cast<Epetra_Operator>(op), // Safe cast due to return type! 00798 opTrans, applyAs, adjointSupport, range, domain 00799 ); 00800 thyraEpetraOp->setObjectLabel(label); 00801 return thyraEpetraOp; 00802 }
1.7.6.1