Dear all,

I'm trying to use a block-diagonal preconditioner for the mixed Poisson 
problem from step-20, but haven't made it yet.

The diagonal preconditioner of interest is from Powell & Silvester,2003 
<https://www.google.com/url?q=https%3A%2F%2Fepubs.siam.org%2Fdoi%2Fabs%2F10.1137%2FS0895479802404428&sa=D&sntz=1&usg=AFQjCNGCFHHh92fZkVu4-ueHwkaDbH_SiA>.
 
Specifically, for the matrix system after discretization with the RT0-DG0 
element pair
  [A  BT
   B  0],
they suggested a block diagonal preconditioner
  P = 
  [DA  0
   0     PS],
where DA is diag(A), and PS is AMG applied to the approximated Schur 
complement SD = B(DA^-1)BT.

As the above idea is quite similar to that in step-55, so I borrowed quite 
a few code blocks from there, e.g. InverseMatrix and 
BlockDiagonalPreconditioner. The resulting solve() with a SolverMinRes solver 
is as follows. (The rest of the code is mainly from step-20)

  template <int dim>
 void MixedLaplaceProblem<dim>::solve()
 {
   TrilinosWrappers::PreconditionJacobi diagA;
   diagA.initialize(system_matrix.block(0, 0));//DA

    ApproximateSchurComplement approximate_schur(system_matrix, solution);
//SD

    InverseMatrix<ApproximateSchurComplement> approximate_inverse(
approximate_schur);//PS

    const BlockDiagonalPreconditioner<TrilinosWrappers::PreconditionJacobi,
         InverseMatrix<ApproximateSchurComplement> >
         preconditioner(diagA, approximate_inverse);

    SolverControl solver_control(system_matrix.m(),
                                1e-6 * system_rhs.l2_norm());

    SolverMinRes<TrilinosWrappers::MPI::BlockVector> solver(solver_control);
   solver.solve(system_matrix, solution, system_rhs,
      preconditioner
     );

    std::cout<<"last step = "<<solver_control.last_step()<<std::endl;
 }

However, the code can't compile, and gives the following error message:

  /home/dealii/test.cc:336:5: error: no matching function for call to ‘
dealii::TrilinosWrappers::PreconditionAMG::initialize(const Step20::
ApproximateSchurComplement&, dealii::TrilinosWrappers::PreconditionAMG::
AdditionalData&)’
      preconditioner.initialize(*matrix, data);
      ^
 In file included from /home/dealii/dealii-v9.0.0/include/deal.II/lac/
generic_linear_algebra.h:141:0,
                  from /home/dealii/test.cc:31:
 /home/dealii/dealii-v9.0.0/include/deal.II/lac/trilinos_precondition.h:1516
:10: note: candidate: void dealii::TrilinosWrappers::PreconditionAMG::
initialize(const dealii::TrilinosWrappers::SparseMatrix&, const dealii::
TrilinosWrappers::PreconditionAMG::AdditionalData&)
      void initialize (const SparseMatrix   &matrix,

The error is related to the use of PreconditionAMG in my implementation of 
InverseMatrix<MatrixType>::vmult:

  template <class MatrixType>
 void InverseMatrix<MatrixType>::vmult (LinearAlgebraTrilinos::MPI::Vector   
    &dst,
                                        const LinearAlgebraTrilinos::MPI::
Vector &src) const
 {
   SolverControl solver_control(src.size(),
                            1e-6 * src.l2_norm());
   SolverCG<TrilinosWrappers::MPI::Vector>    cg (solver_control);
   dst = 0;

    LinearAlgebraTrilinos::MPI::PreconditionAMG preconditioner;
   LinearAlgebraTrilinos::MPI::PreconditionAMG::AdditionalData data;
   preconditioner.initialize(*matrix, data);

    // PreconditionIdentity preconditioner;//A Identity preconditioner 
works fine here

    cg.solve (*matrix, dst, src, preconditioner);

    std::cout<<"inner last step = "<<solver_control.last_step()<<std::endl;
 }

I find a conflict here is that::
1) TrilinosWrappers::PreconditionAMG can only be initialized with a matrix, 
but not a ApproximateSchurComplement;
2) step-20 uses ApproximateSchurComplement because we actually don't want 
to/can't assemble the Schur matrix or its inverse.

