bool runCgSolveExample( const int dim, const Scalar diagScale, const bool symOp, const bool showAllTests, const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance, const int maxNumIters ) { using Teuchos::as; using Teuchos::null; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::OSTab; typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::multiply; using Thyra::scale; typedef typename ST::magnitudeType ScalarMag; bool success = true; bool result; Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); *out << "\n***\n*** Running silly CG solver using scalar type = \'" << ST::name() << "\' ...\n***\n"; Teuchos::Time timer(""); timer.start(true); // // (A) Setup a simple linear system with tridiagonal operator: // // [ a*2 -1 ] // [ -r(1) a*2 -1 ] // A = [ . . . ] // [ -r(n-2) a*2 -1 ] // [ -r(n-1) a*2 ] // // (A.1) Create the tridiagonal matrix operator *out << "\nConstructing tridiagonal matrix A of dimension = " << dim << " and diagonal multiplier = " << diagScale << " ...\n"; Teuchos::Array<Scalar> lower(dim-1), diag(dim), upper(dim-1); const Scalar up = -ST::one(), diagTerm = as<Scalar>(2.0) * diagScale * ST::one(), low = -(symOp ? ST::one() : ST::random()); int k = 0; // First row diag[k] = diagTerm; upper[k] = up; // Middle rows for( k = 1; k < dim - 1; ++k ) { lower[k-1] = low; diag[k] = diagTerm; upper[k] = up; } // Last row lower[k-1] = low; diag[k] = diagTerm; RCP<const Thyra::LinearOpBase<Scalar> > A = rcp(new ExampleTridiagSerialLinearOp<Scalar>(dim, lower, diag, upper)); // (A.2) Testing the linear operator constructed linear operator *out << "\nTesting the constructed linear operator A ...\n"; Thyra::LinearOpTester<Scalar> linearOpTester; linearOpTester.enable_all_tests(false); linearOpTester.check_linear_properties(true); linearOpTester.set_all_error_tol(tolerance); linearOpTester.set_all_warning_tol(1e-2*tolerance); linearOpTester.show_all_tests(showAllTests); result = linearOpTester.check(*A, out.ptr()); if(!result) success = false; // (A.3) Create RHS vector b and set to a random value RCP<Thyra::VectorBase<Scalar> > b = createMember(A->range()); Thyra::seed_randomize<Scalar>(0); Thyra::randomize( -ST::one(), +ST::one(), b.ptr() ); // (A.4) Create LHS vector x and set to zero RCP<Thyra::VectorBase<Scalar> > x = createMember(A->domain()); Thyra::V_S( x.ptr(), ST::zero() ); // (A.5) Create the final linear system if(!symOp) { *out << "\nSetting up normal equations for unsymmetric system A^H*(A*x-b) => new A*x = b ...\n"; // A^H*A RCP<const Thyra::LinearOpBase<Scalar> > AtA = multiply(adjoint(A), A); // A^H*b RCP<Thyra::VectorBase<Scalar> > nb = createMember(AtA->range()); Thyra::apply<Scalar>(*A, Thyra::CONJTRANS, *b, nb.ptr()); A = AtA; b = nb; } // (A.6) Testing the linear operator used with the solve *out << "\nTesting the linear operator used with the solve ...\n"; linearOpTester.check_for_symmetry(true); result = linearOpTester.check(*A, out.ptr()); if(!result) success = false; // // (B) Solve the linear system with the silly CG solver // *out << "\nSolving the linear system with sillyCgSolve(...) ...\n"; { OSTab tab2(out); result = sillyCgSolve(*A, *b, maxNumIters, tolerance, x.ptr(), *out); } if(!result) success = false; // // (C) Check that the linear system was solved to the specified tolerance // RCP<Thyra::VectorBase<Scalar> > r = createMember(A->range()); // r = b Thyra::V_V(r.ptr(), *b); // r = -A*x + r Thyra::apply<Scalar>(*A, Thyra::NOTRANS, *x, r.ptr(), -ST::one(), ST::one()); const ScalarMag r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b); const ScalarMag rel_err = r_nrm/b_nrm, relaxTol = 10.0*tolerance; result = rel_err <= relaxTol; if(!result) success = false; *out << "\nChecking the residual ourselves ...\n"; { OSTab tab(out); *out << "\n||b-A*x||/||b|| = "<<r_nrm<<"/"<<b_nrm<<" = "<<rel_err<<(result?" <= ":" > ") <<"10.0*tolerance = "<<relaxTol<<": "<<(result?"passed":"failed")<<std::endl; } timer.stop(); *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n"; return success; } // end runCgSolveExample()
int exampleImplicitlyComposedLinearOperators( const int n0, const int n1, const int n2, Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel, typename Teuchos::ScalarTraits<Scalar>::magnitudeType errorTol, const bool testAdjoint ) { // Using and other declarations typedef Teuchos::ScalarTraits<Scalar> ST; using Teuchos::as; using Teuchos::RCP; using Teuchos::OSTab; using Thyra::VectorSpaceBase; using Thyra::VectorBase; using Thyra::MultiVectorBase; using Thyra::LinearOpBase; using Thyra::defaultSpmdVectorSpace; using Thyra::randomize; using Thyra::identity; using Thyra::diagonal; using Thyra::multiply; using Thyra::add; using Thyra::subtract; using Thyra::scale; using Thyra::adjoint; using Thyra::block1x2; using Thyra::block2x2; using Thyra::block2x2; out << "\n***" << "\n*** Demonstrating building linear operators for scalar type " << ST::name() << "\n***\n"; OSTab tab(out); // // A) Set up the basic objects and other inputs to build the implicitly // composed linear operators. // // Create serial vector spaces in this case const RCP<const VectorSpaceBase<Scalar> > space0 = defaultSpmdVectorSpace<Scalar>(n0), space1 = defaultSpmdVectorSpace<Scalar>(n1), space2 = defaultSpmdVectorSpace<Scalar>(n2); // Create the component linear operators first as multi-vectors const RCP<MultiVectorBase<Scalar> > mvA = createMembers(space2, n0, "A"), mvB = createMembers(space0, n2, "B"), mvC = createMembers(space0, n0, "C"), mvE = createMembers(space0, n1, "E"), mvF = createMembers(space0, n1, "F"), mvJ = createMembers(space2, n1, "J"), mvK = createMembers(space1, n2, "K"), mvL = createMembers(space2, n1, "L"), mvN = createMembers(space0, n1, "N"), mvP = createMembers(space2, n1, "P"), mvQ = createMembers(space0, n2, "Q"); // Create the vector diagonal for D const RCP<VectorBase<Scalar> > d = createMember(space2); // Get the constants const Scalar one = 1.0, beta = 2.0, gamma = 3.0, eta = 4.0; // Randomize the values in the Multi-Vector randomize( -one, +one, mvA.ptr() ); randomize( -one, +one, mvB.ptr() ); randomize( -one, +one, mvC.ptr() ); randomize( -one, +one, d.ptr() ); randomize( -one, +one, mvE.ptr() ); randomize( -one, +one, mvF.ptr() ); randomize( -one, +one, mvJ.ptr() ); randomize( -one, +one, mvK.ptr() ); randomize( -one, +one, mvL.ptr() ); randomize( -one, +one, mvN.ptr() ); randomize( -one, +one, mvP.ptr() ); randomize( -one, +one, mvQ.ptr() ); // Get the linear operator forms of the basic component linear operators const RCP<const LinearOpBase<Scalar> > A = mvA, B = mvB, C = mvC, E = mvE, F = mvF, J = mvJ, K = mvK, L = mvL, N = mvN, P = mvP, Q = mvQ; out << describe(*A, verbLevel); out << describe(*B, verbLevel); out << describe(*C, verbLevel); out << describe(*E, verbLevel); out << describe(*F, verbLevel); out << describe(*J, verbLevel); out << describe(*K, verbLevel); out << describe(*L, verbLevel); out << describe(*N, verbLevel); out << describe(*P, verbLevel); out << describe(*Q, verbLevel); // // B) Create the composed linear operators // // I const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I"); // D = diag(d) const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D"); // M00 = [ gama*B*A + C, E + F ] ^H // [ J^H * A, I ] const RCP<const LinearOpBase<Scalar> > M00 = adjoint( block2x2( add( scale(gamma,multiply(B,A)), C ), add( E, F ), multiply(adjoint(J),A), I ), "M00" ); out << "\nM00 = " << describe(*M00, verbLevel); // M01 = beta * [ Q ] // [ K ] const RCP<const LinearOpBase<Scalar> > M01 = scale( beta, block2x1( Q, K ), "M01" ); out << "\nM01 = " << describe(*M01, verbLevel); // M10 = [ L * N^H, eta*P ] const RCP<const LinearOpBase<Scalar> > M10 = block1x2( multiply(L,adjoint(N)), scale(eta,P), "M10" ); out << "\nM10 = " << describe(*M10, verbLevel); // M11 = D - Q^H*Q const RCP<const LinearOpBase<Scalar> > M11 = subtract( D, multiply(adjoint(Q),Q), "M11" ); out << "\nM11 = " << describe(*M11, verbLevel); // M = [ M00, M01 ] // [ M10, M11 ] const RCP<const LinearOpBase<Scalar> > M = block2x2( M00, M01, M10, M11, "M" ); out << "\nM = " << describe(*M, verbLevel); // // C) Test the final composed operator // Thyra::LinearOpTester<Scalar> linearOpTester; linearOpTester.set_all_error_tol(errorTol); linearOpTester.check_adjoint(testAdjoint); if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH)) linearOpTester.show_all_tests(true); if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME)) linearOpTester.dump_all(true); const bool result = linearOpTester.check(*M,&out); return result; }