* auto top_left_op = linear_operator(top_left);
* auto bottom_right_op = linear_operator(bottom_right);
* std::array<decltype(top_left_op), 2> operators {{top_left_op,
- * bottom_right_op}}; auto block_op = block_diagonal_operator (operators);
+ * bottom_right_op}};
+ * auto block_op = block_diagonal_operator (operators);
*
* std::vector<BlockVector<double>::size_type> block_sizes {2, 4};
* BlockVector<double> src(block_sizes);
*
* As an example, consider the following code:
* @code
- * FullMatrix<double> A1(4,4);
- * FullMatrix<double> A2(4,4);
- * FullMatrix<double> B(4,3);
- * FullMatrix<double> C(3,3);
+ * FullMatrix<double> A1(4,4);
+ * FullMatrix<double> A2(4,4);
+ * FullMatrix<double> B(4,3);
+ * FullMatrix<double> C(3,3);
*
- * BlockMatrixArray<double> block(2,2);
+ * BlockMatrixArray<double> block(2,2);
*
- * block.enter(A1,0,0);
- * block.enter(A2,0,0,2,true);
- * block.enter(B,0,1,-3.);
- * block.enter(B,0,1,-3.,true);
- * block.enter(C,1,1,1.,true);
+ * block.enter(A1,0,0);
+ * block.enter(A2,0,0,2,true);
+ * block.enter(B,0,1,-3.);
+ * block.enter(B,0,1,-3.,true);
+ * block.enter(C,1,1,1.,true);
*
- * block.print_latex(std::cout);
+ * block.print_latex(std::cout);
* @endcode
* The current function will then produce output of the following kind:
* @code
* \begin{array}{cc}
* M0+2xM1^T & -3xM2-3xM3^T\\
- * & M4^T
+ * & M4^T
* \end{array}
* @endcode
* Note how the individual blocks here are just numbered successively as
* @code
* DiagonalMatrix<LinearAlgebra::distributed::Vector<double> > diagonal_matrix;
* LinearAlgebra::distributed::Vector<double> &diagonal_vector =
- * diagonal_matrix.get_vector(); diagonal_vector.reinit(locally_owned_dofs,
+ * diagonal_matrix.get_vector();
+ * diagonal_vector.reinit(locally_owned_dofs,
* locally_relevant_dofs,
* mpi_communicator);
* @endcode
*
* A typical code snippet showing the above steps is as follows:
* @code
- * ... // set up sparse matrix A and right hand side b somehow
+ * // set up sparse matrix A and right hand side b somehow
+ * ...
*
- * // initialize filtered matrix with
- * // matrix and boundary value constraints
+ * // initialize filtered matrix with matrix and boundary value constraints
* FilteredMatrix<Vector<double> > filtered_A (A);
* filtered_A.add_constraints (boundary_values);
*
- * // set up a linear solver
+ * // set up a linear solver
* SolverControl control (1000, 1.e-10, false, false);
* GrowingVectorMemory<Vector<double> > mem;
* SolverCG<Vector<double> > solver (control, mem);
*
- * // set up a preconditioner object
+ * // set up a preconditioner object
* PreconditionJacobi<SparseMatrix<double> > prec;
* prec.initialize (A, 1.2);
* FilteredMatrix<Vector<double> > filtered_prec (prec);
* filtered_prec.add_constraints (boundary_values);
*
- * // compute modification of right hand side
+ * // compute modification of right hand side
* filtered_A.apply_constraints (b, true);
*
- * // solve for solution vector x
+ * // solve for solution vector x
* solver.solve (filtered_A, x, b, filtered_prec);
* @endcode
*
* SolverControl solver_control (1000, 1e-12);
* SolverCG<> cg (solver_control);
* cg.solve (system_matrix, solution, system_rhs,
- * IdentityMatrix(solution.size()));
+ * IdentityMatrix(solution.size()));
* @endcode
*
*
*
* A typical usage of this class would be as follows:
* @code
- * FullMatrix<double> M;
- * ... // fill matrix M with some values
+ * FullMatrix<double> M;
+ * // fill matrix M with some values
+ * ...
*
- * // now write out M:
- * MatrixOut matrix_out;
- * std::ofstream out ("M.gnuplot");
- * matrix_out.build_patches (M, "M");
- * matrix_out.write_gnuplot (out);
+ * // now write out M:
+ * MatrixOut matrix_out;
+ * std::ofstream out ("M.gnuplot");
+ * matrix_out.build_patches (M, "M");
+ * matrix_out.write_gnuplot (out);
* @endcode
* Of course, you can as well choose a different graphical output format.
* Also, this class supports any matrix, not only of type FullMatrix, as long
* SolverControl solver_control_lin (1000, 1e-10,false,false);
*
* SolverCG<vector_t> cg(solver_control_lin);
- * const auto op_shift_invert = inverse_operator(op_shift, cg,
- * PreconditionIdentity ());
+ * const auto op_shift_invert =
+ * inverse_operator(op_shift, cg, PreconditionIdentity ());
* @endcode
*
* The class is intended to be used with MPI and can work on arbitrary vector
* is made possible by the set_symmetric_mode() function. If your matrix is
* symmetric, you can use this class as follows:
* @code
- * SolverControl cn;
- * PETScWrappers::SparseDirectMUMPS solver(cn, mpi_communicator);
- * solver.set_symmetric_mode(true);
- * solver.solve(system_matrix, solution, system_rhs);
+ * SolverControl cn;
+ * PETScWrappers::SparseDirectMUMPS solver(cn, mpi_communicator);
+ * solver.set_symmetric_mode(true);
+ * solver.solve(system_matrix, solution, system_rhs);
* @endcode
*
* @note The class internally calls KSPSetFromOptions thus you are able to
* @code
* SolverControl solver_control (1000, 1e-12);
* SolverCG<> cg (solver_control);
- * cg.solve (system_matrix, solution, system_rhs,
- * PreconditionIdentity());
+ * cg.solve (system_matrix, solution, system_rhs, PreconditionIdentity());
* @endcode
*
* See the step-3 tutorial program for an example and additional explanations.
* You will usually not want to create a named object of this type, although
* possible. The most common use is like this:
* @code
- * SolverGMRES<SparseMatrix<double>,
- * Vector<double> > gmres(control,memory,500);
+ * SolverGMRES<SparseMatrix<double> Vector<double>> gmres(control,memory,500);
*
- * gmres.solve (matrix, solution, right_hand_side,
- * PreconditionUseMatrix<SparseMatrix<double>,Vector<double> >
- * (matrix,&SparseMatrix<double>::template
- * precondition_Jacobi<double>));
+ * gmres.solve(
+ * matrix, solution, right_hand_side,
+ * PreconditionUseMatrix<SparseMatrix<double>,Vector<double> >(
+ * matrix, &SparseMatrix<double>::template precondition_Jacobi<double>));
* @endcode
* This creates an unnamed object to be passed as the fourth parameter to the
* solver function of the SolverGMRES class. It assumes that the SparseMatrix
* Note that due to the default template parameters, the above example could
* be written shorter as follows:
* @code
- * ...
- * gmres.solve (matrix, solution, right_hand_side,
- * PreconditionUseMatrix<>
- * (matrix,&SparseMatrix<double>::template
- * precondition_Jacobi<double>));
+ * ...
+ * gmres.solve(
+ * matrix, solution, right_hand_side,
+ * PreconditionUseMatrix<>(
+ * matrix,&SparseMatrix<double>::template precondition_Jacobi<double>));
* @endcode
*
* @author Guido Kanschat, Wolfgang Bangerth, 1999
* // Define and initialize preconditioner:
*
* PreconditionJacobi<SparseMatrix<double> > precondition;
- * precondition.initialize (A, PreconditionJacobi<SparseMatrix<double>
- * >::AdditionalData(.6));
+ * precondition.initialize(
+ * A, PreconditionJacobi<SparseMatrix<double>>::AdditionalData(.6));
*
* solver.solve (A, x, b, precondition);
* @endcode
* // Define and initialize preconditioner
*
* PreconditionSOR<SparseMatrix<double> > precondition;
- * precondition.initialize (A, PreconditionSOR<SparseMatrix<double>
- * >::AdditionalData(.6));
+ * precondition.initialize(
+ * A, PreconditionSOR<SparseMatrix<double>>::AdditionalData(.6));
*
* solver.solve (A, x, b, precondition);
* @endcode
* @ref ConceptRelaxationType "relaxation concept".
*
* @code
- * // Declare related objects
+ * // Declare related objects
*
* SparseMatrix<double> A;
* Vector<double> x;
* // Define and initialize preconditioner
*
* PreconditionSSOR<SparseMatrix<double> > precondition;
- * precondition.initialize (A, PreconditionSSOR<SparseMatrix<double>
- * >::AdditionalData(.6));
+ * precondition.initialize(
+ * A, PreconditionSSOR<SparseMatrix<double>>::AdditionalData(.6));
*
* solver.solve (A, x, b, precondition);
* @endcode
* <tt>TPSOR(VectorType&, const VectorType&, double)</tt>.
*
* @code
- * // Declare related objects
+ * // Declare related objects
*
* SparseMatrix<double> A;
* Vector<double> x;
*
* //...fill permutation and its inverse with reasonable values
*
- * // Define and initialize preconditioner
+ * // Define and initialize preconditioner
*
* PreconditionPSOR<SparseMatrix<double> > precondition;
* precondition.initialize (A, permutation, inverse_permutation, .6);
*
* <h3>Usage</h3> The simplest use of this class is the following:
* @code
- * // generate a @p SolverControl and
- * // a @p VectorMemory
+ * // generate a @p SolverControl and a @p VectorMemory
* SolverControl control;
* VectorMemory<Vector<double> > memory;
- * // generate a solver
+ *
+ * // generate a solver
* SolverCG<SparseMatrix<double>, Vector<double> > solver(control, memory);
- * // generate a @p PreconditionSelector
+ *
+ * // generate a @p PreconditionSelector
* PreconditionSelector<SparseMatrix<double>, Vector<double> >
* preconditioning("jacobi", 1.);
- * // give a matrix whose diagonal entries
- * // are to be used for the preconditioning.
- * // Generally the matrix of the linear
- * // equation system Ax=b.
+ *
+ * // give a matrix whose diagonal entries are to be used for the
+ * // preconditioning. Generally the matrix of the linear equation system Ax=b.
* preconditioning.use_matrix(A);
- * // call the @p solve function with this
- * // preconditioning as last argument
+ *
+ * // call the @p solve function with this preconditioning as last argument
* solver.solve(A,x,b,preconditioning);
* @endcode
* The same example where also the @p SolverSelector class is used reads
* @code
- * // generate a @p SolverControl and
- * // a @p VectorMemory
+ * // generate a @p SolverControl and a @p VectorMemory
* SolverControl control;
* VectorMemory<Vector<double> > memory;
- * // generate a @p SolverSelector that
- * // calls the @p SolverCG
+ *
+ * // generate a @p SolverSelector that calls the @p SolverCG
* SolverSelector<SparseMatrix<double>, Vector<double> >
* solver_selector("cg", control, memory);
- * // generate a @p PreconditionSelector
+ *
+ * // generate a @p PreconditionSelector
* PreconditionSelector<SparseMatrix<double>, Vector<double> >
* preconditioning("jacobi", 1.);
*
* @code
* struct Functor
* {
- * void operator() (Number &value);
+ * void operator() (Number &value);
* };
* @endcode
*
* An illustration of typical usage of this operator for a fully coupled
* system is given below.
* @code
- * #include<deal.II/lac/schur_complement.h>
- *
- * // Given BlockMatrix K and BlockVectors d,F
- *
- * // Decomposition of tangent matrix
- * const auto A = linear_operator(K.block(0,0));
- * const auto B = linear_operator(K.block(0,1));
- * const auto C = linear_operator(K.block(1,0));
- * const auto D = linear_operator(K.block(1,1));
- *
- * // Decomposition of solution vector
- * auto x = d.block(0);
- * auto y = d.block(1);
- *
- * // Decomposition of RHS vector
- * auto f = F.block(0);
- * auto g = F.block(1);
- *
- * // Construction of inverse of Schur complement
- * const auto prec_A = PreconditionSelector<...>(A);
- * const auto A_inv = inverse_operator<...>(A,prec_A);
- * const auto S = schur_complement(A_inv,B,C,D);
- * const auto S_prec = PreconditionSelector<...>(D); // D and S operate on
- * same space const auto S_inv = inverse_operator<...>(S,...,prec_S);
- *
- * // Solve reduced block system
- * auto rhs = condense_schur_rhs (A_inv,C,f,g); // PackagedOperation that
- * represents the condensed form of g y = S_inv * rhs; // Solve for y x =
- * postprocess_schur_solution (A_inv,B,y,f); // Compute x using resolved
- * solution y
+ * #include<deal.II/lac/schur_complement.h>
+ *
+ * // Given BlockMatrix K and BlockVectors d,F
+ *
+ * // Decomposition of tangent matrix
+ * const auto A = linear_operator(K.block(0,0));
+ * const auto B = linear_operator(K.block(0,1));
+ * const auto C = linear_operator(K.block(1,0));
+ * const auto D = linear_operator(K.block(1,1));
+ *
+ * // Decomposition of solution vector
+ * auto x = d.block(0);
+ * auto y = d.block(1);
+ *
+ * // Decomposition of RHS vector
+ * auto f = F.block(0);
+ * auto g = F.block(1);
+ *
+ * // Construction of inverse of Schur complement
+ * const auto prec_A = PreconditionSelector<...>(A);
+ * const auto A_inv = inverse_operator<...>(A,prec_A);
+ * const auto S = schur_complement(A_inv,B,C,D);
+ *
+ * // D and S operate on same space
+ * const auto S_prec = PreconditionSelector<...>(D);
+ * const auto S_inv = inverse_operator<...>(S,...,prec_S);
+ *
+ * // Solve reduced block system
+ * // PackagedOperation that represents the condensed form of g
+ * y = S_inv * rhs;
+ *
+ * // PackagedOperation that represents the condensed form of g
+ * auto rhs = condense_schur_rhs (A_inv,C,f,g);
+ *
+ * // Solve for y
+ * y = S_inv * rhs;
+ *
+ * // Compute x using resolved solution y
+ * postprocess_schur_solution (A_inv,B,y,f);
* @endcode
*
* In the above example, the preconditioner for $ S $ was defined as the
* construct the approximate inverse operator $ \tilde{S}^{-1} $ which is then
* used as the preconditioner for computing $ S^{-1} $.
* @code
- * // Construction of approximate inverse of Schur complement
- * const auto A_inv_approx = linear_operator(preconditioner_A);
- * const auto S_approx = schur_complement(A_inv_approx,B,C,D);
- * const auto S_approx_prec = PreconditionSelector<...>(D); // D and S_approx
- * operate on same space const auto S_inv_approx =
- * inverse_operator(S_approx,...,S_approx_prec); // Inner solver: Typically
- * limited to few iterations using IterationNumberControl
- *
- * // Construction of exact inverse of Schur complement
- * const auto S = schur_complement(A_inv,B,C,D);
- * const auto S_inv = inverse_operator(S,...,S_inv_approx); // Outer solver
- *
- * // Solve reduced block system
- * auto rhs = condense_schur_rhs (A_inv,C,f,g);
- * y = S_inv * rhs; // Solve for y
- * x = postprocess_schur_solution (A_inv,B,y,f);
+ * // Construction of approximate inverse of Schur complement
+ * const auto A_inv_approx = linear_operator(preconditioner_A);
+ * const auto S_approx = schur_complement(A_inv_approx,B,C,D);
+ *
+ * // D and S_approx operate on same space
+ * const auto S_approx_prec = PreconditionSelector<...>(D);
+ *
+ * // Inner solver:
+ * // Typically limited to few iterations using IterationNumberControl
+ * auto S_inv_approx = inverse_operator(S_approx,...,S_approx_prec);
+ *
+ * // Construction of exact inverse of Schur complement
+ * const auto S = schur_complement(A_inv,B,C,D);
+ *
+ * // Outer solver
+ * const auto S_inv = inverse_operator(S,...,S_inv_approx);
+ *
+ * // Solve reduced block system
+ * auto rhs = condense_schur_rhs (A_inv,C,f,g);
+ *
+ * // Solve for y
+ * y = S_inv * rhs;
+ * x = postprocess_schur_solution (A_inv,B,y,f);
* @endcode
* Note that due to the construction of @c S_inv_approx and subsequently @c
* S_inv, there are a pair of nested iterative solvers which could
*
* SLEPcWrappers can be implemented in application codes in the following way:
* @code
- * SolverControl solver_control (1000, 1e-9);
- * SolverArnoldi system (solver_control, mpi_communicator);
- * system.solve (A, B, lambda, x, size_of_spectrum);
+ * SolverControl solver_control (1000, 1e-9);
+ * SolverArnoldi system (solver_control, mpi_communicator);
+ * system.solve (A, B, lambda, x, size_of_spectrum);
* @endcode
* for the generalized eigenvalue problem $Ax=B\lambda x$, where the variable
* <code>const unsigned int size_of_spectrum</code> tells SLEPc the number of
* wanted only, the following code can be implemented before calling
* <code>solve()</code>:
* @code
- * system.set_problem_type (EPS_NHEP);
- * system.set_which_eigenpairs (EPS_SMALLEST_REAL);
+ * system.set_problem_type (EPS_NHEP);
+ * system.set_which_eigenpairs (EPS_SMALLEST_REAL);
* @endcode
* These options can also be set at the command line.
*
* additionally specify which linear solver and preconditioner to use. This
* can be achieved as follows
* @code
- * PETScWrappers::PreconditionBoomerAMG::AdditionalData data;
- * data.symmetric_operator = true;
- * PETScWrappers::PreconditionBoomerAMG preconditioner(mpi_communicator,
- * data); SolverControl linear_solver_control (dof_handler.n_dofs(),
- * 1e-12,false,false); PETScWrappers::SolverCG
- * linear_solver(linear_solver_control,mpi_communicator);
- * linear_solver.initialize(preconditioner);
- * SolverControl solver_control (100, 1e-9,false,false);
- * SLEPcWrappers::SolverKrylovSchur
- * eigensolver(solver_control,mpi_communicator);
- * SLEPcWrappers::TransformationShift
- * spectral_transformation(mpi_communicator);
- * spectral_transformation.set_solver(linear_solver);
- * eigensolver.set_transformation(spectral_transformation);
- * eigensolver.solve
- * (stiffness_matrix,mass_matrix,eigenvalues,eigenfunctions,eigenfunctions.size());
+ * PETScWrappers::PreconditionBoomerAMG::AdditionalData data;
+ * data.symmetric_operator = true;
+ * PETScWrappers::PreconditionBoomerAMG preconditioner(mpi_communicator, data);
+ * SolverControl linear_solver_control (dof_handler.n_dofs(),
+ * 1e-12, false, false);
+ * PETScWrappers::SolverCG linear_solver(linear_solver_control,
+ * mpi_communicator);
+ * linear_solver.initialize(preconditioner);
+ * SolverControl solver_control (100, 1e-9,false,false);
+ * SLEPcWrappers::SolverKrylovSchur eigensolver(solver_control,
+ * mpi_communicator);
+ * SLEPcWrappers::TransformationShift spectral_transformation(mpi_communicator);
+ * spectral_transformation.set_solver(linear_solver);
+ * eigensolver.set_transformation(spectral_transformation);
+ * eigensolver.solve(stiffness_matrix, mass_matrix,
+ * eigenvalues, eigenfunctions, eigenfunctions.size());
* @endcode
*
* In order to support this usage case, different from PETSc wrappers, the
* template <typename OutputVector>
* void
* SolverBase::solve (const PETScWrappers::MatrixBase &A,
- * const PETScWrappers::MatrixBase &B,
- * std::vector<PetscScalar> &eigenvalues,
- * std::vector<OutputVector> &eigenvectors,
- * const unsigned int n_eigenpairs)
- * { ... }
+ * const PETScWrappers::MatrixBase &B,
+ * std::vector<PetscScalar> &eigenvalues,
+ * std::vector<OutputVector> &eigenvectors,
+ * const unsigned int n_eigenpairs)
+ * {
+ * ...
+ * }
* @endcode
* as an example on how to do this.
*
* application codes in the following way for <code>XXX=INVERT</code> with
* the solver object <code>eigensolver</code>:
* @code
- * // Set a transformation, this one shifts the eigenspectrum by 3.142..
- * SLEPcWrappers::TransformationShift::AdditionalData additional_data
- * (3.142); SLEPcWrappers::TransformationShift shift
- * (mpi_communicator,additional_data); eigensolver.set_transformation (shift);
+ * // Set a transformation, this one shifts the eigenspectrum by 3.142..
+ * SLEPcWrappers::TransformationShift::AdditionalData
+ * additional_data(3.142);
+ * SLEPcWrappers::TransformationShift shift(mpi_communicator,additional_data);
+ * eigensolver.set_transformation(shift);
* @endcode
* and later calling the <code>solve()</code> function as usual:
* @code
- * SolverControl solver_control (1000, 1e-9);
- * SolverArnoldi system (solver_control, mpi_communicator);
- * eigensolver.solve (A, B, lambda, x, size_of_spectrum);
+ * SolverControl solver_control (1000, 1e-9);
+ * SolverArnoldi system (solver_control, mpi_communicator);
+ * eigensolver.solve (A, B, lambda, x, size_of_spectrum);
* @endcode
*
* @note These options can also be set at the command line.
* An example may illuminate these issues. In the step-3 tutorial program, let
* us add a member function as follows to the main class:
* @code
- * SolverControl::State
- * Step3::write_intermediate_solution (const unsigned int iteration,
- * const double , //check_value
- * const Vector<double> ¤t_iterate)
- * const
- * {
- * DataOut<2> data_out;
- * data_out.attach_dof_handler (dof_handler);
- * data_out.add_data_vector (current_iterate, "solution");
- * data_out.build_patches ();
- *
- * std::ofstream output ((std::string("solution-")
- * + Utilities::int_to_string(iteration,4) +
- * ".vtu").c_str()); data_out.write_vtu (output);
- *
- * return SolverControl::success;
- * }
+ * SolverControl::State
+ * Step3::write_intermediate_solution (
+ * const unsigned int iteration,
+ * const double , //check_value
+ * const Vector<double> ¤t_iterate) const
+ * {
+ * DataOut<2> data_out;
+ * data_out.attach_dof_handler (dof_handler);
+ * data_out.add_data_vector (current_iterate, "solution");
+ * data_out.build_patches ();
+ *
+ * std::ofstream output ("solution-"
+ * + Utilities::int_to_string(iteration,4)
+ * + ".vtu");
+ * data_out.write_vtu (output);
+ *
+ * return SolverControl::success;
+ * }
* @endcode
* The function satisfies the signature necessary to be a slot for the signal
* discussed above, with the exception that it is a member function and
*
* <h3>Usage</h3> The simplest use of this class is the following:
* @code
- * // generate a @p SolverControl and
- * // a @p VectorMemory
+ * // generate a @p SolverControl and a @p VectorMemory
* SolverControl control;
* VectorMemory<Vector<double> > memory;
- * // Line 3:
- * //
- * // generate a @p SolverSelector that
- * // calls the @p SolverCG
+ *
+ * // Line 3:
+ * // generate a @p SolverSelector that calls the @p SolverCG
* SolverSelector<Vector<double> >
* solver_selector("cg", control, memory);
- * // generate e.g. a @p PreconditionRelaxation
+ *
+ * // generate e.g. a @p PreconditionRelaxation
* PreconditionRelaxation<SparseMatrix<double>, Vector<double> >
- * preconditioning(A, &SparseMatrix<double>
- * ::template precondition_SSOR<double>,0.8);
- * // call the @p solve function with this
- * // preconditioning as last argument
+ * preconditioning(
+ * A, &SparseMatrix<double>::template precondition_SSOR<double>,0.8);
+ *
+ * // call the @p solve function with this preconditioning as last argument
* solver_selector.solve(A,x,b,preconditioning);
* @endcode
* But the full usefulness of the @p SolverSelector class is not clear until
* @code
* Parameter_Handler prm;
* prm.declare_entry ("solver", "none",
- * Patterns::Selection(SolverSelector<>::get_solver_names()));
+ * Patterns::Selection(
+ * SolverSelector<>::get_solver_names()));
* ...
* @endcode
* Assuming that in the users parameter file there exists the line
* The specialization
* @code
* template <>
- * struct is_serial_vector< VectorType > : std::true_type {};
+ * struct is_serial_vector<VectorType> : std::true_type
+ * {};
* @endcode
* for a serial vector type, respectively,
* @code
* template <>
- * struct is_serial_vector< VectorType > : std::false_type {};
+ * struct is_serial_vector<VectorType> : std::false_type
+ * {};
* @endcode
* for a vector type with support of distributed storage,
* must be done in a header file of a vector declaration.