Could you please give me a hint on how to solve this conflict in deal.II? 
Is it actually possible to assemble this B(DA^-1)BT directly?

Attached is a minimal (but not working) code.

Best regards,
Charlie

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dealii+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/dealii/73183270-5edb-4c8f-a998-17da5cb12221%40googlegroups.com.
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/function.h>
#include <deal.II/lac/block_vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/solver_minres.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/linear_operator.h>
#include <deal.II/lac/packaged_operation.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_dgq.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <fstream>
#include <iostream>
#include <deal.II/fe/fe_raviart_thomas.h>
#include <deal.II/base/tensor_function.h>

#include <deal.II/lac/generic_linear_algebra.h>
#include <deal.II/lac/solver_gmres.h>
#include <deal.II/base/index_set.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/lac/trilinos_block_sparse_matrix.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal.II/lac/trilinos_parallel_block_vector.h>
#include <deal.II/lac/trilinos_precondition.h>

namespace Step20
{
  using namespace dealii;
  template <int dim>
  class MixedLaplaceProblem
  {
  public:
    MixedLaplaceProblem(const unsigned int degree);
    void run();
  private:
    void make_grid_and_dofs();
    void assemble_system();
    void solve();
    void compute_errors() const;
    void output_results() const;

    const unsigned int degree;
    Triangulation<dim> triangulation;
    FESystem<dim>      fe;
    DoFHandler<dim>    dof_handler;
    BlockSparsityPattern      sparsity_pattern;
    std::vector<IndexSet> stokes_partitioning;
    TrilinosWrappers::BlockSparseMatrix system_matrix;
    TrilinosWrappers::MPI::BlockVector solution;
    TrilinosWrappers::MPI::BlockVector system_rhs;

