/* $Id: step-15.cc 27656 2012-11-21 13:12:20Z bangerth $ */
/* Author: Sven Wetterauer, University of Heidelberg, 2012 */

/*    $Id: step-15.cc 27656 2012-11-21 13:12:20Z bangerth $       */
/*                                                                */
/*    Copyright (C) 2012 by the deal.II authors */
/*                                                                */
/*    This file is subject to QPL and may not be  distributed     */
/*    without copyright and license information. Please refer     */
/*    to the file deal.II/doc/license.html for the  text  and     */
/*    further information on this license.                        */

// @sect3{Include files}

// The first few files have already been covered in previous examples and will
// thus not be further commented on.
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/utilities.h>

#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/compressed_sparsity_pattern.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/constraint_matrix.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/grid/tria_boundary_lib.h>
#include <deal.II/grid/grid_refinement.h>

#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>

#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_q.h>

#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>

#include <fstream>
#include <iostream>

// We will use adaptive mesh refinement between Newton interations. To do so,
// we need to be able to work with a solution on the new mesh, although it was
// computed on the old one. The SolutionTransfer class transfers the solution
// from the old to the new mesh:

#include <deal.II/numerics/solution_transfer.h>

// We then open a namepsace for this program and import everything from the
// dealii namespace into it, as in previous programs:
namespace Step15
{
  using namespace dealii;

  // @sect3{The MinimalSurfaceProblem class template}

  // The class template is basically the same as in step-6.  Three additions
  // are made:
  // - There are two solution vectors, one for the Newton update
  //   $\delta u^n$, and one for the current iterate $u^n$.
  // - The setup_system function takes an argument that denotes whether
  //   this is the first time it is called or not. The difference is that the
  //   first time around we need to distributed degrees of freedom and set the
  //   solution vector for $u^n$ to the correct size. The following times, the
  //   function is called after we have already done these steps as part of
  //   refining the mesh in refine_mesh.
  // - We then also need new functions: set_boundary_values()
  //   takes care of setting the boundary values on the solution vector
  //   correctly, as discussed at the end of the
  //   introduction. compute_residual() is a function that computes
  //   the norm of the nonlinear (discrete) residual. We use this function to
  //   monitor convergence of the Newton iteration. The function takes a step
  //   length $\alpha^n$ as argument to compute the residual of $u^n + \alpha^n
  //   \; \delta u^n$. This is something one typically needs for step length
  //   control, although we will not use this feature here. Finally,
  //   determine_step_length() computes the step length $\alpha^n$
  //   in each Newton iteration. As discussed in the introduction, we here use a
  //   fixed step length and leave implementing a better strategy as an
  //   exercise.

  template <int dim>
  class MinimalSurfaceProblem
  {
  public:
    MinimalSurfaceProblem ();
    ~MinimalSurfaceProblem ();

    void run ();

  private:
    void setup_system (const bool initial_step);
    void assemble_system ();
    void solve ();
    void refine_mesh ();
    void set_boundary_values ();
    double compute_residual (const double alpha) const;
    double determine_step_length () const;

    Triangulation<dim>   triangulation;

    DoFHandler<dim>      dof_handler;
    FE_Q<dim>            fe;

    ConstraintMatrix     hanging_node_constraints;

    SparsityPattern      sparsity_pattern;
    SparseMatrix<double> system_matrix;

    Vector<double>       present_solution;
    Vector<double>       newton_update;
    Vector<double>       system_rhs;
  };

  // @sect3{Boundary condition}

  // The boundary condition is implemented just like in step-4.  It is chosen
  // as $g(x,y)=\sin(2 \pi (x+y))$:

  template <int dim>
  class BoundaryValues : public Function<dim>
  {
  public:
    BoundaryValues () : Function<dim>() {}

    virtual double value (const Point<dim>   &p,
                          const unsigned int  component = 0) const;
  };

  template <int dim>
  double BoundaryValues<dim>::value (const Point<dim> &p,
                                     const unsigned int /*component*/) const
  {
    return std::sin(2 * numbers::PI * (p[0]+p[1]));
  }

  // @sect3{The MinimalSurfaceProblem class implementation}

  // @sect4{MinimalSurfaceProblem::MinimalSurfaceProblem}

  // The constructor and destructor of the class are the same as in the first
  // few tutorials.

  template <int dim>
  MinimalSurfaceProblem<dim>::MinimalSurfaceProblem ()
    :
    dof_handler (triangulation),
    fe (2)
  {}

  template <int dim>
  MinimalSurfaceProblem<dim>::~MinimalSurfaceProblem ()
  {
    dof_handler.clear ();
  }

  // @sect4{MinimalSurfaceProblem::setup_system}

  // As always in the setup-system function, we setup the variables of the
  // finite element method. There are same differences to step-6, because
  // there we start solving the PDE from scratch in every refinement cycle
  // whereas here we need to take the solution from the previous mesh onto the
  // current mesh. Consequently, we can't just reset solution vectors. The
  // argument passed to this function thus indicates whether we can
  // distributed degrees of freedom (plus compute constraints) and set the
  // solution vector to zero or whether this has happened elsewhere already
  // (specifically, in refine_mesh()).

  template <int dim>
  void MinimalSurfaceProblem<dim>::setup_system (const bool initial_step)
  {
    if (initial_step)
      {
        dof_handler.distribute_dofs (fe);
        present_solution.reinit (dof_handler.n_dofs());

        hanging_node_constraints.clear ();
        DoFTools::make_hanging_node_constraints (dof_handler,
                                                 hanging_node_constraints);
        hanging_node_constraints.close ();
      }

    // The remaining parts of the function are the same as in step-6.

    newton_update.reinit (dof_handler.n_dofs());
    system_rhs.reinit (dof_handler.n_dofs());

    CompressedSparsityPattern c_sparsity(dof_handler.n_dofs());
    DoFTools::make_sparsity_pattern (dof_handler, c_sparsity);

    hanging_node_constraints.condense (c_sparsity);

    sparsity_pattern.copy_from(c_sparsity);
    system_matrix.reinit (sparsity_pattern);
  }

  // @sect4{MinimalSurfaceProblem::assemble_system}

