|
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 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 // @HEADER 00028 00029 #ifndef THYRA_ASSERT_OP_HPP 00030 #define THYRA_ASSERT_OP_HPP 00031 00032 00033 #include "Thyra_OperatorVectorTypes.hpp" 00034 #include "Thyra_VectorSpaceBase.hpp" 00035 #include "Thyra_VectorBase.hpp" 00036 #include "Thyra_LinearOpBase.hpp" 00037 #include "Teuchos_TestForException.hpp" 00038 00039 00040 namespace Thyra { 00041 00042 00043 /* Utility struct for dumping vector space names, dimension etc. 00044 */ 00045 template<class Scalar> 00046 struct dump_vec_spaces_t { 00047 public: 00048 dump_vec_spaces_t( 00049 const Thyra::VectorSpaceBase<Scalar>& _vec_space1, 00050 const std::string &_vec_space1_name, 00051 const Thyra::VectorSpaceBase<Scalar>& _vec_space2, 00052 const std::string &_vec_space2_name 00053 ) 00054 :vec_space1(_vec_space1),vec_space1_name(_vec_space1_name) 00055 ,vec_space2(_vec_space2),vec_space2_name(_vec_space2_name) 00056 {} 00057 const Thyra::VectorSpaceBase<Scalar> &vec_space1; 00058 const std::string vec_space1_name; 00059 const Thyra::VectorSpaceBase<Scalar> &vec_space2; 00060 const std::string vec_space2_name; 00061 }; // end dum_vec_spaces 00062 00063 00064 /* Utility function for dumping vector space names, dimension etc. 00065 */ 00066 template<class Scalar> 00067 inline dump_vec_spaces_t<Scalar> dump_vec_spaces( 00068 const Thyra::VectorSpaceBase<Scalar>& vec_space1, 00069 const std::string &vec_space1_name, 00070 const Thyra::VectorSpaceBase<Scalar>& vec_space2, 00071 const std::string &vec_space2_name 00072 ) 00073 { 00074 return dump_vec_spaces_t<Scalar>( 00075 vec_space1,vec_space1_name,vec_space2,vec_space2_name); 00076 } 00077 00078 00079 // Notice!!!!!!! Place a breakpoint in following function in order to halt the 00080 // program just before an exception is thrown! 00081 00082 00083 /* Utility ostream operator for dumping vector space names, dimension etc. 00084 */ 00085 template<class Scalar> 00086 std::ostream& operator<<( std::ostream& o, const dump_vec_spaces_t<Scalar>& d ) 00087 { 00088 00089 using Teuchos::OSTab; 00090 const Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM; 00091 o << "Error, the following vector spaces are not compatible:\n\n"; 00092 OSTab(o).o() 00093 << d.vec_space1_name << " : " 00094 << Teuchos::describe(d.vec_space1,verbLevel); 00095 o << "\n"; 00096 OSTab(o).o() 00097 << d.vec_space2_name << " : " 00098 << Teuchos::describe(d.vec_space2,verbLevel); 00099 return o; 00100 } 00101 00102 00103 /* Utility enum for selecting domain or range spaces 00104 */ 00105 enum EM_VS { VS_RANGE, VS_DOMAIN }; 00106 00107 00112 template<class Scalar> 00113 const Thyra::VectorSpaceBase<Scalar>& linear_op_op( 00114 const Thyra::LinearOpBase<Scalar>& M, 00115 Thyra::EOpTransp M_trans, 00116 EM_VS M_VS 00117 ) 00118 { 00119 if(real_trans(M_trans) == NOTRANS && M_VS == VS_RANGE) 00120 return *M.range(); 00121 if(real_trans(M_trans) == TRANS && M_VS == VS_RANGE) 00122 return *M.domain(); 00123 if(real_trans(M_trans) == NOTRANS && M_VS == VS_DOMAIN) 00124 return *M.domain(); 00125 // real_trans(M_trans) == TRANS && M_VS == VS_DOMAIN 00126 return *M.range(); 00127 } 00128 00129 00130 } // end namespace Thyra 00131 00132 00137 #define THYRA_ASSERT_LHS_ARG(FUNC_NAME,LHS_ARG) \ 00138 TEST_FOR_EXCEPTION( \ 00139 (LHS_ARG) == NULL, std::invalid_argument \ 00140 ,FUNC_NAME << " : Error!" \ 00141 ); 00142 00143 00144 // Notice!!!!!!! Setting a breakpoint at the line number that is printed by this macro 00145 // and then trying to set the condition !isCompatible does not work (at least not 00146 // in gdb). 00147 00148 00153 #define THYRA_ASSERT_VEC_SPACES_NAMES(FUNC_NAME,VS1,VS1_NAME,VS2,VS2_NAME) \ 00154 { \ 00155 const bool l_isCompatible = (VS1).isCompatible(VS2); \ 00156 TEST_FOR_EXCEPTION( \ 00157 !l_isCompatible, ::Thyra::Exceptions::IncompatibleVectorSpaces, \ 00158 FUNC_NAME << "\n\n" \ 00159 << ::Thyra::dump_vec_spaces(VS1,VS1_NAME,VS2,VS2_NAME) \ 00160 ) \ 00161 } 00162 00163 00175 #define THYRA_ASSERT_VEC_SPACES(FUNC_NAME,VS1,VS2)\ 00176 THYRA_ASSERT_VEC_SPACES_NAMES(FUNC_NAME,VS1,#VS1,VS2,#VS2) 00177 00178 00186 #define THYRA_ASSERT_MAT_VEC_SPACES(FUNC_NAME,M,M_T,M_VS,VS) \ 00187 { \ 00188 std::ostringstream M_VS_name; \ 00189 M_VS_name << "(" #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << ")" \ 00190 << "." << ( (M_VS) == Thyra::VS_RANGE ? "range()" : "domain()" ); \ 00191 THYRA_ASSERT_VEC_SPACES_NAMES( \ 00192 FUNC_NAME, \ 00193 ::Thyra::linear_op_op(M,M_T,M_VS),M_VS_name.str().c_str(), \ 00194 (VS),#VS \ 00195 ) \ 00196 } 00197 00198 00211 #define THYRA_ASSERT_LINEAR_OP_VEC_APPLY_SPACES(FUNC_NAME,M,M_T,X,Y) \ 00212 { \ 00213 std::ostringstream headeross; \ 00214 headeross \ 00215 << FUNC_NAME << ":\n" \ 00216 << "Spaces check failed for " \ 00217 << #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << " * " \ 00218 << #X << " and " << #Y; \ 00219 const std::string &header = headeross.str(); \ 00220 THYRA_ASSERT_LHS_ARG(header,Y); \ 00221 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_RANGE,*(Y)->space()); \ 00222 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_DOMAIN,*(X).space()); \ 00223 } 00224 00225 00238 #define THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(FUNC_NAME,M,M_T,X,Y) \ 00239 { \ 00240 std::ostringstream headeross; \ 00241 headeross \ 00242 << FUNC_NAME << ":\n\n" \ 00243 << "Spaces check failed for " \ 00244 << #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << " * " \ 00245 << #X << " and " << #Y << ":\n\n"; \ 00246 const std::string &header = headeross.str(); \ 00247 THYRA_ASSERT_LHS_ARG(header,Y); \ 00248 THYRA_ASSERT_VEC_SPACES(header,*(X).domain(),*(Y)->domain()); \ 00249 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_RANGE,*(Y)->range()); \ 00250 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_DOMAIN,*(X).range()); \ 00251 } 00252 00253 00254 namespace Thyra { 00255 00256 00257 template<class Scalar> 00258 void assertLinearOpPlusLinearOpNames( 00259 const std::string &funcName, 00260 const LinearOpBase<Scalar> &M1, const EOpTransp M1_trans_in, const std::string &M1_name, 00261 const LinearOpBase<Scalar> &M2, const EOpTransp M2_trans_in, const std::string &M2_name 00262 ) 00263 { 00264 const EOpTransp M1_trans = real_trans(M1_trans_in); 00265 const EOpTransp M2_trans = real_trans(M2_trans_in); 00266 std::ostringstream headeross; 00267 headeross 00268 << funcName << ":\n\n" 00269 << "Spaces check failed for " 00270 << "(" << M1_name << ")" << ( M1_trans == NOTRANS ? "" : "^T" ) 00271 << " + " 00272 << "(" << M2_name << ")" << ( M2_trans == NOTRANS ? "" : "^T" ) 00273 << " where:\n\n" 00274 << " " << M1_name << ": " << M1.description() << "\n\n" 00275 << " " << M2_name << ": " << M2.description(); 00276 const std::string &header = headeross.str(); 00277 if ( M1_trans == M2_trans ) { 00278 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00279 *M1.range(), M1_name + ".range()", 00280 *M2.range(), M2_name + ".range()" ); 00281 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00282 *M1.domain(), M1_name + ".domain()", 00283 *M2.domain(), M2_name + ".domain()" ); 00284 } 00285 else { // M1_trans != M2_trans 00286 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00287 *M1.domain(), M1_name + ".domain()", 00288 *M2.range(), M2_name + ".range()" ); 00289 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00290 *M1.range(), M1_name + ".range()", 00291 *M2.domain(), M2_name + ".domain()" ); 00292 } 00293 } 00294 00295 00296 template<class Scalar> 00297 void assertLinearOpTimesLinearOpNames( 00298 const std::string &funcName, 00299 const LinearOpBase<Scalar> &M1, const EOpTransp M1_trans_in, const std::string &M1_name, 00300 const LinearOpBase<Scalar> &M2, const EOpTransp M2_trans_in, const std::string &M2_name 00301 ) 00302 { 00303 const EOpTransp M1_trans = real_trans(M1_trans_in); 00304 const EOpTransp M2_trans = real_trans(M2_trans_in); 00305 std::ostringstream headeross; 00306 headeross 00307 << funcName << ":\n\n" 00308 << "Spaces check failed for " 00309 << "(" << M1_name << ")" << ( M1_trans == NOTRANS ? "" : "^T" ) 00310 << " * " 00311 << "(" << M2_name << ")" << ( M2_trans == NOTRANS ? "" : "^T" ) 00312 << " where:\n\n" 00313 << " " << M1_name << ": " << M1.description() << "\n\n" 00314 << " " << M2_name << ": " << M2.description(); 00315 const std::string &header = headeross.str(); 00316 if ( M1_trans == NOTRANS && M2_trans == NOTRANS ) { 00317 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00318 *M1.domain(), M1_name + ".domain()", 00319 *M2.range(), M2_name + ".range()" ); 00320 } 00321 else if ( M1_trans == NOTRANS && M2_trans == TRANS ) { 00322 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00323 *M1.domain(), M1_name + ".domain()", 00324 *M2.domain(), M2_name + ".domain()" ); 00325 } 00326 else if ( M1_trans == TRANS && M2_trans == NOTRANS ) { 00327 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00328 *M1.domain(), M1_name + ".range()", 00329 *M2.range(), M2_name + ".range()" ); 00330 } 00331 else if ( M1_trans == TRANS && M2_trans == TRANS ) { 00332 THYRA_ASSERT_VEC_SPACES_NAMES( header, 00333 *M1.domain(), M1_name + ".range()", 00334 *M2.range(), M2_name + ".domain()" ); 00335 } 00336 else { 00337 TEST_FOR_EXCEPTION( true, std::logic_error, 00338 header << "\n\n" << "Error, invalid value for trasponse enums!" ); 00339 } 00340 } 00341 00342 00343 } // namespace Thyra 00344 00345 00350 #define THYRA_ASSERT_LINEAR_OP_PLUS_LINEAR_OP_SPACES_NAMES(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) \ 00351 ::Thyra::assertLinearOpPlusLinearOpNames(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) 00352 00353 00358 #define THYRA_ASSERT_LINEAR_OP_TIMES_LINEAR_OP_SPACES_NAMES(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) \ 00359 ::Thyra::assertLinearOpTimesLinearOpNames(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) 00360 00361 00368 #define THYRA_ASSERT_MAT_MAT_SPACES(FUNC_NAME,M1,M1_T,M1_VS,M2,M2_T,M2_VS) \ 00369 { \ 00370 std::ostringstream headeross; \ 00371 headeross \ 00372 << FUNC_NAME << "\n" \ 00373 << "Spaces check failed for " \ 00374 << #M1 << ( (M1_T) == Thyra::NOTRANS ? "" : "^T" ) << " and " \ 00375 << #M2 << ( (M2_T) == Thyra::NOTRANS ? "" : "^T" ); \ 00376 const std::string &header = headeross.str(); \ 00377 std::ostringstream M1_VS_name, M2_VS_name; \ 00378 M1_VS_name << "(" #M1 << ( M1_T == ::Thyra::NOTRANS ? "" : "^T" ) << ")" \ 00379 << "." << ( M1_VS == ::Thyra::VS_RANGE ? "range()" : "domain()" ); \ 00380 M2_VS_name << "(" #M2 << ( M2_T == ::Thyra::NOTRANS ? "" : "^T" ) << ")" \ 00381 << "." << ( M2_VS == ::Thyra::VS_RANGE ? "range()" : "domain()" ); \ 00382 THYRA_ASSERT_VEC_SPACES_NAMES( \ 00383 header, \ 00384 ::Thyra::linear_op_op(M1,M1_T,M1_VS),M1_VS_name.str().c_str() \ 00385 ::Thyra::linear_op_op(M2,M2_T,M2_VS),M2_VS_name.str().c_str() \ 00386 ); \ 00387 } 00388 00389 00390 #endif // THYRA_ASSERT_OP_HPP
1.7.4