    bool verbose;
  };
  template <class PreconditionerA, class PreconditionerS>
  class BlockDiagonalPreconditioner : public Subscriptor
  {
  public:
    BlockDiagonalPreconditioner(const PreconditionerA &preconditioner_A,
                                const PreconditionerS &preconditioner_S);
    void vmult(LinearAlgebraTrilinos::MPI::BlockVector &      dst,
               const LinearAlgebraTrilinos::MPI::BlockVector &src) const;
  private:
    const PreconditionerA &preconditioner_A;
    const PreconditionerS &preconditioner_S;
  };
  template <class PreconditionerA, class PreconditionerS>
  BlockDiagonalPreconditioner<PreconditionerA, PreconditionerS>::
    BlockDiagonalPreconditioner(const PreconditionerA &preconditioner_A,
                                const PreconditionerS &preconditioner_S)
    : preconditioner_A(preconditioner_A)
    , preconditioner_S(preconditioner_S)
  {}
  template <class PreconditionerA, class PreconditionerS>
  void BlockDiagonalPreconditioner<PreconditionerA, PreconditionerS>::vmult(
    LinearAlgebraTrilinos::MPI::BlockVector &      dst,
    const LinearAlgebraTrilinos::MPI::BlockVector &src) const
  {
    preconditioner_A.vmult(dst.block(0), src.block(0));
    preconditioner_S.vmult(dst.block(1), src.block(1));
  }
  template <int dim>
  class RightHandSide : public Function<dim>
  {
  public:
    RightHandSide()
      : Function<dim>(1)
    {}
    virtual double value(const Point<dim> & p,
                         const unsigned int component = 0) const override;
  };
  template <int dim>
  class PressureBoundaryValues : public Function<dim>
  {
  public:
    PressureBoundaryValues()
      : Function<dim>(1)
    {}
    virtual double value(const Point<dim> & p,
                         const unsigned int component = 0) const override;
  };
  template <int dim>
  class ExactSolution : public Function<dim>
  {
  public:
    ExactSolution()
      : Function<dim>(dim + 1)
    {}
    virtual void vector_value(const Point<dim> &p,
                              Vector<double> &  value) const override;
  };
  template <int dim>
  double RightHandSide<dim>::value(const Point<dim> & /*p*/,
                                   const unsigned int /*component*/) const
  {
    return 0;
  }
  template <int dim>
  double
  PressureBoundaryValues<dim>::value(const Point<dim> &p,
                                     const unsigned int /*component*/) const
  {
    const double alpha = 0.3;
    const double beta  = 1;
    return -(alpha * p[0] * p[1] * p[1] / 2 + beta * p[0] -
             alpha * p[0] * p[0] * p[0] / 6);
  }
  template <int dim>
  void ExactSolution<dim>::vector_value(const Point<dim> &p,
                                        Vector<double> &  values) const
  {
    Assert(values.size() == dim + 1,
           ExcDimensionMismatch(values.size(), dim + 1));
    const double alpha = 0.3;
    const double beta  = 1;
    values(0) = alpha * p[1] * p[1] / 2 + beta - alpha * p[0] * p[0] / 2;
    values(1) = alpha * p[0] * p[1];
    values(2) = -(alpha * p[0] * p[1] * p[1] / 2 + beta * p[0] -
                  alpha * p[0] * p[0] * p[0] / 6);
  }
  template <int dim>
  class KInverse : public TensorFunction<2, dim>
  {
  public:
    KInverse()
      : TensorFunction<2, dim>()
    {}
    virtual void value_list(const std::vector<Point<dim>> &points,
                            std::vector<Tensor<2, dim>> &values) const override;
  };
  template <int dim>
  void KInverse<dim>::value_list(const std::vector<Point<dim>> &points,
                                 std::vector<Tensor<2, dim>> &  values) const
  {
    (void)points;
    AssertDimension(points.size(), values.size());
    for (auto &value : values)
      {
        value.clear();
        for (unsigned int d = 0; d < dim; ++d)
          value[d][d] = 1.;
      }
  }
  template <int dim>
  MixedLaplaceProblem<dim>::MixedLaplaceProblem(const unsigned int degree)
    : degree(degree)
    , fe(FE_RaviartThomas<dim>(degree), 1, FE_DGQ<dim>(degree), 1)
    , dof_handler(triangulation)
  {
    verbose = false;
  }
  template <int dim>
  void MixedLaplaceProblem<dim>::make_grid_and_dofs()
  {
    GridGenerator::hyper_cube(triangulation, -1, 1);
    triangulation.refine_global(5);

    dof_handler.distribute_dofs(fe);
    DoFRenumbering::component_wise(dof_handler);

    std::vector<types::global_dof_index> dofs_per_component(dim + 1);
    DoFTools::count_dofs_per_component(dof_handler, dofs_per_component);
    const unsigned int n_u = dofs_per_component[0],
                       n_p = dofs_per_component[dim];
    std::cout << "Number of active cells: " << triangulation.n_active_cells()
              << std::endl
              << "Total number of cells: " << triangulation.n_cells()
              << std::endl
              << "Number of degrees of freedom: " << dof_handler.n_dofs()
              << " (" << n_u << '+' << n_p << ')' << std::endl;
    BlockDynamicSparsityPattern dsp(2, 2);
    dsp.block(0, 0).reinit(n_u, n_u);
    dsp.block(1, 0).reinit(n_p, n_u);
    dsp.block(0, 1).reinit(n_u, n_p);
    dsp.block(1, 1).reinit(n_p, n_p);
    dsp.collect_sizes();
    DoFTools::make_sparsity_pattern(dof_handler, dsp);
    system_matrix.reinit(dsp);
    stokes_partitioning.resize(2);
    stokes_partitioning[0] = complete_index_set(n_u);
    stokes_partitioning[1] = complete_index_set(n_p);

    solution.reinit(stokes_partitioning, MPI_COMM_WORLD);
    system_rhs.reinit(stokes_partitioning, MPI_COMM_WORLD);

  }
  template <int dim>
  void MixedLaplaceProblem<dim>::assemble_system()
  {
    QGauss<dim>     quadrature_formula(degree + 2);
    QGauss<dim - 1> face_quadrature_formula(degree + 2);
    FEValues<dim>     fe_values(fe,
                            quadrature_formula,
                            update_values | update_gradients |
                              update_quadrature_points | update_JxW_values);
    FEFaceValues<dim> fe_face_values(fe,
                                     face_quadrature_formula,
                                     update_values | update_normal_vectors |
                                       update_quadrature_points |
                                       update_JxW_values);
    const unsigned int dofs_per_cell   = fe.dofs_per_cell;
    const unsigned int n_q_points      = quadrature_formula.size();
    const unsigned int n_face_q_points = face_quadrature_formula.size();
    FullMatrix<double> local_matrix(dofs_per_cell, dofs_per_cell);
    Vector<double>     local_rhs(dofs_per_cell);
    std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
    const RightHandSide<dim>          right_hand_side;
    const PressureBoundaryValues<dim> pressure_boundary_values;
    const KInverse<dim>               k_inverse;
    std::vector<double>         rhs_values(n_q_points);
    std::vector<double>         boundary_values(n_face_q_points);
    std::vector<Tensor<2, dim>> k_inverse_values(n_q_points);
    const FEValuesExtractors::Vector velocities(0);
    const FEValuesExtractors::Scalar pressure(dim);
    for (const auto &cell : dof_handler.active_cell_iterators())
      {
        fe_values.reinit(cell);
        local_matrix = 0;
        local_rhs    = 0;
        right_hand_side.value_list(fe_values.get_quadrature_points(),
                                   rhs_values);
        k_inverse.value_list(fe_values.get_quadrature_points(),
                             k_inverse_values);
        for (unsigned int q = 0; q < n_q_points; ++q)
          for (unsigned int i = 0; i < dofs_per_cell; ++i)
            {
              const Tensor<1, dim> phi_i_u = fe_values[velocities].value(i, q);
              const double div_phi_i_u = fe_values[velocities].divergence(i, q);
              const double phi_i_p     = fe_values[pressure].value(i, q);
              for (unsigned int j = 0; j < dofs_per_cell; ++j)
                {
                  const Tensor<1, dim> phi_j_u =
                    fe_values[velocities].value(j, q);
                  const double div_phi_j_u =
                    fe_values[velocities].divergence(j, q);
                  const double phi_j_p = fe_values[pressure].value(j, q);
                  local_matrix(i, j) +=
                    (phi_i_u * k_inverse_values[q] * phi_j_u 
                     - phi_i_p * div_phi_j_u                 
                     - div_phi_i_u * phi_j_p)                
                    * fe_values.JxW(q);
                }
              local_rhs(i) += -phi_i_p * rhs_values[q] * fe_values.JxW(q);
            }
        for (unsigned int face_n = 0;
             face_n < GeometryInfo<dim>::faces_per_cell;
             ++face_n)
          if (cell->at_boundary(face_n))
            {
              fe_face_values.reinit(cell, face_n);
              pressure_boundary_values.value_list(
                fe_face_values.get_quadrature_points(), boundary_values);
              for (unsigned int q = 0; q < n_face_q_points; ++q)
                for (unsigned int i = 0; i < dofs_per_cell; ++i)
                  local_rhs(i) += -(fe_face_values[velocities].value(i, q) * 
                                    fe_face_values.normal_vector(q) *        
                                    boundary_values[q] *                     
                                    fe_face_values.JxW(q));
            }
        cell->get_dof_indices(local_dof_indices);
        for (unsigned int i = 0; i < dofs_per_cell; ++i)
          for (unsigned int j = 0; j < dofs_per_cell; ++j)
            system_matrix.add(local_dof_indices[i],
                              local_dof_indices[j],
                              local_matrix(i, j));
        for (unsigned int i = 0; i < dofs_per_cell; ++i)
          system_rhs(local_dof_indices[i]) += local_rhs(i);
      }
    if (verbose)
    {
    std::cout<<"         ***         \nafter constrants.condense\n";
    system_matrix.print(std::cout);
    system_rhs.print(std::cout);
    }

  }
  template <class MatrixType>
  class InverseMatrix : public Subscriptor
  {
  public:
    InverseMatrix(const MatrixType &m);
    void vmult(LinearAlgebraTrilinos::MPI::Vector       &dst,
               const LinearAlgebraTrilinos::MPI::Vector &src) const;
  private:
    const SmartPointer<const MatrixType> matrix;
  };
  template <class MatrixType>
  InverseMatrix<MatrixType>::InverseMatrix (const MatrixType &m)
    :
    matrix (&m)
  {}
  template <class MatrixType>
  void InverseMatrix<MatrixType>::vmult (LinearAlgebraTrilinos::MPI::Vector       &dst,
                                         const LinearAlgebraTrilinos::MPI::Vector &src) const
  {
    SolverControl solver_control(src.size(),
                             1e-6 * src.l2_norm());
    SolverCG<TrilinosWrappers::MPI::Vector>    cg (solver_control);
    dst = 0;

    LinearAlgebraTrilinos::MPI::PreconditionAMG preconditioner;
    LinearAlgebraTrilinos::MPI::PreconditionAMG::AdditionalData data;
    preconditioner.initialize(*matrix, data);

    // PreconditionIdentity preconditioner;//a Identity preconditioner works fine

    cg.solve (*matrix, dst, src, preconditioner);

    std::cout<<"inner last step = "<<solver_control.last_step()<<std::endl;
  }

