Thyra_AssertOp.hpp

Go to the documentation of this file.
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::ETransp 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 isCompatible = (VS1).isCompatible(VS2); \
00156   TEST_FOR_EXCEPTION( \
00157     !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 ETransp M1_trans_in, const std::string &M1_name,
00261   const LinearOpBase<Scalar> &M2, const ETransp M2_trans_in, const std::string &M2_name
00262   )
00263 {
00264   const ETransp M1_trans = real_trans(M1_trans_in);
00265   const ETransp 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 ETransp M1_trans_in, const std::string &M1_name,
00300   const LinearOpBase<Scalar> &M2, const ETransp M2_trans_in, const std::string &M2_name
00301   )
00302 {
00303   const ETransp M1_trans = real_trans(M1_trans_in);
00304   const ETransp 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

Generated on Tue Oct 20 12:47:25 2009 for Thyra Package Browser (Single Doxygen Collection) by doxygen 1.4.7