00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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 };
00062
00063
00064
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
00080
00081
00082
00083
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
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
00126 return *M.range();
00127 }
00128
00129
00130 }
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
00145
00146
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 {
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 }
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