  class ApproximateSchurComplement : public Subscriptor
  {
  public:
    ApproximateSchurComplement (const LinearAlgebraTrilinos::MPI::BlockSparseMatrix &A, const LinearAlgebraTrilinos::MPI::BlockVector &V);
    void vmult (LinearAlgebraTrilinos::MPI::Vector       &dst,
                const LinearAlgebraTrilinos::MPI::Vector &src) const;
  private:
    const SmartPointer<const LinearAlgebraTrilinos::MPI::BlockSparseMatrix > system_matrix;
    mutable LinearAlgebraTrilinos::MPI::Vector tmp1, tmp2;
  };
  ApproximateSchurComplement::ApproximateSchurComplement
  (const LinearAlgebraTrilinos::MPI::BlockSparseMatrix &A, const LinearAlgebraTrilinos::MPI::BlockVector &V) :
    system_matrix (&A),
    tmp1(V.block(0)),
    tmp2(V.block(0))
  {}
  void
  ApproximateSchurComplement::vmult
  (LinearAlgebraTrilinos::MPI::Vector       &dst,
   const LinearAlgebraTrilinos::MPI::Vector &src) const
  {

    tmp1 = 0;
    tmp2 = 0;

    system_matrix->block(0,1).vmult (tmp1, src);

    TrilinosWrappers::PreconditionJacobi diagA;
    diagA.initialize(system_matrix->block(0, 0));
    diagA.vmult(tmp2, tmp1);

    system_matrix->block(1,0).vmult (dst, tmp2);
  }