  // This function does the same as in the previous tutorials except that now,
  // of course, the matrix and right hand side functions depend on the
  // previous iteration's solution. As discussed in the introduction, we need
  // to use zero boundary values for the Newton updates; we compute them at
  // the end of this function.
  //
  // The top of the function contains the usual boilerplate code, setting up
  // the objects that allow us to evaluate shape functions at quadrature
  // points and temporary storage locations for the local matrices and
  // vectors, as well as for the gradients of the previous solution at the
  // quadrature points. We then start the loop over all cells:
  template <int dim>
  void MinimalSurfaceProblem<dim>::assemble_system ()
  {
    const QGauss<dim>  quadrature_formula(3);

    system_matrix = 0;
    system_rhs = 0;

    FEValues<dim> fe_values (fe, quadrature_formula,
                             update_gradients         |
                             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();

    FullMatrix<double>           cell_matrix (dofs_per_cell, dofs_per_cell);
    Vector<double>               cell_rhs (dofs_per_cell);

    std::vector<Tensor<1, dim> > old_solution_gradients(n_q_points);

    std::vector<unsigned int>    local_dof_indices (dofs_per_cell);

    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
    for (; cell!=endc; ++cell)
      {
        cell_matrix = 0;
        cell_rhs = 0;

        fe_values.reinit (cell);

        // For the assembly of the linear system, we have to obtain the values
        // of the previous solution's gradients at the quadrature
        // points. There is a standard way of doing this: the
        // FEValues::get_function function takes a vector that represents a
        // finite element field defined on a DoFHandler, and evaluates the
        // gradients of this field at the quadrature points of the cell with
        // which the FEValues object has last been reinitialized. The values
        // of the gradients at all quadrature points are then written into the
        // second argument:
        fe_values.get_function_gradients(present_solution,
                                         old_solution_gradients);

        // With this, we can then do the integration loop over all quadrature
        // points and shape functions.  Having just computed the gradients of
        // the old solution in the quadrature points, we are able to compute
        // the coefficients $a_{n}$ in these points.  The assembly of the
        // system itself then looks similar to what we always do with the
        // exception of the nonlinear terms, as does copying the results from
        // the local objects into the global ones:
        for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
          {
            const double coeff
              = 1.0 / std::sqrt(1 +
                                old_solution_gradients[q_point] *
                                old_solution_gradients[q_point]);

            for (unsigned int i=0; i<dofs_per_cell; ++i)
              {
                for (unsigned int j=0; j<dofs_per_cell; ++j)
                  {
                    cell_matrix(i, j) += (fe_values.shape_grad(i, q_point)
                                          * coeff
                                          * (fe_values.shape_grad(j, q_point)
                                             -
                                             coeff * coeff
                                             * (fe_values.shape_grad(j, q_point)
                                                *
                                                old_solution_gradients[q_point])
                                             * old_solution_gradients[q_point]
                                            )
                                          * fe_values.JxW(q_point));
                  }

                cell_rhs(i) -= (fe_values.shape_grad(i, q_point)
                                * coeff
                                * old_solution_gradients[q_point]
                                * fe_values.JxW(q_point));
              }
          }

        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],
                                 cell_matrix(i,j));

            system_rhs(local_dof_indices[i]) += cell_rhs(i);
          }
      }

    // Finally, we remove hanging nodes from the system and apply zero
    // boundary values to the linear system that defines the Newton updates
    // $\delta u^n$:
    hanging_node_constraints.condense (system_matrix);
    hanging_node_constraints.condense (system_rhs);

    std::map<unsigned int,double> boundary_values;
    VectorTools::interpolate_boundary_values (dof_handler,
                                              0,
                                              ZeroFunction<dim>(),
                                              boundary_values);
    MatrixTools::apply_boundary_values (boundary_values,
                                        system_matrix,
                                        newton_update,
                                        system_rhs);
  }

  // @sect4{MinimalSurfaceProblem::solve}

  // The solve function is the same as always. At the end of the solution
  // process we update the current solution by setting
  // $u^{n+1}=u^n+\alpha^n\;\delta u^n$.
  template <int dim>
  void MinimalSurfaceProblem<dim>::solve ()
  {
    SolverControl solver_control (system_rhs.size(),
                                  system_rhs.l2_norm()*1e-6);
    SolverCG<>    solver (solver_control);

    PreconditionSSOR<> preconditioner;
    preconditioner.initialize(system_matrix, 1.2);

    solver.solve (system_matrix, newton_update, system_rhs,
                  preconditioner);

    hanging_node_constraints.distribute (newton_update);

    const double alpha = determine_step_length();
    present_solution.add (alpha, newton_update);
  }

  // @sect4{MinimalSurfaceProblem::refine_mesh}

  // The first part of this function is the same as in step-6... However,
  // after refining the mesh we have to transfer the old solution to the new
  // one which we do with the help of the SolutionTransfer class. The process
  // is slightly convoluted, so let us describe it in detail:
  template <int dim>
  void MinimalSurfaceProblem<dim>::refine_mesh ()
  {
    Vector<float> estimated_error_per_cell (triangulation.n_active_cells());

    KellyErrorEstimator<dim>::estimate (dof_handler,
                                        QGauss<dim-1>(3),
                                        typename FunctionMap<dim>::type(),
                                        present_solution,
                                        estimated_error_per_cell);

    GridRefinement::refine_and_coarsen_fixed_number (triangulation,
                                                     estimated_error_per_cell,
                                                     0.3, 0.03);

    // Then we need an additional step: if, for example, you flag a cell that
    // is once more refined than its neighbor, and that neighbor is not
    // flagged for refinement, we would end up with a jump of two refinement
    // levels across a cell interface.  To avoid these situations, the library
    // will silently also have to refine the neighbor cell once. It does so by
    // calling the Triangulation::prepare_coarsening_and_refinement function
    // before actually doing the refinement and coarsening.  This function
    // flags a set of additional cells for refinement or coarsening, to
    // enforce rules like the one-hanging-node rule.  The cells that are
    // flagged for refinement and coarsening after calling this function are
    // exactly the ones that will actually be refined or coarsened. Usually,
    // you don't have to do this by hand
    // (Triangulation::execute_coarsening_and_refinement does this for
    // you). However, we need to initialize the SolutionTransfer class and it
    // needs to know the final set of cells that will be coarsened or refined
    // in order to store the data from the old mesh and transfer to the new
    // one. Thus, we call the function by hand:
    triangulation.prepare_coarsening_and_refinement ();

    // With this out of the way, we initialize a SolutionTransfer object with
    // the present DoFHandler and attach the solution vector to it, followed
    // by doing the actual refinement and distribution of degrees of freedom
    // on the new mesh
    SolutionTransfer<dim> solution_transfer(dof_handler);
    solution_transfer.prepare_for_coarsening_and_refinement(present_solution);

    triangulation.execute_coarsening_and_refinement();

    dof_handler.distribute_dofs(fe);

    // Finally, we retrieve the old solution interpolated to the new
    // mesh. Since the SolutionTransfer function does not actually store the
    // values of the old solution, but rather indices, we need to preserve the
    // old solution vector until we have gotten the new interpolated
    // values. Thus, we have the new values written into a temporary vector,
    // and only afterwards write them into the solution vector object. Once we
    // have this solution we have to make sure that the $u^n$ we now have
    // actually has the correct boundary values. As explained at the end of
    // the introduction, this is not automatically the case even if the
    // solution before refinement had the correct boundary values, and so we
    // have to explicitly make sure that it now has:
    Vector<double> tmp(dof_handler.n_dofs());
    solution_transfer.interpolate(present_solution, tmp);
    present_solution = tmp;

    set_boundary_values ();

    // On the new mesh, there are different hanging nodes, which we have to
    // compute again. To ensure there are no hanging nodes of the old mesh in
    // the object, it's first cleared.  To be on the safe side, we then also
    // make sure that the current solution's vector entries satisfy the
    // hanging node constraints:

    hanging_node_constraints.clear();

    DoFTools::make_hanging_node_constraints(dof_handler,
                                            hanging_node_constraints);
    hanging_node_constraints.close();

    hanging_node_constraints.distribute (present_solution);

    // We end the function by updating all the remaining data structures,
    // indicating to setup_dofs() that this is not the first
    // go-around and that it needs to preserve the content of the solution
    // vector:
    setup_system (false);
  }

  // @sect4{MinimalSurfaceProblem::set_boundary_values}

  // The next function ensures that the solution vector's entries respect the
  // boundary values for our problem.  Having refined the mesh (or just
  // started computations), there might be new nodal points on the
  // boundary. These have values that are simply interpolated from the
  // previous mesh (or are just zero), instead of the correct boundary
  // values. This is fixed up by setting all boundary nodes explicit to the
  // right value:
  template <int dim>
  void MinimalSurfaceProblem<dim>::set_boundary_values ()
  {
    std::map<unsigned int, double> boundary_values;
    VectorTools::interpolate_boundary_values (dof_handler,
                                              0,
                                              BoundaryValues<dim>(),
                                              boundary_values);
    for (std::map<unsigned int, double>::const_iterator
         p = boundary_values.begin();
         p != boundary_values.end(); ++p)
      present_solution(p->first) = p->second;
  }

  // @sect4{MinimalSurfaceProblem::compute_residual}

  // In order to monitor convergence, we need a way to compute the norm of the
  // (discrete) residual, i.e., the norm of the vector
  // $\left<F(u^n),\varphi_i\right>$ with $F(u)=-\nabla \cdot \left(
  // \frac{1}{\sqrt{1+|\nabla u|^{2}}}\nabla u \right)$ as discussed in the
  // introduction. It turns out that (although we don't use this feature in
  // the current version of the program) one needs to compute the residual
  // $\left<F(u^n+\alpha^n\;\delta u^n),\varphi_i\right>$ when determining
  // optimal step lengths, and so this is what we implement here: the function
  // takes the step length $\alpha^n$ as an argument. The original
  // functionality is of course obtained by passing a zero as argument.
  //
  // In the function below, we first set up a vector for the residual, and
  // then a vector for the evaluation point $u^n+\alpha^n\;\delta u^n$. This
  // is followed by the same boilerplate code we use for all integration
  // operations:
  template <int dim>
  double MinimalSurfaceProblem<dim>::compute_residual (const double alpha) const
  {
    Vector<double> residual (dof_handler.n_dofs());

    Vector<double> evaluation_point (dof_handler.n_dofs());
    evaluation_point = present_solution;
    evaluation_point.add (alpha, newton_update);

    const QGauss<dim>  quadrature_formula(3);
    FEValues<dim> fe_values (fe, quadrature_formula,
                             update_gradients         |
                             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();

    Vector<double>               cell_rhs (dofs_per_cell);
    std::vector<Tensor<1, dim> > gradients(n_q_points);

    std::vector<unsigned int>    local_dof_indices (dofs_per_cell);

    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
    for (; cell!=endc; ++cell)
      {
        cell_rhs = 0;
        fe_values.reinit (cell);

        // The actual computation is much as in
        // assemble_system(). We first evaluate the gradients of
        // $u^n+\alpha^n\,\delta u^n$ at the quadrature points, then compute
        // the coefficient $a_n$, and then plug it all into the formula for
        // the residual:
        fe_values.get_function_gradients (evaluation_point,
                                          gradients);

        for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
          {
            const double coeff = 1/std::sqrt(1 +
                                             gradients[q_point] *
                                             gradients[q_point]);

            for (unsigned int i = 0; i < dofs_per_cell; ++i)
              cell_rhs(i) -= (fe_values.shape_grad(i, q_point)
                              * coeff
                              * gradients[q_point]
                              * fe_values.JxW(q_point));
          }

        cell->get_dof_indices (local_dof_indices);
        for (unsigned int i=0; i<dofs_per_cell; ++i)
          residual(local_dof_indices[i]) += cell_rhs(i);
      }

    // At the end of this function we also have to deal with the hanging node
    // constraints and with the issue of boundary values. With regard to the
    // latter, we have to set to zero the elements of the residual vector for
    // all entries that correspond to degrees of freedom that sit at the
    // boundary. The reason is that because the value of the solution there is
    // fixed, they are of course no "real" degrees of freedom and so, strictly
    // speaking, we shouldn't have assembled entries in the residual vector
    // for them. However, as we always do, we want to do exactly the same
    // thing on every cell and so we didn't not want to deal with the question
    // of whether a particular degree of freedom sits at the boundary in the
    // integration above. Rather, we will simply set to zero these entries
    // after the fact. To this end, we first need to determine which degrees
    // of freedom do in fact belong to the boundary and then loop over all of
    // those and set the residual entry to zero. This happens in the following
    // lines which we have already seen used in step-11:
    hanging_node_constraints.condense (residual);

    std::vector<bool> boundary_dofs (dof_handler.n_dofs());
    DoFTools::extract_boundary_dofs (dof_handler,
                                     ComponentMask(),
                                     boundary_dofs);
    for (unsigned int i=0; i<dof_handler.n_dofs(); ++i)
      if (boundary_dofs[i] == true)
        residual(i) = 0;

    // At the end of the function, we return the norm of the residual:
    return residual.l2_norm();
  }

  // @sect4{MinimalSurfaceProblem::determine_step_length}

  // As discussed in the introduction, Newton's method frequently does not
  // converge if we always take full steps, i.e., compute $u^{n+1}=u^n+\delta
  // u^n$. Rather, one needs a damping parameter (step length) $\alpha^n$ and
  // set $u^{n+1}=u^n+\alpha^n\; delta u^n$. This function is the one called
  // to compute $\alpha^n$.
  //
  // Here, we simply always return 0.1. This is of course a sub-optimal
  // choice: ideally, what one wants is that the step size goes to one as we
  // get closer to the solution, so that we get to enjoy the rapid quadratic
  // convergence of Newton's method. We will discuss better strategies below
  // in the results section.
  template <int dim>
  double MinimalSurfaceProblem<dim>::determine_step_length() const
  {
    return 0.1;
  }

  // @sect4{MinimalSurfaceProblem::run}

  // In the run function, we build the first grid and then have the top-level
  // logic for the Newton iteration. The function has two variables, one that
  // indicates whether this is the first time we solve for a Newton update and
  // one that indicates the refinement level of the mesh:
  template <int dim>
  void MinimalSurfaceProblem<dim>::run ()
  {
    unsigned int refinement = 0;
    bool         first_step = true;

    // As described in the introduction, the domain is the unit disk around
    // the origin, created in the same way as shown in step-6. The mesh is
    // globally refined twice followed later on by several adaptive cycles:
    GridGenerator::hyper_ball (triangulation);
    static const HyperBallBoundary<dim> boundary;
    triangulation.set_boundary (0, boundary);
    triangulation.refine_global(2);

    // The Newton iteration starts next. During the first step we do not have
    // information about the residual prior to this step and so we continue
    // the Newton iteration until we have reached at least one iteration and
    // until residual is less than $10^{-3}$.
    //
    // At the beginning of the loop, we do a bit of setup work. In the first
    // go around, we compute the solution on the twice globally refined mesh
    // after setting up the basic data structures. In all following mesh
    // refinement loops, the mesh will be refined adaptively.
    double previous_res = 0;
    while (first_step || (previous_res>1e-3))
      {
        if (first_step == true)
          {
            std::cout << "******** Initial mesh "
                      << " ********"
                      << std::endl;

            setup_system (true);
            set_boundary_values ();
          }
        else
          {
            ++refinement;
            std::cout << "******** Refined mesh " << refinement
                      << " ********"
                      << std::endl;

            refine_mesh();
          }

        // On every mesh we do exactly five Newton steps. We print the initial
        // residual here and then start the iterations on this mesh.
        //
        // In every Newton step the system matrix and the right hand side have
        // to be computed first, after which we store the norm of the right
        // hand side as the residual to check against when deciding whether to
        // stop the iterations. We then solve the linear system (the function
        // also updates $u^{n+1}=u^n+\alpha^n\;\delta u^n$) and output the
        // residual at the end of this Newton step:
        std::cout << "  Initial residual: "
                  << compute_residual(0)
                  << std::endl;

        for (unsigned int inner_iteration=0; inner_iteration<5; ++inner_iteration)
          {
            assemble_system ();
            previous_res = system_rhs.l2_norm();

            solve ();

            first_step = false;
            std::cout << "  Residual: "
                      << compute_residual(0)
                      << std::endl;
          }

        // Every fifth iteration, i.e., just before we refine the mesh again,
        // we output the solution as well as the Newton update. This happens
        // as in all programs before:
        DataOut<dim> data_out;

        data_out.attach_dof_handler (dof_handler);
        data_out.add_data_vector (present_solution, "solution");
        data_out.add_data_vector (newton_update, "update");
        data_out.build_patches ();
        const std::string filename = "solution-" +
                                     Utilities::int_to_string (refinement, 2) +
                                     ".vtk";
        std::ofstream output (filename.c_str());
        data_out.write_vtk (output);

      }
  }
}

