Thyra Version of the Day
Loading...
Searching...
No Matches
exampleImplicitlyComposedLinearOperators.cpp
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// Bring in all of the operator/vector ANA client support software
11#include "Thyra_OperatorVectorClientSupport.hpp"
12
13// Just use a default SPMD space for this example
14#include "Thyra_DefaultSpmdVectorSpace.hpp"
15
16// Some utilities from Teuchos
17#include "Teuchos_CommandLineProcessor.hpp"
18#include "Teuchos_VerboseObject.hpp"
19#include "Teuchos_VerbosityLevelCommandLineProcessorHelpers.hpp"
20#include "Teuchos_Time.hpp"
21#include "Teuchos_StandardCatchMacros.hpp"
22#include "Teuchos_as.hpp"
23#include "Teuchos_GlobalMPISession.hpp"
24
25
68template<class Scalar>
69int exampleImplicitlyComposedLinearOperators(
70 const int n0,
71 const int n1,
72 const int n2,
74 const Teuchos::EVerbosityLevel verbLevel,
76 const bool testAdjoint
77 )
78{
79
80 // Using and other declarations
82 using Teuchos::as;
83 using Teuchos::RCP;
84 using Teuchos::OSTab;
89 using Thyra::defaultSpmdVectorSpace;
90 using Thyra::randomize;
91 using Thyra::identity;
92 using Thyra::diagonal;
93 using Thyra::multiply;
94 using Thyra::add;
95 using Thyra::subtract;
96 using Thyra::scale;
97 using Thyra::adjoint;
98 using Thyra::block1x2;
99 using Thyra::block2x2;
100 using Thyra::block2x2;
101
102 out << "\n***"
103 << "\n*** Demonstrating building linear operators for scalar type "
104 << ST::name()
105 << "\n***\n";
106
107 OSTab tab(out);
108
109 //
110 // A) Set up the basic objects and other inputs to build the implicitly
111 // composed linear operators.
112 //
113
114 // Create serial vector spaces in this case
115 const RCP<const VectorSpaceBase<Scalar> >
116 space0 = defaultSpmdVectorSpace<Scalar>(n0),
117 space1 = defaultSpmdVectorSpace<Scalar>(n1),
118 space2 = defaultSpmdVectorSpace<Scalar>(n2);
119
120 // Create the component linear operators first as multi-vectors
121 const RCP<MultiVectorBase<Scalar> >
122 mvA = createMembers(space2, n0, "A"),
123 mvB = createMembers(space0, n2, "B"),
124 mvC = createMembers(space0, n0, "C"),
125 mvE = createMembers(space0, n1, "E"),
126 mvF = createMembers(space0, n1, "F"),
127 mvJ = createMembers(space2, n1, "J"),
128 mvK = createMembers(space1, n2, "K"),
129 mvL = createMembers(space2, n1, "L"),
130 mvN = createMembers(space0, n1, "N"),
131 mvP = createMembers(space2, n1, "P"),
132 mvQ = createMembers(space0, n2, "Q");
133
134 // Create the vector diagonal for D
135 const RCP<VectorBase<Scalar> > d = createMember(space2);
136
137 // Get the constants
138 const Scalar
139 one = 1.0,
140 beta = 2.0,
141 gamma = 3.0,
142 eta = 4.0;
143
144 // Randomize the values in the Multi-Vector
145 randomize( -one, +one, mvA.ptr() );
146 randomize( -one, +one, mvB.ptr() );
147 randomize( -one, +one, mvC.ptr() );
148 randomize( -one, +one, d.ptr() );
149 randomize( -one, +one, mvE.ptr() );
150 randomize( -one, +one, mvF.ptr() );
151 randomize( -one, +one, mvJ.ptr() );
152 randomize( -one, +one, mvK.ptr() );
153 randomize( -one, +one, mvL.ptr() );
154 randomize( -one, +one, mvN.ptr() );
155 randomize( -one, +one, mvP.ptr() );
156 randomize( -one, +one, mvQ.ptr() );
157
158 // Get the linear operator forms of the basic component linear operators
159 const RCP<const LinearOpBase<Scalar> >
160 A = mvA,
161 B = mvB,
162 C = mvC,
163 E = mvE,
164 F = mvF,
165 J = mvJ,
166 K = mvK,
167 L = mvL,
168 N = mvN,
169 P = mvP,
170 Q = mvQ;
171
172 out << describe(*A, verbLevel);
173 out << describe(*B, verbLevel);
174 out << describe(*C, verbLevel);
175 out << describe(*E, verbLevel);
176 out << describe(*F, verbLevel);
177 out << describe(*J, verbLevel);
178 out << describe(*K, verbLevel);
179 out << describe(*L, verbLevel);
180 out << describe(*N, verbLevel);
181 out << describe(*P, verbLevel);
182 out << describe(*Q, verbLevel);
183
184 //
185 // B) Create the composed linear operators
186 //
187
188 // I
189 const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I");
190
191 // D = diag(d)
192 const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D");
193
194 // M00 = [ gama*B*A + C, E + F ] ^H
195 // [ J^H * A, I ]
196 const RCP<const LinearOpBase<Scalar> > M00 =
197 adjoint(
198 block2x2(
199 add( scale(gamma,multiply(B,A)), C ), add( E, F ),
200 multiply(adjoint(J),A), I
201 ),
202 "M00"
203 );
204
205 out << "\nM00 = " << describe(*M00, verbLevel);
206
207 // M01 = beta * [ Q ]
208 // [ K ]
209 const RCP<const LinearOpBase<Scalar> > M01 =
210 scale(
211 beta,
212 block2x1( Q, K ),
213 "M01"
214 );
215
216 out << "\nM01 = " << describe(*M01, verbLevel);
217
218 // M10 = [ L * N^H, eta*P ]
219 const RCP<const LinearOpBase<Scalar> > M10 =
220 block1x2(
221 multiply(L,adjoint(N)), scale(eta,P),
222 "M10"
223 );
224
225 out << "\nM10 = " << describe(*M10, verbLevel);
226
227 // M11 = D - Q^H*Q
228 const RCP<const LinearOpBase<Scalar> > M11 =
229 subtract( D, multiply(adjoint(Q),Q), "M11" );
230
231 out << "\nM11 = " << describe(*M11, verbLevel);
232
233
234 // M = [ M00, M01 ]
235 // [ M10, M11 ]
236 const RCP<const LinearOpBase<Scalar> > M =
237 block2x2(
238 M00, M01,
239 M10, M11,
240 "M"
241 );
242
243 out << "\nM = " << describe(*M, verbLevel);
244
245
246 //
247 // C) Test the final composed operator
248 //
249
250 Thyra::LinearOpTester<Scalar> linearOpTester;
251 linearOpTester.set_all_error_tol(errorTol);
252 linearOpTester.check_adjoint(testAdjoint);
253 if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH))
254 linearOpTester.show_all_tests(true);
255 if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME))
256 linearOpTester.dump_all(true);
257
258 const bool result = linearOpTester.check(*M, Teuchos::inOutArg(out));
259
260 return result;
261
262}
263
264
265//
266// Main driver program
267//
268int main( int argc, char *argv[] )
269{
270
272
273 bool success = true;
274 bool result;
275
276 Teuchos::GlobalMPISession mpiSession(&argc,&argv);
277 // Above is needed to run in an MPI build with some MPI implementations
278
281
282 try {
283
284 //
285 // Read in command-line options
286 //
287
288 CommandLineProcessor clp;
289 clp.throwExceptions(false);
290 clp.addOutputSetupOptions(true);
291
292 int n0 = 2;
293 clp.setOption( "n0", &n0 );
294
295 int n1 = 3;
296 clp.setOption( "n1", &n1 );
297
298 int n2 = 4;
299 clp.setOption( "n2", &n2 );
300
302 setVerbosityLevelOption( "verb-level", &verbLevel,
303 "Top-level verbosity level. By default, this gets deincremented as you go deeper into numerical objects.",
304 &clp );
305
306 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
307 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
308
309#if defined(HAVE_TEUCHOS_INST_FLOAT)
310 // Run using float
311 result = exampleImplicitlyComposedLinearOperators<float>(
312 n0, n1, n2, *out, verbLevel, 1e-5, true );
313 if (!result) success = false;
314#endif
315
316 // Run using double
317 result = exampleImplicitlyComposedLinearOperators<double>(
318 n0, n1, n2, *out, verbLevel, 1e-12, true );
319 if (!result) success = false;
320
321#if defined(HAVE_TEUCHOS_INST_COMPLEX_FLOAT) && defined(HAVE_TEUCHOS_INST_FLOAT)
322 // Run using std::complex<float>
323 result = exampleImplicitlyComposedLinearOperators<std::complex<float> >(
324 n0, n1, n2, *out, verbLevel, 1e-5, false );
325 if (!result) success = false;
326 // 2007/11/02: rabartl: Above, I skip the test of the adjoint since it
327 // fails but a lot. On my machine, the relative error is:
328 // rel_err((-3.00939,-0.836347),(-0.275689,1.45244)) = 1.14148.
329 // Since this works just fine for the next complex<double> case, I am
330 // going to just skip this test.
331#endif
332
333#if defined(HAVE_TEUCHOS_INST_COMPLEX_DOUBLE)
334 // Run using std::complex<double>
335 result = exampleImplicitlyComposedLinearOperators<std::complex<double> >(
336 n0, n1, n2, *out, verbLevel, 1e-12, true );
337 if (!result) success = false;
338#endif
339
340#ifdef HAVE_TEUCHOS_GNU_MP
341
342 // Run using mpf_class
343 result = exampleImplicitlyComposedLinearOperators<mpf_class>(
344 n0, n1, n2, *out, verbLevel, 1e-20, true );
345 if (!result) success = false;
346
347#endif // HAVE_TEUCHOS_GNU_MP
348
349 }
350 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success)
351
352 if(success)
353 *out << "\nCongratulations! All of the tests checked out!\n";
354 else
355 *out << "\nOh no! At least one of the tests failed!\n";
356
357 return success ? 0 : 1;
358
359} // end main()
static RCP< FancyOStream > getDefaultOStream()
Base class for all linear operators.
Testing class for LinearOpBase.
void set_all_error_tol(const ScalarMag error_tol)
Set all the error tolerances to the same value.
bool check(const LinearOpBase< Scalar > &op, const Ptr< MultiVectorRandomizerBase< Scalar > > &rangeRandomizer, const Ptr< MultiVectorRandomizerBase< Scalar > > &domainRandomizer, const Ptr< FancyOStream > &out) const
Check a linear operator.
Interface for a collection of column vectors called a multi-vector.
Abstract interface for finite-dimensional dense vectors.
Abstract interface for objects that represent a space for vectors.
TypeTo as(const TypeFrom &t)
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
basic_OSTab< char > OSTab