  template <int dim>
  void MixedLaplaceProblem<dim>::solve()
  {
    TrilinosWrappers::PreconditionJacobi diagA;
    diagA.initialize(system_matrix.block(0, 0));

    ApproximateSchurComplement approximate_schur(system_matrix, solution);

    InverseMatrix<ApproximateSchurComplement> approximate_inverse(approximate_schur);

    const BlockDiagonalPreconditioner<TrilinosWrappers::PreconditionJacobi,
          InverseMatrix<ApproximateSchurComplement> >
          preconditioner(diagA, approximate_inverse);

    SolverControl solver_control(system_matrix.m(),
                                 1e-6 * system_rhs.l2_norm());

    SolverMinRes<TrilinosWrappers::MPI::BlockVector> solver(solver_control);
    solver.solve(system_matrix, solution, system_rhs, 
      preconditioner
      );

    std::cout<<"last step = "<<solver_control.last_step()<<std::endl;
  }
  template <int dim>
  void MixedLaplaceProblem<dim>::compute_errors() const
  {
    const ComponentSelectFunction<dim> pressure_mask(dim, dim + 1);
    const ComponentSelectFunction<dim> velocity_mask(std::make_pair(0, dim),
                                                     dim + 1);
    ExactSolution<dim> exact_solution;
    Vector<double>     cellwise_errors(triangulation.n_active_cells());
    QTrapez<1>     q_trapez;
    QIterated<dim> quadrature(q_trapez, degree + 2);
    VectorTools::integrate_difference(dof_handler,
                                      solution,
                                      exact_solution,
                                      cellwise_errors,
                                      quadrature,
                                      VectorTools::L2_norm,
                                      &pressure_mask);
    const double p_l2_error =
      VectorTools::compute_global_error(triangulation,
                                        cellwise_errors,
                                        VectorTools::L2_norm);
    VectorTools::integrate_difference(dof_handler,
                                      solution,
                                      exact_solution,
                                      cellwise_errors,
                                      quadrature,
                                      VectorTools::L2_norm,
                                      &velocity_mask);
    const double u_l2_error =
      VectorTools::compute_global_error(triangulation,
                                        cellwise_errors,
                                        VectorTools::L2_norm);
    std::cout << "Errors: ||e_p||_L2 = " << p_l2_error
              << ",   ||e_u||_L2 = " << u_l2_error << std::endl;
  }
  template <int dim>
  void MixedLaplaceProblem<dim>::output_results() const
  {
    std::vector<std::string> solution_names(dim, "u");
    solution_names.emplace_back("p");
    std::vector<DataComponentInterpretation::DataComponentInterpretation>
      interpretation(dim,
                     DataComponentInterpretation::component_is_part_of_vector);
    interpretation.push_back(DataComponentInterpretation::component_is_scalar);
    DataOut<dim> data_out;
    data_out.add_data_vector(dof_handler,
                             solution,
                             solution_names,
                             interpretation);
    data_out.build_patches(degree + 1);
    std::ofstream output("solution.vtk");
    data_out.write_vtk(output);
  }
  template <int dim>
  void MixedLaplaceProblem<dim>::run()
  {
    make_grid_and_dofs();

    assemble_system();
    solve();
    compute_errors();
    output_results();

  }
}
int main(int argc, char *argv[])
{
  try
    {
      using namespace dealii;
      using namespace Step20;

      Utilities::MPI::MPI_InitFinalize mpi_initialization(
        argc, argv, numbers::invalid_unsigned_int);
      AssertThrow(Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD) == 1,
                  ExcMessage(
                    "This program can only be run in serial."));

      MixedLaplaceProblem<2> mixed_laplace_problem(0);
      mixed_laplace_problem.run();
    }
  catch (std::exception &exc)
    {
      std::cerr << std::endl
                << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }
  catch (...)
    {
      std::cerr << std::endl
                << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }
  return 0;
}
##
#  CMake script for the step-21 tutorial program:
##