// @sect4{The main function}

// Finally the main function. This follows the scheme of all other main
// functions:
int main ()
{
  try
    {
      using namespace dealii;
      using namespace Step15;

      deallog.depth_console (0);

      MinimalSurfaceProblem<2> laplace_problem_2d;
      laplace_problem_2d.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;
}


//  Copyright John Maddock 2007.
//  Copyright Paul A. Bristow 2010

//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!

#include <iostream>
using std::cout;  using std::endl;
#include <cerrno> // for ::errno

//[policy_eg_4

/*`
Suppose we want `C::foo()` to behave in a C-compatible way and set
`::errno` on error rather than throwing any exceptions.

We'll begin by including the needed header for our function:
*/

#include <boost/math/special_functions.hpp>
//using boost::math::tgamma; // Not needed because using C::tgamma.

/*`
Open up the "C" namespace that we'll use for our functions, and
define the policy type we want: in this case a C-style one that sets
::errno and returns a standard value, rather than throwing exceptions.

Any policies we don't specify here will inherit the defaults.
*/

namespace C
{ // To hold our C-style policy.
  //using namespace boost::math::policies; or explicitly:
  using boost::math::policies::policy;

  using boost::math::policies::domain_error;
  using boost::math::policies::pole_error;
  using boost::math::policies::overflow_error;
  using boost::math::policies::evaluation_error;
  using boost::math::policies::errno_on_error;

  typedef policy<
     domain_error<errno_on_error>,
     pole_error<errno_on_error>,
     overflow_error<errno_on_error>,
     evaluation_error<errno_on_error>
  > c_policy;

/*`
All we need do now is invoke the BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS
macro passing our policy type c_policy as the single argument:
*/

BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy)

} // close namespace C

/*`
We now have a set of forwarding functions defined in namespace C
that all look something like this:

``
template <class RealType>
inline typename boost::math::tools::promote_args<RT>::type
   tgamma(RT z)
{
   return boost::math::tgamma(z, c_policy());
}
``

So that when we call `C::tgamma(z)`, we really end up calling
`boost::math::tgamma(z, C::c_policy())`:
*/

int main()
{
   errno = 0;
   cout << "Result of tgamma(30000) is: "
      << C::tgamma(30000) << endl; // Note using C::tgamma
   cout << "errno = " << errno << endl; // errno = 34
   cout << "Result of tgamma(-10) is: "
      << C::tgamma(-10) << endl;
   cout << "errno = " << errno << endl; // errno = 33, overwriting previous value of 34.
}

/*`

Which outputs:

[pre
Result of C::tgamma(30000) is: 1.#INF
errno = 34
Result of C::tgamma(-10) is: 1.#QNAN
errno = 33
]

This mechanism is particularly useful when we want to define a project-wide policy,
and don't want to modify the Boost source,
or to set project wide build macros (possibly fragile and easy to forget).

*/
//] //[/policy_eg_4]


/******************************************************************************\
* Author: Matthew Beauregard Smith                                             *
* Affiliation: The University of Texas at Austin                               *
* Department: Oden Institute and Institute for Cellular and Molecular Biology  *
* PI: Edward Marcotte                                                          *
* Project: Protein Fluorosequencing                                            *
\******************************************************************************/

// Boost unit test framework (recommended to be the first include):
#include <boost/test/unit_test.hpp>

// File under test:
#include "leaf-node.h"

// Standard C++ library headers:
#include <vector>

// External headers:
#include "fakeit.hpp"

// Local project headers:
#include "test-util/fakeit.h"  // in test directory

