Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_AssertOp.hpp
1// @HEADER
2// *****************************************************************************
3// Thyra: Interfaces and Support for Abstract Numerical Algorithms
4//
5// Copyright 2004 NTESS and the Thyra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef THYRA_ASSERT_OP_HPP
11#define THYRA_ASSERT_OP_HPP
12
13
14#include "Thyra_OperatorVectorTypes.hpp"
15#include "Thyra_VectorSpaceBase.hpp"
16#include "Thyra_VectorBase.hpp"
17#include "Thyra_LinearOpBase.hpp"
18#include "Teuchos_Assert.hpp"
19
20
21namespace Thyra {
22
23
24/* Utility struct for dumping vector space names, dimension etc.
25 */
26template<class Scalar>
27struct dump_vec_spaces_t {
28public:
29 dump_vec_spaces_t(
30 const Thyra::VectorSpaceBase<Scalar>& _vec_space1,
31 const std::string &_vec_space1_name,
32 const Thyra::VectorSpaceBase<Scalar>& _vec_space2,
33 const std::string &_vec_space2_name
34 )
35 :vec_space1(_vec_space1),vec_space1_name(_vec_space1_name)
36 ,vec_space2(_vec_space2),vec_space2_name(_vec_space2_name)
37 {}
38 const Thyra::VectorSpaceBase<Scalar> &vec_space1;
39 const std::string vec_space1_name;
40 const Thyra::VectorSpaceBase<Scalar> &vec_space2;
41 const std::string vec_space2_name;
42}; // end dum_vec_spaces
43
44
45/* Utility function for dumping vector space names, dimension etc.
46 */
47template<class Scalar>
48inline dump_vec_spaces_t<Scalar> dump_vec_spaces(
49 const Thyra::VectorSpaceBase<Scalar>& vec_space1,
50 const std::string &vec_space1_name,
51 const Thyra::VectorSpaceBase<Scalar>& vec_space2,
52 const std::string &vec_space2_name
53 )
54{
55 return dump_vec_spaces_t<Scalar>(
56 vec_space1,vec_space1_name,vec_space2,vec_space2_name);
57}
58
59
60// Notice!!!!!!! Place a breakpoint in following function in order to halt the
61// program just before an exception is thrown!
62
63
64/* Utility ostream operator for dumping vector space names, dimension etc.
65 */
66template<class Scalar>
67std::ostream& operator<<( std::ostream& o, const dump_vec_spaces_t<Scalar>& d )
68{
69
70 using Teuchos::OSTab;
72 o << "Error, the following vector spaces are not compatible:\n\n";
73 OSTab(o).o()
74 << d.vec_space1_name << " : "
75 << Teuchos::describe(d.vec_space1,verbLevel);
76 o << "\n";
77 OSTab(o).o()
78 << d.vec_space2_name << " : "
79 << Teuchos::describe(d.vec_space2,verbLevel);
80 return o;
81}
82
83
84/* Utility enum for selecting domain or range spaces
85 */
86enum EM_VS { VS_RANGE, VS_DOMAIN };
87
88
93template<class Scalar>
96 Thyra::EOpTransp M_trans,
97 EM_VS M_VS
98 )
99{
100 if(real_trans(M_trans) == NOTRANS && M_VS == VS_RANGE)
101 return *M.range();
102 if(real_trans(M_trans) == TRANS && M_VS == VS_RANGE)
103 return *M.domain();
104 if(real_trans(M_trans) == NOTRANS && M_VS == VS_DOMAIN)
105 return *M.domain();
106 // real_trans(M_trans) == TRANS && M_VS == VS_DOMAIN
107 return *M.range();
108}
109
110
111} // end namespace Thyra
112
113
118#define THYRA_ASSERT_LHS_ARG(FUNC_NAME,LHS_ARG) \
119 TEUCHOS_TEST_FOR_EXCEPTION( \
120 (&*LHS_ARG) == NULL, std::invalid_argument, \
121 FUNC_NAME << " : Error!" \
122 );
123
124
125// Notice!!!!!!! Setting a breakpoint at the line number that is printed by this macro
126// and then trying to set the condition !isCompatible does not work (at least not
127// in gdb).
128
129
134#define THYRA_ASSERT_VEC_SPACES_NAMES(FUNC_NAME,VS1,VS1_NAME,VS2,VS2_NAME) \
135{ \
136 const bool l_isCompatible = (VS1).isCompatible(VS2); \
137 TEUCHOS_TEST_FOR_EXCEPTION( \
138 !l_isCompatible, ::Thyra::Exceptions::IncompatibleVectorSpaces, \
139 FUNC_NAME << "\n\n" \
140 << ::Thyra::dump_vec_spaces(VS1,VS1_NAME,VS2,VS2_NAME) \
141 ) \
142}
143
144
156#define THYRA_ASSERT_VEC_SPACES(FUNC_NAME,VS1,VS2)\
157THYRA_ASSERT_VEC_SPACES_NAMES(FUNC_NAME,VS1,#VS1,VS2,#VS2)
158
159
167#define THYRA_ASSERT_MAT_VEC_SPACES(FUNC_NAME,M,M_T,M_VS,VS) \
168{ \
169 std::ostringstream M_VS_name; \
170 M_VS_name << "(" #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << ")" \
171 << "." << ( (M_VS) == Thyra::VS_RANGE ? "range()" : "domain()" ); \
172 THYRA_ASSERT_VEC_SPACES_NAMES( \
173 FUNC_NAME, \
174 ::Thyra::linear_op_op(M,M_T,M_VS),M_VS_name.str().c_str(), \
175 (VS),#VS \
176 ) \
177}
178
179
192#define THYRA_ASSERT_LINEAR_OP_VEC_APPLY_SPACES(FUNC_NAME,M,M_T,X,Y) \
193 { \
194 std::ostringstream headeross; \
195 headeross \
196 << FUNC_NAME << ":\n" \
197 << "Spaces check failed for " \
198 << #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << " * " \
199 << #X << " and " << #Y; \
200 const std::string &header = headeross.str(); \
201 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_RANGE,*(Y)->space()); \
202 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_DOMAIN,*(X).space()); \
203 }
204
205
218#define THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(FUNC_NAME,M,M_T,X,Y) \
219 { \
220 std::ostringstream headeross; \
221 headeross \
222 << FUNC_NAME << ":\n\n" \
223 << "Spaces check failed for " \
224 << #M << ( (M_T) == Thyra::NOTRANS ? "" : "^T" ) << " * " \
225 << #X << " and " << #Y << ":\n\n"; \
226 const std::string &header = headeross.str(); \
227 THYRA_ASSERT_VEC_SPACES(header,*(X).domain(),*(Y)->domain()); \
228 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_RANGE,*(Y)->range()); \
229 THYRA_ASSERT_MAT_VEC_SPACES(header,M,M_T,::Thyra::VS_DOMAIN,*(X).range()); \
230 }
231
232
233namespace Thyra {
234
235
236template<class Scalar>
237void assertLinearOpPlusLinearOpNames(
238 const std::string &funcName,
239 const LinearOpBase<Scalar> &M1, const EOpTransp M1_trans_in, const std::string &M1_name,
240 const LinearOpBase<Scalar> &M2, const EOpTransp M2_trans_in, const std::string &M2_name
241 )
242{
243 const EOpTransp M1_trans = real_trans(M1_trans_in);
244 const EOpTransp M2_trans = real_trans(M2_trans_in);
245 std::ostringstream headeross;
246 headeross
247 << funcName << ":\n\n"
248 << "Spaces check failed for "
249 << "(" << M1_name << ")" << ( M1_trans == NOTRANS ? "" : "^T" )
250 << " + "
251 << "(" << M2_name << ")" << ( M2_trans == NOTRANS ? "" : "^T" )
252 << " where:\n\n"
253 << " " << M1_name << ": " << M1.description() << "\n\n"
254 << " " << M2_name << ": " << M2.description();
255 const std::string &header = headeross.str();
256 if ( M1_trans == M2_trans ) {
258 *M1.range(), M1_name + ".range()",
259 *M2.range(), M2_name + ".range()" );
261 *M1.domain(), M1_name + ".domain()",
262 *M2.domain(), M2_name + ".domain()" );
263 }
264 else { // M1_trans != M2_trans
266 *M1.domain(), M1_name + ".domain()",
267 *M2.range(), M2_name + ".range()" );
269 *M1.range(), M1_name + ".range()",
270 *M2.domain(), M2_name + ".domain()" );
271 }
272}
273
274
275template<class Scalar>
276void assertLinearOpTimesLinearOpNames(
277 const std::string &funcName,
278 const LinearOpBase<Scalar> &M1, const EOpTransp M1_trans_in, const std::string &M1_name,
279 const LinearOpBase<Scalar> &M2, const EOpTransp M2_trans_in, const std::string &M2_name
280 )
281{
282 const EOpTransp M1_trans = real_trans(M1_trans_in);
283 const EOpTransp M2_trans = real_trans(M2_trans_in);
284 std::ostringstream headeross;
285 headeross
286 << funcName << ":\n\n"
287 << "Spaces check failed for "
288 << "(" << M1_name << ")" << ( M1_trans == NOTRANS ? "" : "^T" )
289 << " * "
290 << "(" << M2_name << ")" << ( M2_trans == NOTRANS ? "" : "^T" )
291 << " where:\n\n"
292 << " " << M1_name << ": " << M1.description() << "\n\n"
293 << " " << M2_name << ": " << M2.description();
294 const std::string &header = headeross.str();
295 if ( M1_trans == NOTRANS && M2_trans == NOTRANS ) {
297 *M1.domain(), M1_name + ".domain()",
298 *M2.range(), M2_name + ".range()" );
299 }
300 else if ( M1_trans == NOTRANS && M2_trans == TRANS ) {
302 *M1.domain(), M1_name + ".domain()",
303 *M2.domain(), M2_name + ".domain()" );
304 }
305 else if ( M1_trans == TRANS && M2_trans == NOTRANS ) {
307 *M1.domain(), M1_name + ".range()",
308 *M2.range(), M2_name + ".range()" );
309 }
310 else if ( M1_trans == TRANS && M2_trans == TRANS ) {
312 *M1.domain(), M1_name + ".range()",
313 *M2.range(), M2_name + ".domain()" );
314 }
315 else {
316 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error,
317 header << "\n\n" << "Error, invalid value for trasponse enums!" );
318 }
319}
320
321
322} // namespace Thyra
323
324
329#define THYRA_ASSERT_LINEAR_OP_PLUS_LINEAR_OP_SPACES_NAMES(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) \
330 ::Thyra::assertLinearOpPlusLinearOpNames(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N)
331
332
337#define THYRA_ASSERT_LINEAR_OP_TIMES_LINEAR_OP_SPACES_NAMES(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N) \
338 ::Thyra::assertLinearOpTimesLinearOpNames(FUNC_NAME,M1,M1_T,M1_N,M2,M2_T,M2_N)
339
340
347#define THYRA_ASSERT_MAT_MAT_SPACES(FUNC_NAME,M1,M1_T,M1_VS,M2,M2_T,M2_VS) \
348 { \
349 std::ostringstream headeross; \
350 headeross \
351 << FUNC_NAME << "\n" \
352 << "Spaces check failed for " \
353 << #M1 << ( (M1_T) == Thyra::NOTRANS ? "" : "^T" ) << " and " \
354 << #M2 << ( (M2_T) == Thyra::NOTRANS ? "" : "^T" ); \
355 const std::string &header = headeross.str(); \
356 std::ostringstream M1_VS_name, M2_VS_name; \
357 M1_VS_name << "(" #M1 << ( M1_T == ::Thyra::NOTRANS ? "" : "^T" ) << ")" \
358 << "." << ( M1_VS == ::Thyra::VS_RANGE ? "range()" : "domain()" ); \
359 M2_VS_name << "(" #M2 << ( M2_T == ::Thyra::NOTRANS ? "" : "^T" ) << ")" \
360 << "." << ( M2_VS == ::Thyra::VS_RANGE ? "range()" : "domain()" ); \
361 THYRA_ASSERT_VEC_SPACES_NAMES( \
362 header, \
363 ::Thyra::linear_op_op(M1,M1_T,M1_VS),M1_VS_name.str().c_str() \
364 ::Thyra::linear_op_op(M2,M2_T,M2_VS),M2_VS_name.str().c_str() \
365 ); \
366 }
367
368
369#endif // THYRA_ASSERT_OP_HPP
Base class for all linear operators.
virtual RCP< const VectorSpaceBase< Scalar > > range() const =0
Return a smart pointer for the range space for this operator.
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
Return a smart pointer for the domain space for this operator.
Abstract interface for objects that represent a space for vectors.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define THYRA_ASSERT_VEC_SPACES_NAMES(FUNC_NAME, VS1, VS1_NAME, VS2, VS2_NAME)
Helper assertion macro.
const Thyra::VectorSpaceBase< Scalar > & linear_op_op(const Thyra::LinearOpBase< Scalar > &M, Thyra::EOpTransp M_trans, EM_VS M_VS)
Utility function for selecting domain or range spaces.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
EOpTransp real_trans(EOpTransp transp)
Return NOTRANS or TRANS for real scalar valued operators and this also is used for determining struct...
@ TRANS
Use the transposed operator.
@ NOTRANS
Use the non-transposed operator.
basic_OSTab< char > OSTab
std::ostream & operator<<(std::ostream &out, const SerialBandDenseMatrixPrinter< OrdinalType, ScalarType > printer)