# Set the name of the project and target:
SET(TARGET "test")

# Declare all source files the target consists of. Here, this is only
# the one step-X.cc file, but as you expand your project you may wish
# to add other source files as well. If your project becomes much larger,
# you may want to either replace the following statement by something like
#  FILE(GLOB_RECURSE TARGET_SRC  "source/*.cc")
#  FILE(GLOB_RECURSE TARGET_INC  "include/*.h")
#  SET(TARGET_SRC ${TARGET_SRC}  ${TARGET_INC})
# or switch altogether to the large project CMakeLists.txt file discussed
# in the "CMake in user projects" page accessible from the "User info"
# page of the documentation.
SET(TARGET_SRC
  ${TARGET}.cc
  )

# Usually, you will not need to modify anything beyond this point...

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)

FIND_PACKAGE(deal.II 9.0.0 QUIET
  HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
  )
IF(NOT ${deal.II_FOUND})
  MESSAGE(FATAL_ERROR "\n"
    "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
    "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to 
cmake\n"
    "or set an environment variable \"DEAL_II_DIR\" that contains this path."
    )
ENDIF()

DEAL_II_INITIALIZE_CACHED_VARIABLES()
PROJECT(${TARGET})
DEAL_II_INVOKE_AUTOPILOT()

Reply via email to