namespace whatprot {
namespace kd_tree {

namespace {
using boost::unit_test::tolerance;
using fakeit::_;
using fakeit::Fake;
using fakeit::Mock;
using fakeit::Verify;
using fakeit::VerifyNoOtherInvocations;
using std::vector;
using whatprot::test_util::Close;
using whatprot::test_util::Ptr;
const double TOL = 0.000000001;
}  // namespace

// Class we can use as a template parameter for E.
class Vec {
public:
    Vec(vector<double> v) : v(v), hits(1) {}
    Vec(vector<double> v, int hits) : v(v), hits(hits) {}
    double& operator[](int d) {
        return v[d];
    }
    double operator[](int d) const {
        return v[d];
    }
    // Needed to check arguments with FakeIt.
    bool operator==(const Vec& other) const {
        return (v == other.v) && (hits == other.hits);
    }
    vector<double> v;
    int hits;
};

BOOST_AUTO_TEST_SUITE(kd_tree_suite)
BOOST_AUTO_TEST_SUITE(leaf_node_suite)

BOOST_AUTO_TEST_CASE(constructor_test, *tolerance(TOL)) {
    int d = 3;
    vector<Vec> vecs(2, Vec(vector<double>(3, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    BOOST_TEST(leaf.d == d);
    BOOST_TEST(leaf.begin == &vecs[0]);
    BOOST_TEST(leaf.end == &vecs[2]);
}

BOOST_AUTO_TEST_CASE(consider_success_test, *tolerance(TOL)) {
    int d = 3;
    vector<Vec> vecs(2, Vec(vector<double>(3, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    vector<double> query(3, 0);
    query[0] = 1.0;
    query[1] = 1.1;
    query[2] = 1.2;
    Vec entry(vector<double>(3, 0));
    entry[0] = 2.00;
    entry[1] = 2.11;
    entry[2] = 2.22;
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e9;
    leaf.consider(query, &entry, k_best);
    double dist_sq = 1.0 * 1.0 + 1.01 * 1.01 + 1.02 * 1.02;
    Verify(Method(k_best_mock, insert).Using(Close(dist_sq, TOL), Ptr(entry)));
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(consider_failure_test, *tolerance(TOL)) {
    int d = 3;
    vector<Vec> vecs(2, Vec(vector<double>(3, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    vector<double> query(3, 0);
    query[0] = 1.0;
    query[1] = 1.1;
    query[2] = 1.2;
    Vec entry(vector<double>(3, 0));
    entry[0] = 2.00;
    entry[1] = 2.11;
    entry[2] = 2.22;
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e-2;
    leaf.consider(query, &entry, k_best);
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(consider_success_big_d_test, *tolerance(TOL)) {
    int d = 6;
    vector<Vec> vecs(2, Vec(vector<double>(6, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    vector<double> query(6, 0);
    query[0] = 1.0;
    query[1] = 1.1;
    query[2] = 1.2;
    query[3] = 1.3;
    query[4] = 1.4;
    query[5] = 1.5;
    Vec entry(vector<double>(6, 0));
    entry[0] = 2.00;
    entry[1] = 2.11;
    entry[2] = 2.22;
    entry[3] = 2.33;
    entry[4] = 2.44;
    entry[5] = 2.55;
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e9;
    leaf.consider(query, &entry, k_best);
    double dist_sq = 1.0 * 1.0 + 1.01 * 1.01 + 1.02 * 1.02 + 1.03 * 1.03
                     + 1.04 * 1.04 + 1.05 * 1.05;
    Verify(Method(k_best_mock, insert).Using(Close(dist_sq, TOL), Ptr(entry)));
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(consider_failure_big_d_test, *tolerance(TOL)) {
    int d = 6;
    vector<Vec> vecs(2, Vec(vector<double>(6, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    vector<double> query(6, 0);
    query[0] = 1.0;
    query[1] = 1.1;
    query[2] = 1.2;
    query[3] = 1.3;
    query[4] = 1.4;
    query[5] = 1.5;
    Vec entry(vector<double>(6, 0));
    entry[0] = 2.00;
    entry[1] = 2.11;
    entry[2] = 2.22;
    entry[3] = 2.33;
    entry[4] = 2.44;
    entry[5] = 2.55;
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e-2;
    leaf.consider(query, &entry, k_best);
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(consider_barely_failure_big_d_test, *tolerance(TOL)) {
    int d = 6;
    vector<Vec> vecs(2, Vec(vector<double>(6, 0)));
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    vector<double> query(6, 0);
    query[0] = 1.0;
    query[1] = 1.1;
    query[2] = 1.2;
    query[3] = 1.3;
    query[4] = 1.4;
    query[5] = 1.5;
    Vec entry(vector<double>(6, 0));
    entry[0] = 2.00;
    entry[1] = 2.11;
    entry[2] = 2.22;
    entry[3] = 2.33;
    entry[4] = 2.44;
    entry[5] = 2.55;
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq =
            1.0 * 1.0 + 1.01 * 1.01 + 1.02 * 1.02 + 1.03 * 1.03 - 1e-7;
    leaf.consider(query, &entry, k_best);
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(search_success_test, *tolerance(TOL)) {
    int d = 3;
    vector<Vec> vecs(2, Vec(vector<double>(3, 0)));
    vecs[0][0] = 0.0;
    vecs[0][1] = 0.1;
    vecs[0][2] = 0.2;
    vecs[1][0] = 1.0;
    vecs[1][1] = 1.1;
    vecs[1][2] = 1.2;
    vector<double> query(3, 0);
    query[0] = 0.2;
    query[1] = 0.3;
    query[2] = 0.5;
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e9;
    leaf.search(query, k_best);
    double dst1 = 0.0;
    dst1 += (0.2 - 0.0) * (0.2 - 0.0);
    dst1 += (0.3 - 0.1) * (0.3 - 0.1);
    dst1 += (0.5 - 0.2) * (0.5 - 0.2);
    Vec v1(vector<double>(3, 0));
    v1[0] = 0.0;
    v1[1] = 0.1;
    v1[2] = 0.2;
    Verify(Method(k_best_mock, insert).Using(Close(dst1, TOL), Ptr(v1)))
            .Exactly(1);
    double dst2 = 0.0;
    dst2 += (0.2 - 1.0) * (0.2 - 1.0);
    dst2 += (0.3 - 1.1) * (0.3 - 1.1);
    dst2 += (0.5 - 1.2) * (0.5 - 1.2);
    Vec v2(vector<double>(3, 0));
    v2[0] = 1.0;
    v2[1] = 1.1;
    v2[2] = 1.2;
    Verify(Method(k_best_mock, insert).Using(Close(dst2, TOL), Ptr(v2)))
            .Exactly(1);
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_CASE(search_failure_test, *tolerance(TOL)) {
    int d = 3;
    vector<Vec> vecs(2, Vec(vector<double>(3, 0)));
    vecs[0][0] = 0.0;
    vecs[0][1] = 0.1;
    vecs[0][2] = 0.2;
    vecs[1][0] = 1.0;
    vecs[1][1] = 1.1;
    vecs[1][2] = 1.2;
    vector<double> query(3, 0);
    query[0] = 0.2;
    query[1] = 0.3;
    query[2] = 0.5;
    LeafNode<Vec, vector<double>> leaf(d, &vecs[0], &vecs[2]);
    Mock<KBest<Vec>> k_best_mock;
    Fake(Method(k_best_mock, insert));
    KBest<Vec>* k_best = &k_best_mock.get();
    k_best->kth_dist_sq = 1e-2;
    leaf.search(query, k_best);
    VerifyNoOtherInvocations(k_best_mock);
}

BOOST_AUTO_TEST_SUITE_END()  // leaf_node_suite
BOOST_AUTO_TEST_SUITE_END()  // kd_tree_suite

}  // namespace kd_tree
}  // namespace whatprot


/*    Copyright (c) 2010-2019, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 */

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#include <boost/make_shared.hpp>

#include "Tudat/Basics/testMacros.h"

#include "Tudat/Astrodynamics/Ephemerides/itrsToGcrsRotationModel.h"
#include "Tudat/Astrodynamics/EarthOrientation/UnitTests/sofaEarthOrientationCookbookExamples.h"
#include "Tudat/External/SpiceInterface/spiceInterface.h"

namespace tudat
{
namespace unit_tests
{

using namespace ephemerides;
using namespace earth_orientation;
using namespace basic_astrodynamics;

BOOST_AUTO_TEST_SUITE( test_itrs_to_gcrs_rotation )

//! Test ITRS <-> GCRS rotation by compariong against Spice
BOOST_AUTO_TEST_CASE( test_ItrsToGcrsRotationAgainstSpice )
{

    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "naif0012.tls" );
    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "earth_latest_high_prec.bpc" );
    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "earth_fixed.tf" );

    // Create rotation model
    std::shared_ptr< GcrsToItrsRotationModel > earthRotationModel =
            std::make_shared< GcrsToItrsRotationModel >(
                earth_orientation::createStandardEarthOrientationCalculator( ) );

    // Compare spice vs. Tudat for list of evaluation times
    std::vector< double > testTimes;
    testTimes.push_back( 1.0E8 );
    testTimes.push_back( 1.0E7 );
    testTimes.push_back( 0.0 );
    for( unsigned test = 0; test < testTimes.size( ); test++ )
    {
        Eigen::Matrix3d sofaRotation = earthRotationModel->getRotationToBaseFrame( testTimes.at( test ) ).toRotationMatrix( );
        Eigen::Matrix3d sofaRotationDerivative = earthRotationModel->getDerivativeOfRotationToBaseFrame( testTimes.at( test ) );
        Eigen::Matrix3d spiceRotation = spice_interface::computeRotationQuaternionBetweenFrames(
                    "ITRF93", "J2000", testTimes.at( test ) ).toRotationMatrix( );
        Eigen::Matrix3d spiceRotationDerivative = spice_interface::computeRotationMatrixDerivativeBetweenFrames(
                    "ITRF93", "J2000", testTimes.at( test ) );

        // Check whether Spice and Tudat give same result. Note that Spice model is not accurate up to IERS standards. Comparison
        // is done at 10 cm position difference on Earth surface (per component).
        double tolerance = 0.1 / 6378.0E3;

        for( unsigned int i = 0; i < 3; i++ )
        {
            for( unsigned int j = 0; j < 3; j++ )
            {
                BOOST_CHECK_SMALL( sofaRotation( i, j ) - spiceRotation( i, j ), tolerance );
                BOOST_CHECK_SMALL( sofaRotationDerivative( i, j ) - spiceRotationDerivative( i, j ), 5.0E-12 );

            }
        }
    }
}

//! Test ITRS <-> GCRS rotation by compariong against Sofa
BOOST_AUTO_TEST_CASE( test_ItrsToGcrsRotationAgainstSofaCookbook )
{

    // Get UTC time for evaluation
    int year = 2007;
    int month = 4;
    int day = 5;
    int hour = 12;
    int minutes = 0;
    double seconds = 0.0;
    double sofaCookbookTime = convertCalendarDateToJulianDaysSinceEpoch(
                year, month, day, hour, minutes, seconds, JULIAN_DAY_ON_J2000 ) *
            physical_constants::JULIAN_DAY;

    // Create Earth rotation model
    std::shared_ptr< GcrsToItrsRotationModel > earthRotationModelFromUtc =
            std::make_shared< GcrsToItrsRotationModel >(
                earth_orientation::createStandardEarthOrientationCalculator( ),
                utc_scale );

    // Test Tudat vs. Sofa implementations, with default Sofa EOP corrections (as defined in cookbook
    {
        Eigen::Matrix3d sofaCookbookResult = getSofaEarthOrientationExamples( 3 ).transpose( );
        Eigen::Matrix3d tudatResult = earthRotationModelFromUtc->getRotationToBaseFrame( sofaCookbookTime ).toRotationMatrix( );

        // Check sofa against Tudat result, small difference due to slightly different values of EOP corrections.
        for( unsigned int i = 0; i < 3; i++ )
        {
            for( unsigned int j = 0; j < 3; j++ )
            {
                BOOST_CHECK_SMALL( sofaCookbookResult( i, j ) - tudatResult( i, j ), 2.0E-9 );
            }
        }
    }

    // Test Tudat vs. Sofa implementations with identical EOP corrections.
    {
        // Set current time in UTC and TT
        double interpolationUtc = sofaCookbookTime;
        double interpolationTt = earthRotationModelFromUtc->getAnglesCalculator( )->getTerrestrialTimeScaleConverter( )->
                getCurrentTime( utc_scale, tt_scale, interpolationUtc );

        // Get EOP corrections
        double Xcorrection = earthRotationModelFromUtc->getAnglesCalculator( )->getPrecessionNutationCalculator( )->
                getDailyCorrectionInterpolator( )->interpolate( interpolationUtc ).x( );
        double Ycorrection = earthRotationModelFromUtc->getAnglesCalculator( )->getPrecessionNutationCalculator( )->
                getDailyCorrectionInterpolator( )->interpolate( interpolationUtc ).y( );
        double xPolarMotion = earthRotationModelFromUtc->getAnglesCalculator( )->getPolarMotionCalculator( )->
                getPositionOfCipInItrs( interpolationTt, interpolationUtc ).x( );
        double yPolarMotion = earthRotationModelFromUtc->getAnglesCalculator( )->getPolarMotionCalculator( )->
                getPositionOfCipInItrs( interpolationTt, interpolationUtc ).y( );
        double ut1Correction = earthRotationModelFromUtc->getAnglesCalculator( )->getTerrestrialTimeScaleConverter( )->
                getUt1Correction( utc_scale, Time( sofaCookbookTime ) );

        // Compute Sofa rotation matrix
        Eigen::Matrix3d  sofaCookbookResult = getSofaEarthOrientationExamples(
                    3, unit_conversions::convertRadiansToArcSeconds( Xcorrection ) * 1000.0,
                    unit_conversions::convertRadiansToArcSeconds( Ycorrection ) * 1000.0,
                    unit_conversions::convertRadiansToArcSeconds( xPolarMotion ),
                    unit_conversions::convertRadiansToArcSeconds( yPolarMotion ), ut1Correction ).transpose( );

        // Compute Tudat rotation matrix
        Eigen::Matrix3d tudatResult = earthRotationModelFromUtc->getRotationToBaseFrame( sofaCookbookTime ).toRotationMatrix( );

        // Check sofa against Tudat result, small difference due to rounding errors, in particular in Earth rotation angle
        for( unsigned int i = 0; i < 3; i++ )
        {
            for( unsigned int j = 0; j < 3; j++ )
            {
                if( i < 2 && j < 2 )
                {
                    BOOST_CHECK_SMALL( sofaCookbookResult( i, j ) - tudatResult( i, j ), 1.0E-11 );
                }
                else
                {
                    BOOST_CHECK_SMALL( sofaCookbookResult( i, j ) - tudatResult( i, j ), 1.0E-14 );
                }
            }
        }

        // Compute Tudat rotation matrix with high-precision time input
        long double sofaCookbookExtendedTime = convertCalendarDateToJulianDaysSinceEpoch< long double >(
                    year, month, day, hour, minutes, seconds, JULIAN_DAY_ON_J2000 ) *
                physical_constants::JULIAN_DAY_LONG;
        Eigen::Matrix3d tudatResultPrecise = earthRotationModelFromUtc->getRotationToBaseFrameFromExtendedTime(
                    Time( sofaCookbookExtendedTime ) ).toRotationMatrix( );

        // Check sofa against Tudat result
        for( unsigned int i = 0; i < 3; i++ )
        {
            for( unsigned int j = 0; j < 3; j++ )
            {
                BOOST_CHECK_SMALL( sofaCookbookResult( i, j ) - tudatResultPrecise( i, j ), 1.0E-15 );
            }
        }
    }
}

BOOST_AUTO_TEST_SUITE_END( )

}

}


/*
 [auto_generated]
 libs/numeric/odeint/test/resizing.cpp

 [begin_description]
 This file tests the resizing mechanism of odeint.
 [end_description]

 Copyright 2010-2012 Karsten Ahnert
 Copyright 2010-2012 Mario Mulansky

 Distributed under the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or
 copy at http://www.boost.org/LICENSE_1_0.txt)
 */

// disable checked iterator warning for msvc
#include <boost/config.hpp>
#ifdef BOOST_MSVC
    #pragma warning(disable:4996)
#endif

#define BOOST_TEST_MODULE odeint_resize

#include <vector>
#include <cmath>

#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/utility.hpp>
#include <boost/type_traits/integral_constant.hpp>

#include <boost/test/unit_test.hpp>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>

#include <boost/numeric/odeint/stepper/euler.hpp>
#include <boost/numeric/odeint/stepper/runge_kutta4_classic.hpp>
#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
#include <boost/numeric/odeint/algebra/vector_space_algebra.hpp>

#include <boost/numeric/odeint/util/resizer.hpp>
#include <boost/numeric/odeint/util/is_resizeable.hpp>

#include "resizing_test_state_type.hpp"

using namespace boost::unit_test;
using namespace boost::numeric::odeint;

namespace mpl = boost::mpl;

void constant_system( const test_array_type &x , test_array_type &dxdt , double t ) { dxdt[0] = 1.0; }

BOOST_AUTO_TEST_SUITE( check_resize_test )

typedef euler< test_array_type , double , test_array_type , double , range_algebra , default_operations , never_resizer > euler_manual_type;
typedef euler< test_array_type , double , test_array_type , double , range_algebra , default_operations , initially_resizer > euler_initially_type;
typedef euler< test_array_type , double , test_array_type , double , range_algebra , default_operations , always_resizer > euler_always_type;

typedef runge_kutta4_classic< test_array_type , double , test_array_type , double , range_algebra , default_operations , never_resizer > rk4_manual_type;
typedef runge_kutta4_classic< test_array_type , double , test_array_type , double , range_algebra , default_operations , initially_resizer > rk4_initially_type;
typedef runge_kutta4_classic< test_array_type , double , test_array_type , double , range_algebra , default_operations , always_resizer > rk4_always_type;

typedef runge_kutta4< test_array_type , double , test_array_type , double , range_algebra , default_operations , never_resizer > rk4_gen_manual_type;
typedef runge_kutta4< test_array_type , double , test_array_type , double , range_algebra , default_operations , initially_resizer > rk4_gen_initially_type;
typedef runge_kutta4< test_array_type , double , test_array_type , double , range_algebra , default_operations , always_resizer > rk4_gen_always_type;

typedef mpl::vector<
    mpl::vector< euler_manual_type , mpl::int_<1> , mpl::int_<0> > ,
    mpl::vector< euler_initially_type , mpl::int_<1> , mpl::int_<1> > ,
    mpl::vector< euler_always_type , mpl::int_<1> , mpl::int_<3> > ,
    mpl::vector< rk4_manual_type , mpl::int_<5> , mpl::int_<0> > ,
    mpl::vector< rk4_initially_type , mpl::int_<5> , mpl::int_<1> > ,
    mpl::vector< rk4_always_type , mpl::int_<5> , mpl::int_<3> > ,
    mpl::vector< rk4_gen_manual_type , mpl::int_<5> , mpl::int_<0> > ,
    mpl::vector< rk4_gen_initially_type , mpl::int_<5> , mpl::int_<1> > ,
    mpl::vector< rk4_gen_always_type , mpl::int_<5> , mpl::int_<3> >
    >::type resize_check_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( test_resize , T, resize_check_types )
{
    typedef typename mpl::at< T , mpl::int_< 0 > >::type stepper_type;
    const size_t resize_calls = mpl::at< T , mpl::int_< 1 > >::type::value;
    const size_t multiplicity = mpl::at< T , mpl::int_< 2 > >::type::value;
    adjust_size_count = 0;

    stepper_type stepper;
    test_array_type x;
    stepper.do_step( constant_system , x , 0.0 , 0.1 );
    stepper.do_step( constant_system , x , 0.0 , 0.1 );
    stepper.do_step( constant_system , x , 0.0 , 0.1 );

    BOOST_TEST_MESSAGE( "adjust_size_count : " << adjust_size_count );
    BOOST_CHECK_MESSAGE( adjust_size_count == resize_calls * multiplicity , "adjust_size_count : " << adjust_size_count << " expected: " << resize_calls * multiplicity );
}

BOOST_AUTO_TEST_SUITE_END()


//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//

#define BOOST_TEST_MODULE TestSortByKey
#include <boost/test/unit_test.hpp>

#include <boost/compute/system.hpp>
#include <boost/compute/algorithm/sort_by_key.hpp>
#include <boost/compute/algorithm/is_sorted.hpp>
#include <boost/compute/container/vector.hpp>

#include "check_macros.hpp"
#include "context_setup.hpp"

namespace compute = boost::compute;

// test trivial sorting of zero element vectors
BOOST_AUTO_TEST_CASE(sort_int_0)
{
    compute::vector<int> keys(context);
    compute::vector<int> values(context);
    BOOST_CHECK_EQUAL(keys.size(), size_t(0));
    BOOST_CHECK_EQUAL(values.size(), size_t(0));
    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end()) == true);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end()) == true);
    compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
}

// test trivial sorting of one element vectors
BOOST_AUTO_TEST_CASE(sort_int_1)
{
    int keys_data[] = { 11 };
    int values_data[] = { 100 };

    compute::vector<int> keys(keys_data, keys_data + 1, queue);
    compute::vector<int> values(values_data, values_data + 1, queue);

    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);

    compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
}

// test trivial sorting of two element vectors
BOOST_AUTO_TEST_CASE(sort_int_2)
{
    int keys_data[] = { 4, 2 };
    int values_data[] = { 42, 24 };

    compute::vector<int> keys(keys_data, keys_data + 2, queue);
    compute::vector<int> values(values_data, values_data + 2, queue);

    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == false);

    compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);

    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
}

BOOST_AUTO_TEST_CASE(sort_char_by_int)
{
    int keys_data[] = { 6, 2, 1, 3, 4, 7, 5, 0 };
    char values_data[] = { 'g', 'c', 'b', 'd', 'e', 'h', 'f', 'a' };

    compute::vector<int> keys(keys_data, keys_data + 8, queue);
    compute::vector<char> values(values_data, values_data + 8, queue);

    compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);

    CHECK_RANGE_EQUAL(int, 8, keys, (0, 1, 2, 3, 4, 5, 6, 7));
    CHECK_RANGE_EQUAL(char, 8, values, ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'));
}

BOOST_AUTO_TEST_CASE(sort_int_and_float)
{
    int n = 1024;
    std::vector<int> host_keys(n);
    std::vector<float> host_values(n);
    for(int i = 0; i < n; i++){
        host_keys[i] = n - i;
        host_values[i] = (n - i) / 2.f;
    }

    compute::vector<int> keys(host_keys.begin(), host_keys.end(), queue);
    compute::vector<float> values(host_values.begin(), host_values.end(), queue);

    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == false);

    compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);

    BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
    BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
}

BOOST_AUTO_TEST_SUITE_END()


/**\file
 * \page "Unit Tests"
 *
 * Source: main.cpp (current working version of test code here)
 *
 * **Unit tests for C++ classes for Category datatype, RDataframe7
 *         datatype and UtilCSV37 CSV Manipulation**
 *
 *
 * @author David York <david@debian2x8david>
 * @date Sunday September 4, 2016
 * @version 0.3
 *
 * @brief This is the main() module for Unit testing of the classes related to
 *        the RDataframe data type ( Dataframe )and relevant other code including
 *        that for the category data type the node data type ( Node ) and the CSV
 *        file utilities ( UtilCSV ).
 *
 *
 * © 2016 David York
 */
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <tuple>
#include <algorithm>
#include <typeinfo>
#include <cxxabi.h>
#include <array>
#include <initializer_list>
#include <boost/any.hpp>

#include "node.hpp"
#include "dataframe.hpp"
#include "utilCSV.hpp"
#include "category.hpp"

using namespace std;

/**
 * \page "Unit Tests"
 *  @brief The main() function is a non-member function related to testing of the
 *  classes  Node, RDataframe, Category, UtilCSV
 * \fn "the main function"
 *  The Unit Test suite for the Node and Dataframe classes
 *  @param argc, an int argument (optional)
 *  @param argv, a character array
 *  @return an int, 0 if runs successfully (ie. no errors)
 */

int main(int argc, char **argv)
{
/**
 * \page " "
 * \section "RDataframe Unit Tests"
 *  \subsection "Test Documentation"
 * This part of the main() function is related to both the Node class
 * and the Dataframe class. When run is complete it will have called all
 * functions of the two classes as well as any external calls to the UtilsCSV
 * library in order to test import of disk file datasets into the Dataframe
 * objects.
 */

    cout << "   Dataframe Unit Test Suite:" << endl;
    cout << "   =========================" << endl << endl;
    cout << "       Getting test data. . ." << endl << endl;
    /** Make working data arrays for unit tests
    *   from AirPassengers.csv, a base R dataset */
    initializer_list<int> data[13];
    initializer_list<string> colHead = {"Date","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    data[0] = {1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960};
    data[1] = {112, 115, 145, 171, 196, 204, 242, 284, 315, 340, 360, 417};
    data[2] = {118, 126, 150, 180, 196, 188, 233, 277, 301, 318, 342, 391};
    data[3] = {132, 141, 178, 193, 236, 235, 267, 317, 356,362, 406, 419};
    data[4] = {129, 135, 163, 181, 235, 227, 269, 313, 348, 348, 396, 461};
    data[5] = {121, 125, 172, 183, 229, 234, 270, 318, 355, 363, 420, 472};
    data[6] = {135, 149, 178, 218, 243, 264, 315, 374, 422, 435, 472, 535};
    data[7] = {148, 170, 199, 230, 264, 302, 364, 413, 465, 491, 548, 622};
    data[8] = {148, 170, 199, 242, 272, 293, 347, 405, 467, 505, 559, 606};
    data[9] = {136, 158, 184, 209, 237, 259, 312, 355, 404, 404, 463, 508};
    data[10] = {119, 133, 162, 191, 211, 229, 274, 306, 347, 359, 407, 461};
    data[11] = {104, 114, 146, 172, 180, 203, 237, 271, 305, 310, 362, 390};
    data[12] = {118, 140, 166, 194, 201, 229, 278, 306, 336, 337, 405, 432};
    vector<string> cnames {colHead};
    vector<int> year {data[0]};
    vector<int> jan {data[1]};
    vector<int> feb {data[2]};
    vector<int> mar {data[3]};
    vector<int> apr {data[4]};
    vector<int> may {data[5]};
    vector<int> jun {data[6]};
    vector<int> jul {data[7]};
    vector<int> aug {data[8]};
    vector<int> sep {data[9]};
    vector<int> oct {data[10]};
    vector<int> nov {data[11]};
    vector<int> dec {data[12]};

    /** NODE TESTS */
    cout << endl << "  Node Specific Tests " << endl;
    cout << "  ------------------- " << endl << endl;
    string vName;
    string vType;
    int vNumber;
    void* pVData;
    int r;

    /** test default constructors*/
    vName = "Date";
    vType = "int";
    vNumber = 0;
    pVData =&year;
    r = year.size();
    node variable1;
    variable1.setNodeContent(r, vName, vType, vNumber, pVData);
    cout << " NODE #: " << vNumber << endl;
    variable1.displayNode();
    cout << endl;

 /** test full constructors */
    vName = "Jan";
    vType = "int";
    vNumber = 1;
    pVData = &jan;
    r = jan.size();

    node variable2(r, vName, vType, vNumber, pVData);
    cout << "NODE #: " << vNumber << endl;
    variable2.displayNode();
    cout << endl << endl;

    /** test various class methods */
    /**    Setters */
    cout << " testing setters . . ."<<endl;
    cout << "   change variable name and type" << endl;
    cout<<endl;
    variable2.setVarName("other");
    variable2.setVarType("long");
    cout << "   show new or adjusted name and type"<< endl;
    variable2.displayName_Type();
    cout << "   change position number " <<endl;
    variable2.setVarNumber(3);
    variable2.setVarDataRows(30);
    cout << "   show changed position number and nrows and display the whole amended node," << endl;
    variable2.displayNode();
    cout<<endl;

    r = jan.size();
    cout << "  return contents to original and display the node again." <<endl;
    variable2.setNodeContent(r, vName, vType, vNumber, pVData);
    cout << " show meta-data and data vector now . . " << endl;
    cout << " NODE #: " << vNumber << endl;
    variable2.displayNode();
    cout << endl << endl;

    cout << " Check Node.toString() function, " << endl << variable2.toString() << endl << endl;

    /**    Getters */
    cout << " Check All the Getters," << endl;
    cout << "   getting variable data pointer: " << variable1.getVarData() << endl;
    cout << "   getting variable name:         " << variable1.getVarName() << endl;
    cout << "   getting variable type:         " << variable1.getVarType() << endl;
    cout << "   getting variable position number: " << variable1.getVarNumber() << endl;
    cout << "   getting number of variable data rows: " << variable1.getNRows() << endl<< endl;
    cout << "   get variable data range:          " << endl;
    void* retDataPtr = variable2.getVarDataRange(4,10);
    vector<int>* extrIntDataPtr = ((vector<int>*)retDataPtr);
    cout << "returned recast vector size: " << (*extrIntDataPtr).size() << endl;
    vector<int> extrData = (*extrIntDataPtr);
    cout << "returned recast vector size: " << extrData.size() << endl;
    for(unsigned int i = 0; i < extrData.size(); ++i) {
                    cout << extrData[i] << endl;
                }
    cout << endl;

    /** Testing different data types
     *  string */
    cout << endl << endl;
    cout << "  Create and test a string variable " << endl << endl;
    initializer_list<string> strData = {"Date","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    vector<string> months {strData};
    vName = "Month";
    vType = "string";
    vNumber = 0;
    pVData = &months;
    r = months.size();

    node variable5s(r, vName, vType, vNumber, pVData);
    cout << "NODE #: " << vNumber << endl;
    variable5s.displayNode();

    cout << endl;
    cout << "extract some elements fro the string variable vector" << endl;
    retDataPtr = variable5s.getVarDataRange(4,10);
    vector<string>* extrStrDataPtr = ((vector<string>*)retDataPtr);
    cout << "returned recast vector size: " << (*extrStrDataPtr).size() << endl;
    vector<string> extrStrData = (*extrStrDataPtr);
    cout << "returned recast vector size: " << extrStrData.size() << endl;
    for(unsigned int i = 0; i < extrStrData.size(); ++i) {
        cout << extrStrData[i] << endl;
    }
    cout << endl << endl;

    /** double type */
    cout << "  Create and test a double variable" << endl << endl;
    initializer_list<double> dblData {2.3413,5.23, 23.56, 198.0, 7.11042, 734.9992, 19.1945, 3.1415962, 45, 30.2, 7565.11, 629.023};
    vector<double> rndNumbs {dblData};
    vName = "randoms";
    vType = "double";
    vNumber = 0;
    pVData = &rndNumbs;
    r = rndNumbs.size();

    node variable5d(r, vName, vType, vNumber, pVData);
    cout << "NODE #: " << vNumber << endl;
    variable5d.displayNode();

    cout << endl;
    cout << "extract some elements fro the double variable vector" << endl;
    retDataPtr = variable5d.getVarDataRange(4,10);
    vector<double>* extrDblDataPtr = ((vector<double>*)retDataPtr);
    cout << "returned recast vector size: " << (*extrDblDataPtr).size() << endl;
    vector<double> extrDblData = (*extrDblDataPtr);
    cout << "returned recast vector size: " << extrDblData.size() << endl;
    for(unsigned int i = 0; i < extrDblData.size(); ++i) {
        cout << extrDblData[i] << endl;
    }
    cout << endl;
    cout << endl << endl;
    cout << "  ************************************* " << endl <<endl;
    /** DATAFRAME TESTS */
    /** test default constructors*/
    cout << "  Dataframe SpecificTests "<< endl;
    cout << "  ----------------------- " <<endl << endl;
    dataframe dfTest;
    cout << "  dfTest an empty dataframe constructed, awaits meta-data and data variables " << endl<<endl;

    /** test full constructors */

    /** test various class methods */

    cout << endl << "  ************************************* " << endl;

/**
 * \section "UtilCSV Unit Tests"
 *  \subsection "Test Documentation"
 * This part of the main() function is related to both the UtilCSB class
 * and thefunctions there-in. When the run is complete it will have called
 * all functions of the class as well as any external calls in
 * order to test import of disk file datasets.
 */

    /** UTILCSV TESTS*/
    string frmCSV ="./data/AirPassengersNoHeader.csv";
    bool hHeader = true;
    utilCSV Airpass(frmCSV, hHeader);
    cout << "  UtilCSV Unit Test Suite:" << endl;
    cout << "  =======================" << endl<< endl;
    cout << " Getting test data. . ."<< endl<<endl;
    cout << " no. cols: " << Airpass.getNcols() << endl;
    cout << " no. rows: " << Airpass.getNrows() << endl;
    Airpass.displayInternCSV();
    Airpass.displayColNames();
    Airpass.displayStrDataStruct();
    vector<vector<string> > strDStruct = Airpass.getStrDataStruct();
    Airpass.writeCSV(strDStruct, "datafile.csv");
    vector<string> newCols;
        newCols.push_back("Date");
        newCols.push_back("Jan");
        newCols.push_back("Feb");
        newCols.push_back("Mar");
        newCols.push_back("Apr");
        newCols.push_back("May");
        newCols.push_back("Jun");
        newCols.push_back("Jul");
        newCols.push_back("Aug");
        newCols.push_back("Sep");
        newCols.push_back("Oct");
        newCols.push_back("Nov");
        newCols.push_back("Dec");
    Airpass.setColNames(newCols);
    Airpass.displayInternCSV();
    Airpass.displayColNames();
    Airpass.displayStrDataStruct();
    vector<vector<string> > sDS = Airpass.getStrDataStruct();
    Airpass.writeCSV(Airpass.getStrDataStruct(), "./data/newHeader.csv");
    cout << endl << endl;

    // Now make a df from the string data structure and stor in a data frame
    dataframe dfAirpass("dfAirPass", 11, 13);
    cout << "  New dataframe:  " << dfAirpass.getDataFrameName() << endl<< endl;
    cout << "  old string frame: again " << endl << endl<< endl;
    Airpass.displayStrDataStruct();
    vector<vector<string> > sDStruct = sDS;
    // read nR = 11 elements into column colNumber = 12
    dfAirpass.readRowsSDS(sDS, 11, 5);
    // read all 11 elements of all 12 columns
    dfAirpass.convertCSVtoDF(sDStruct, 11, 13);

    /** Category data type TESTS */
    cout << endl<<endl<<endl;
    cout << "  ==============================" << endl;
    cout << "  CATEGORY type Unit Test Suite:" << endl;
    cout << "  ==============================" << endl<< endl;
    cout << endl<<endl;

    cout << "   All Tests Completed"<< endl;

    return 0;
}


//  (C) Copyright Gennadiy Rozental 2001-2015.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  See http://www.boost.org/libs/test for the library home page.
//

//[snippet12
#define __BOOST_TEST_MODULE__ MyTest
#include <boost/test/unit_test.hpp>

int add( int i, int j ) { return i + j; }

__BOOST_AUTO_TEST_CASE__(my_test)
{
  // six ways to detect and report the same error:

  // continues on error
  __BOOST_TEST__( add(2, 2) == 4 );          /*<
                                          This approach uses tool __BOOST_TEST__, which displays an error message (by default on `std::cout`) that includes
                                          the expression that failed, as well as the values on the two side of the equation, the source file name,
                                          and the source file line number. It also increments the error count. At program termination,
                                          the error count will be displayed automatically by the __UTF__.>*/

  // throws on error
  __BOOST_TEST_REQUIRE__( add(2, 2) == 4 );  /*<
                                          This approach uses tool __BOOST_TEST_REQUIRE__, is similar to approach #1, except that after displaying the error,
                                          an exception is thrown, to be caught by the __UTF__. This approach is suitable when writing an
                                          explicit test program, and the error would be so severe as to make further testing impractical.
                                          >*/

  //continues on error
  if (add(2, 2) != 4)
    __BOOST_ERROR__( "Ouch..." );            /*<
                                          This approach is similar to approach #1, except that the error detection and error reporting are coded separately.
                                          This is most useful when the specific condition being tested requires several independent statements and/or is
                                          not indicative of the reason for failure.
                                          >*/

  // throws on error
  if (add(2, 2) != 4)
    __BOOST_FAIL__( "Ouch..." );             /*<
                                         This approach is similar to approach #2, except that the error detection and error reporting are coded separately.
                                         This is most useful when the specific condition being tested requires several independent statements and/or is
                                         not indicative of the reason for failure.
                                         >*/

  // throws on error
  if (add(2, 2) != 4)
    throw "Ouch...";                     /*<
                                         This approach throws an exception, which will be caught and reported by the __UTF__. The error
                                         message displayed when the exception is caught will be most meaningful if the exception is derived from
                                         `std::exception`, or is a `char*` or `std::string`.
                                         >*/

  // continues on error
  __BOOST_TEST__( add(2, 2) == 4,            /*<
                                                           This approach uses tool __BOOST_TEST__ with additional message argument, is similar to approach #1,
                                                           except that similar to the approach #3 displays an alternative error message specified as a second argument.
                                                           >*/
              "2 plus 2 is not 4 but " << add(2, 2));
}
//]


// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

// Copyright Paul A. Bristow 2015.
// Copyright Christopher Kormanyos 2015.
// Copyright Nikhar Agrawal 2015.

// This file is written to be included from a Quickbook .qbk document.
// It can be compiled by the C++ compiler, and run. Any output can
// also be added here as comment or included or pasted in elsewhere.
// Caution: this file contains Quickbook markup as well as code
// and comments: don't change any of the special comment markups!

// This file also includes Doxygen-style documentation about the function of the code.
// See http://www.doxygen.org for details.

//! \file

// Below are snippets of code that can be included into a Quickbook file.

#include <iostream>
#include <iomanip>
#include <exception>
#include <typeinfo>
#include <limits>

#include <boost/cstdint.hpp>

//[fixed_point_include_1
#include <boost/fixed_point/fixed_point.hpp>
//] [/fixed_point_include_1]

/*
! Show numeric_limits values for a type.
\tparam T floating-point, fixed-point type.
\param os std::ostream, default @c std::cout
*/

// static int Functions to access template parameters for fixed_point
// that are missing for fundamental integral and floating-point types.
// Version selected on whether is not arithmetic, is floating_point or is integral.

template <typename NumericalType,
          typename EnableType = void>
struct numerical_details
{
  static int get_range     () { return 0; }
  static int get_resolution() { return 0; }
};

/*! Deduce fixed-point if @c std::is_class (so exclude @c bool, @c int...) and not arithmetic (exclude @c float, @c double...).
*/
template <typename NumericalType>
struct numerical_details<NumericalType,
                         typename std::enable_if<   (std::is_arithmetic<NumericalType>::value == false)
                                                 && (std::is_class<NumericalType>::value      == true)>::type>
{
  static int get_range     () { return NumericalType::range; }
  static int get_resolution() { return NumericalType::resolution; }
};

/*! Deduce fundamental floating-point type @c float, @c double or @c long double.
*/

template <typename NumericalType>
struct numerical_details<NumericalType,
                         typename std::enable_if<std::is_floating_point<NumericalType>::value>::type>
{
  static int get_range     () { return 0; }
  static int get_resolution() { return std::numeric_limits<NumericalType>::digits; }
};

/*! Deduce fundamental integral type.
*/
template <typename NumericalType>
struct numerical_details<NumericalType,
                         typename std::enable_if<std::is_integral<NumericalType>::value>::type>
{
  static int get_range     () { return std::numeric_limits<NumericalType>::digits; }
  static int get_resolution() { return 0; }
};

template <typename T>
void show_fixed_point(std::ostream& os = std::cout)
{
  using boost::fixed_point::negatable;

  os.precision(std::numeric_limits<T>::max_digits10);

  os << "Numeric_limits of type: "
     << typeid(T).name()
     << "\n range        = " << numerical_details<T>::get_range() //
     << "\n resolution   = " << numerical_details<T>::get_resolution()
     << "\n radix        = " << std::numeric_limits<T>::radix  // Always 2 for fixed-point.
     << "\n digits       = " << std::numeric_limits<T>::digits; // Does not include any sign bit.

  if (std::is_signed<T>::value == true)
  {
    os << "\n signed "
       << "\n total bits =   " << std::numeric_limits<T>::digits + 1; // DOES include sign bit.
  }

  if (std::numeric_limits<T>::is_exact == false)
  { // epsilon has meaning.
    os << "\n epsilon      = " << std::numeric_limits<T>::epsilon();
  }
  else
  {
    os << "\n exact        = "  << std::numeric_limits<T>::is_exact;
  }

  // Avoid char values showing as a character or squiggle.
  BOOST_CONSTEXPR_OR_CONST bool is_any_character_type = (   std::is_same<T, signed char>::value
                                                         || std::is_same<T, unsigned char>::value
                                                         || std::is_same<T, char16_t>::value
                                                         || std::is_same<T, char32_t>::value);

  os << "\n lowest       = ";
  if(is_any_character_type)
  {
    os << static_cast<boost::int32_t>(std::numeric_limits<T>::lowest());
  }
  else
  {
    os << std::numeric_limits<T>::lowest();
  }

  BOOST_CONSTEXPR_OR_CONST bool is_8bit_character_type = (   std::is_same<T, signed char>::value
                                                          || std::is_same<T, unsigned char>::value);

  os << "\n min          = ";
  if(is_8bit_character_type)
  {
    os << static_cast<boost::int32_t>((std::numeric_limits<T>::min)());
  }
  else
  {
    os << (std::numeric_limits<T>::min)();
  }

  os << "\n max          = ";
  if(is_8bit_character_type)
  {
    os << static_cast<boost::int32_t>((std::numeric_limits<T>::max)());
  }
  else
  {
    os << (std::numeric_limits<T>::max)();
  }

  os << "\n max_exponent = " << std::numeric_limits<T>::max_exponent
     << "\n min_exponent = " << std::numeric_limits<T>::min_exponent
     << "\n digits10     = " << std::numeric_limits<T>::digits10
     << "\n max_digits10 = " << std::numeric_limits<T>::max_digits10
     << "\n"
     << std::endl;
} // template <typename T> void show_fixed_point

int main()
{
  using boost::fixed_point::negatable;

  typedef negatable<15,  -16> fixed_point_type_15m16;
  typedef negatable<11,  -20> fixed_point_type_11m20;
  typedef negatable< 0,  -31> fixed_point_type_0m31;
  typedef negatable<29,   -2> fixed_point_type_29m2;
  typedef negatable<0,  -168> fixed_point_type_0m168;
  typedef negatable<20, -148> fixed_point_type_20m148;

  try
  {
    std::cout.setf(std::ios_base::boolalpha | std::ios_base::showpoint); // Show any trailing zeros.
    std::cout << std::endl;

//[fixed_example_1

    // Show all the significant digits for this particular type.

    // Fundamental (built-in) integral types.
    show_fixed_point<bool>              ();
    show_fixed_point<signed char>       ();
    show_fixed_point<unsigned char>     ();
    show_fixed_point<char16_t>          (); // Shows as type unsigned short.
    show_fixed_point<char32_t>          (); // Shows as type unsigned int.
    show_fixed_point<short int>         ();
    show_fixed_point<unsigned short int>();
    show_fixed_point<int>               ();
    show_fixed_point<unsigned int>      ();

   // Fundamental (built-in) floating-point types.
    show_fixed_point<float>();
    // digits 24 (leaving 8 for decimal exponent).
    // epsilon 1.2e-7.

    show_fixed_point<double>();
    // digits 53 (leaving 10 for decimal exponent).
    // epsilon 2.2e-16.
    show_fixed_point<long double>();
    // Varies with compiler
    // Using MSVC double == long double

//] [/fixed_example_1]

// Some fixed_point types using only a single 8-bit byte (signed char).

//[fixed_point_15m16

    // Some fixed_point types using 32 bits, and more.
    show_fixed_point<fixed_point_type_15m16> (); // Even split bits between range and resolution.
    show_fixed_point<fixed_point_type_11m20> (); // More resolution than range.
    show_fixed_point<fixed_point_type_0m31>  (); // All bits used for resolution.
    show_fixed_point<fixed_point_type_29m2>  (); // Most bits used for range.
    show_fixed_point<fixed_point_type_0m168> ();
    show_fixed_point<fixed_point_type_20m148>();

    //std::cout << "fixed_point_type(123) / 100 = "
    //  << x // 1.22999573 is the nearest representation of decimal digit string 1.23.
    //  << std::endl;
  }
  catch (std::exception ex)
  {
    std::cout << ex.what() << std::endl;
  }
}

/*
//[fixed_point_type_examples_output_1

//] [/fixed_point_type_examples_output_1]
*/


/*
 [auto_generated]
 libs/numeric/odeint/test/n_step_iterator.cpp

 [begin_description]
 This file tests the n-step iterator.
 [end_description]

 Copyright 2009-2013 Karsten Ahnert
 Copyright 2009-2013 Mario Mulansky

 Distributed under the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or
 copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#define BOOST_TEST_MODULE odeint_n_step_iterator

#include <iterator>
#include <algorithm>
#include <vector>

#include <boost/numeric/odeint/config.hpp>
#include <boost/array.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/mpl/vector.hpp>

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>

#include <boost/numeric/odeint/iterator/n_step_iterator.hpp>
#include "dummy_steppers.hpp"
#include "dummy_odes.hpp"
#include "dummy_observers.hpp"

namespace mpl = boost::mpl;
using namespace boost::numeric::odeint;

typedef dummy_stepper::state_type state_type;
typedef dummy_stepper::value_type value_type;

BOOST_AUTO_TEST_SUITE( n_step_iterator_test )

typedef mpl::vector<
    dummy_stepper
    , dummy_dense_output_stepper
    > dummy_steppers;

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_stepper_iterator , Stepper , dummy_steppers )
{
    typedef n_step_iterator< Stepper , empty_system , state_type > iterator_type;
    state_type x = {{ 1.0 }};
    iterator_type iter1 = iterator_type( Stepper() , empty_system() , x , 0.0 , 0.1 , 10 );
    iterator_type iter2 = iter1;
    BOOST_CHECK_EQUAL( &(*iter1) , &(*iter2) );
    BOOST_CHECK_EQUAL( &(*iter1) , &x );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( assignment_stepper_iterator , Stepper , dummy_steppers )
{
    typedef n_step_iterator< Stepper , empty_system , state_type > iterator_type;
    state_type x1 = {{ 1.0 }} , x2 = {{ 2.0 }};
    iterator_type iter1 = iterator_type( Stepper() , empty_system() , x1 , 0.0 , 0.1 , 10 );
    iterator_type iter2 = iterator_type( Stepper() , empty_system() , x2 , 0.0 , 0.2 , 10 );
    BOOST_CHECK_EQUAL( &(*iter1) , &x1 );
    BOOST_CHECK_EQUAL( &(*iter2) , &x2 );
    BOOST_CHECK( !iter1.same( iter2 ) );
    iter2 = iter1;
    BOOST_CHECK_EQUAL( &(*iter1) , &x1 );
    BOOST_CHECK_EQUAL( &(*iter2) , &x1 );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( stepper_iterator_factory , Stepper , dummy_steppers )
{
    Stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
        make_n_step_iterator_begin( stepper , boost::ref( system ) , x , 0.0 , 0.1 , 10 ) ,
        make_n_step_iterator_end( stepper , boost::ref( system ) , x ) ,
        dummy_observer() );

    // dummy_steppers just add 0.25 at each step, the above for_each leads to 10 do_step calls so x should be 3.5
    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-13 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( stepper_range , Stepper , dummy_steppers )
{
    Stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_n_step_range( stepper , boost::ref( system ) , x , 0.0 , 0.1 , 10 ) ,
                     dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-13 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( stepper_iterator_with_reference_wrapper_factory , Stepper , dummy_steppers )
{
    Stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
        make_n_step_iterator_begin( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 0.1 , 10 ) ,
        make_n_step_iterator_end( boost::ref( stepper ) , boost::ref( system ) , x ) ,
        dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-13 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( stepper_range_with_reference_wrapper , Stepper , dummy_steppers )
{
    Stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_n_step_range( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 0.1 , 10 ) ,
                     dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-13 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( transitivity1 , Stepper , dummy_steppers )
{
    typedef n_step_iterator< Stepper , empty_system , state_type > stepper_iterator;

    state_type x = {{ 1.0 }};
    stepper_iterator first1( Stepper() , empty_system() , x , 2.5 , 0.1 , 0 );
    stepper_iterator last1( Stepper() , empty_system() , x );
    stepper_iterator last2( Stepper() , empty_system() , x );

    BOOST_CHECK( last1 == last2 );
    BOOST_CHECK( first1 != last1 );
    BOOST_CHECK( ++first1 == last1 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm , Stepper , dummy_steppers )
{
    typedef n_step_iterator< Stepper , empty_system , state_type > stepper_iterator;
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    stepper_iterator first( Stepper() , empty_system() , x , 0.0 , 0.1 , 3 );
    stepper_iterator last( Stepper() , empty_system() , x );

    std::copy( first , last , std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 4 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );

    BOOST_CHECK_CLOSE( x[0] , 1.75 , 1.0e-14 );     // the iterator should not iterate over the end
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm_negative_time_step , Stepper , dummy_steppers )
{
    typedef n_step_iterator< Stepper , empty_system , state_type > stepper_iterator;
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    stepper_iterator first( Stepper() , empty_system() , x , 0.3 , -0.1 , 3 );
    stepper_iterator last( Stepper() , empty_system() , x );

    std::copy( first , last , std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 4 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );

    BOOST_CHECK_CLOSE( x[0] , 1.75 , 1.0e-14 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm_with_factory , Stepper , dummy_steppers )
{
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    std::copy( make_n_step_iterator_begin( Stepper() , empty_system() , x , 0.0 , 0.1 , 3 ) ,
               make_n_step_iterator_end( Stepper() , empty_system() , x ) ,
               std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 4 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );

    BOOST_CHECK_CLOSE( x[0] , 1.75 , 1.0e-14 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm_with_range_factory , Stepper , dummy_steppers )
{
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    boost::range::copy( make_n_step_range( Stepper() , empty_system() , x , 0.0 , 0.1 , 3 ) ,
                        std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 4 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );

    BOOST_CHECK_CLOSE( x[0] , 1.75 , 1.0e-14 );
}

BOOST_AUTO_TEST_SUITE_END()