/* Author: Luca Heltai, Cataldo Manigrasso, 2009                  */

/*    $Id: step-34.cc 28376 2013-02-13 15:19:38Z heister $       */
/*                                                                */
/*    Copyright (C) 2009-2012 by 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 program starts with including a bunch of include files that we will use
// in the various parts of the program. Most of them have been discussed in
// previous tutorials already:
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/convergence_table.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/quadrature_selector.h>
#include <deal.II/base/parsed_function.h>
#include <deal.II/base/utilities.h>

#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/solver_control.h>
#include <deal.II/lac/solver_gmres.h>
#include <deal.II/lac/precondition.h>

#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_in.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/tria_boundary_lib.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_q.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping_q.h>

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

// And here are a few C++ standard header files that we will need:
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>

// The last part of this preamble is to import everything in the dealii
// namespace into the one into which everything in this program will go:
namespace Step34
{
  using namespace dealii;

  // @sect3{Single and double layer operator kernels}

  // First, let us define a bit of the boundary integral equation machinery.

  // The following two functions are the actual calculations of the single and
  // double layer potential kernels, that is $G$ and $\nabla G$. They are well
  // defined only if the vector $R = \mathbf{y}-\mathbf{x}$ is different from
  // zero.
  namespace LaplaceKernel
  {
    template <int dim>
    double single_layer(const Point<dim> &R)
    {
      switch (dim)
        {
        case 2:
          return (-std::log(R.norm()) / (2*numbers::PI) );

        case 3:
          return (1./( R.norm()*4*numbers::PI ) );

        default:
          Assert(false, ExcInternalError());
          return 0.;
        }
    }

    template <int dim>
    Point<dim> double_layer(const Point<dim> &R)
    {
      switch (dim)
        {
        case 2:
          return R / ( -2*numbers::PI * R.square());
        case 3:
          return R / ( -4*numbers::PI * R.square() * R.norm() );

        default:
          Assert(false, ExcInternalError());
          return Point<dim>();
        }
    }
  }

  // @sect3{The BEMProblem class}

  // The structure of a boundary element method code is very similar to the
  // structure of a finite element code, and so the member functions of this
  // class are like those of most of the other tutorial programs. In
  // particular, by now you should be familiar with reading parameters from an
  // external file, and with the splitting of the different tasks into
  // different modules. The same applies to boundary element methods, and we
  // won't comment too much on them, except on the differences.
  template <int dim>
  class BEMProblem
  {
  public:
    BEMProblem(const unsigned int fe_degree = 1,
               const unsigned int mapping_degree = 1);

    void run();

  private:

    void read_parameters (const std::string &filename);

    void read_domain();

    void refine_and_resize();

    // The only really different function that we find here is the assembly
    // routine. We wrote this function in the most possible general way, in
    // order to allow for easy generalization to higher order methods and to
    // different fundamental solutions (e.g., Stokes or Maxwell).
    //
    // The most noticeable difference is the fact that the final matrix is
    // full, and that we have a nested loop inside the usual loop on cells
    // that visits all support points of the degrees of freedom.  Moreover,
    // when the support point lies inside the cell which we are visiting, then
    // the integral we perform becomes singular.
    //
    // The practical consequence is that we have two sets of quadrature
    // formulas, finite element values and temporary storage, one for standard
    // integration and one for the singular integration, which are used where
    // necessary.
    void assemble_system();

    // There are two options for the solution of this problem. The first is to
    // use a direct solver, and the second is to use an iterative solver. We
    // opt for the second option.
    //
    // The matrix that we assemble is not symmetric, and we opt to use the
    // GMRES method; however the construction of an efficient preconditioner
    // for boundary element methods is not a trivial issue. Here we use a non
    // preconditioned GMRES solver. The options for the iterative solver, such
    // as the tolerance, the maximum number of iterations, are selected
    // through the parameter file.
    void solve_system();

    // Once we obtained the solution, we compute the $L^2$ error of the
    // computed potential as well as the $L^\infty$ error of the approximation
    // of the solid angle. The mesh we are using is an approximation of a
    // smooth curve, therefore the computed diagonal matrix of fraction of
    // angles or solid angles $\alpha(\mathbf{x})$ should be constantly equal
    // to $\frac 12$. In this routine we output the error on the potential and
    // the error in the approximation of the computed angle. Notice that the
    // latter error is actually not the error in the computation of the angle,
    // but a measure of how well we are approximating the sphere and the
    // circle.
    //
    // Experimenting a little with the computation of the angles gives very
    // accurate results for simpler geometries. To verify this you can comment
    // out, in the read_domain() method, the tria.set_boundary(1, boundary)
    // line, and check the alpha that is generated by the program. By removing
    // this call, whenever the mesh is refined new nodes will be placed along
    // the straight lines that made up the coarse mesh, rather than be pulled
    // onto the surface that we really want to approximate. In the three
    // dimensional case, the coarse grid of the sphere is obtained starting
    // from a cube, and the obtained values of alphas are exactly $\frac 12$
    // on the nodes of the faces, $\frac 34$ on the nodes of the edges and
    // $\frac 78$ on the 8 nodes of the vertices.
    void compute_errors(const unsigned int cycle);

    // Once we obtained a solution on the codimension one domain, we want to
    // interpolate it to the rest of the space. This is done by performing
    // again the convolution of the solution with the kernel in the
    // compute_exterior_solution() function.
    //
    // We would like to plot the velocity variable which is the gradient of
    // the potential solution. The potential solution is only known on the
    // boundary, but we use the convolution with the fundamental solution to
    // interpolate it on a standard dim dimensional continuous finite element
    // space. The plot of the gradient of the extrapolated solution will give
    // us the velocity we want.
    //
    // In addition to the solution on the exterior domain, we also output the
    // solution on the domain's boundary in the output_results() function, of
    // course.
    void compute_exterior_solution();

    void output_results(const unsigned int cycle);

    // To allow for dimension independent programming, we specialize this
    // single function to extract the singular quadrature formula needed to
    // integrate the singular kernels in the interior of the cells.
    const Quadrature<dim-1> & get_singular_quadrature(
      const typename DoFHandler<dim-1, dim>::active_cell_iterator &cell,
      const unsigned int index) const;

    // The usual deal.II classes can be used for boundary element methods by
    // specifying the "codimension" of the problem. This is done by setting
    // the optional second template arguments to Triangulation, FiniteElement
    // and DoFHandler to the dimension of the embedding space. In our case we
    // generate either 1 or 2 dimensional meshes embedded in 2 or 3
    // dimensional spaces.
    //
    // The optional argument by default is equal to the first argument, and
    // produces the usual finite element classes that we saw in all previous
    // examples.
    //
    // The class is constructed in a way to allow for arbitrary order of
    // approximation of both the domain (through high order mapping) and the
    // finite element space. The order of the finite element space and of the
    // mapping can be selected in the constructor of the class.

    Triangulation<dim-1, dim>   tria;
    FE_Q<dim-1,dim>             fe;
    DoFHandler<dim-1,dim>       dh;
    MappingQ<dim-1, dim>      mapping;

    // In BEM methods, the matrix that is generated is dense. Depending on the
    // size of the problem, the final system might be solved by direct LU
    // decomposition, or by iterative methods. In this example we use an
    // unpreconditioned GMRES method. Building a preconditioner for BEM method
    // is non trivial, and we don't treat this subject here.

    FullMatrix<double>    system_matrix;
    Vector<double>        system_rhs;

    // The next two variables will denote the solution $\phi$ as well as a
    // vector that will hold the values of $\alpha(\mathbf x)$ (the fraction
    // of $\Omega$ visible from a point $\mathbf x$) at the support points of
    // our shape functions.

    Vector<double>              phi;
    Vector<double>              alpha;

    // The convergence table is used to output errors in the exact solution
    // and in the computed alphas.

    ConvergenceTable  convergence_table;

    // The following variables are the ones that we fill through a parameter
    // file.  The new objects that we use in this example are the
    // Functions::ParsedFunction object and the QuadratureSelector object.
    //
    // The Functions::ParsedFunction class allows us to easily and quickly
    // define new function objects via parameter files, with custom
    // definitions which can be very complex (see the documentation of that
    // class for all the available options).
    //
    // We will allocate the quadrature object using the QuadratureSelector
    // class that allows us to generate quadrature formulas based on an
    // identifying string and on the possible degree of the formula itself. We
    // used this to allow custom selection of the quadrature formulas for the
    // standard integration, and to define the order of the singular
    // quadrature rule.
    //
    // We also define a couple of parameters which are used in case we wanted
    // to extend the solution to the entire domain.

    Functions::ParsedFunction<dim> wind;
    Functions::ParsedFunction<dim> exact_solution;

    unsigned int singular_quadrature_order;
    std_cxx1x::shared_ptr<Quadrature<dim-1> > quadrature;

    SolverControl solver_control;

    unsigned int n_cycles;
    unsigned int external_refinement;

    bool run_in_this_dimension;
    bool extend_solution;
  };

  // @sect4{BEMProblem::BEMProblem and BEMProblem::read_parameters}

  // The constructor initializes the variuous object in much the same way as
  // done in the finite element programs such as step-4 or step-6. The only
  // new ingredient here is the ParsedFunction object, which needs, at
  // construction time, the specification of the number of components.
  //
  // For the exact solution the number of vector components is one, and no
  // action is required since one is the default value for a ParsedFunction
  // object. The wind, however, requires dim components to be
  // specified. Notice that when declaring entries in a parameter file for the
  // expression of the Functions::ParsedFunction, we need to specify the
  // number of components explicitly, since the function
  // Functions::ParsedFunction::declare_parameters is static, and has no
  // knowledge of the number of components.
  template <int dim>
  BEMProblem<dim>::BEMProblem(const unsigned int fe_degree,
                              const unsigned int mapping_degree)
    :
    fe(fe_degree),
    dh(tria),
    mapping(mapping_degree, true),
    wind(dim)
  {}

  template <int dim>
  void BEMProblem<dim>::read_parameters (const std::string &filename)
  {
    deallog << std::endl << "Parsing parameter file " << filename << std::endl
            << "for a " << dim << " dimensional simulation. " << std::endl;

    ParameterHandler prm;

    prm.declare_entry("Number of cycles", "4",
                      Patterns::Integer());
    prm.declare_entry("External refinement", "5",
                      Patterns::Integer());
    prm.declare_entry("Extend solution on the -2,2 box", "true",
                      Patterns::Bool());
    prm.declare_entry("Run 2d simulation", "true",
                      Patterns::Bool());
    prm.declare_entry("Run 3d simulation", "true",
                      Patterns::Bool());

    prm.enter_subsection("Quadrature rules");
    {
      prm.declare_entry("Quadrature type", "gauss",
                        Patterns::Selection(QuadratureSelector<(dim-1)>::get_quadrature_names()));
      prm.declare_entry("Quadrature order", "4", Patterns::Integer());
      prm.declare_entry("Singular quadrature order", "5", Patterns::Integer());
    }
    prm.leave_subsection();

    // For both two and three dimensions, we set the default input data to be
    // such that the solution is $x+y$ or $x+y+z$. The actually computed
    // solution will have value zero at infinity. In this case, this coincide
    // with the exact solution, and no additional corrections are needed, but
    // you should be aware of the fact that we arbitrarily set $\phi_\infty$,
    // and the exact solution we pass to the program needs to have the same
    // value at infinity for the error to be computed correctly.
    //
    // The use of the Functions::ParsedFunction object is pretty straight
    // forward. The Functions::ParsedFunction::declare_parameters function
    // takes an additional integer argument that specifies the number of
    // components of the given function. Its default value is one. When the
    // corresponding Functions::ParsedFunction::parse_parameters method is
    // called, the calling object has to have the same number of components
    // defined here, otherwise an exception is thrown.
    //
    // When declaring entries, we declare both 2 and three dimensional
    // functions. However only the dim-dimensional one is ultimately
    // parsed. This allows us to have only one parameter file for both 2 and 3
    // dimensional problems.
    //
    // Notice that from a mathematical point of view, the wind function on the
    // boundary should satisfy the condition $\int_{\partial\Omega}
    // \mathbf{v}\cdot \mathbf{n} d \Gamma = 0$, for the problem to have a
    // solution. If this condition is not satisfied, then no solution can be
    // found, and the solver will not converge.
    prm.enter_subsection("Wind function 2d");
    {
      Functions::ParsedFunction<2>::declare_parameters(prm, 2);
      prm.set("Function expression", "1; 1");
    }
    prm.leave_subsection();

    prm.enter_subsection("Wind function 3d");
    {
      Functions::ParsedFunction<3>::declare_parameters(prm, 3);
      prm.set("Function expression", "1; 1; 1");
    }
    prm.leave_subsection();

    prm.enter_subsection("Exact solution 2d");
    {
      Functions::ParsedFunction<2>::declare_parameters(prm);
      prm.set("Function expression", "x+y");
    }
    prm.leave_subsection();

    prm.enter_subsection("Exact solution 3d");
    {
      Functions::ParsedFunction<3>::declare_parameters(prm);
      prm.set("Function expression", "x+y+z");
    }
    prm.leave_subsection();

    // In the solver section, we set all SolverControl parameters. The object
    // will then be fed to the GMRES solver in the solve_system() function.
    prm.enter_subsection("Solver");
    SolverControl::declare_parameters(prm);
    prm.leave_subsection();

    // After declaring all these parameters to the ParameterHandler object,
    // let's read an input file that will give the parameters their values. We
    // then proceed to extract these values from the ParameterHandler object:
    prm.read_input(filename);

    n_cycles = prm.get_integer("Number of cycles");
    external_refinement = prm.get_integer("External refinement");
    extend_solution = prm.get_bool("Extend solution on the -2,2 box");

    prm.enter_subsection("Quadrature rules");
    {
      quadrature =
        std_cxx1x::shared_ptr<Quadrature<dim-1> >
        (new QuadratureSelector<dim-1> (prm.get("Quadrature type"),
                                        prm.get_integer("Quadrature order")));
      singular_quadrature_order = prm.get_integer("Singular quadrature order");
    }
    prm.leave_subsection();

    prm.enter_subsection(std::string("Wind function ")+
                         Utilities::int_to_string(dim)+std::string("d"));
    {
      wind.parse_parameters(prm);
    }
    prm.leave_subsection();

    prm.enter_subsection(std::string("Exact solution ")+
                         Utilities::int_to_string(dim)+std::string("d"));
    {
      exact_solution.parse_parameters(prm);
    }
    prm.leave_subsection();

    prm.enter_subsection("Solver");
    solver_control.parse_parameters(prm);
    prm.leave_subsection();

    // Finally, here's another example of how to use parameter files in
    // dimension independent programming.  If we wanted to switch off one of
    // the two simulations, we could do this by setting the corresponding "Run
    // 2d simulation" or "Run 3d simulation" flag to false:
    run_in_this_dimension = prm.get_bool("Run " +
                                         Utilities::int_to_string(dim) +
                                         "d simulation");
  }

  // @sect4{BEMProblem::read_domain}

  // A boundary element method triangulation is basically the same as a
  // (dim-1) dimensional triangulation, with the difference that the vertices
  // belong to a (dim) dimensional space.
  //
  // Some of the mesh formats supported in deal.II use by default three
  // dimensional points to describe meshes. These are the formats which are
  // compatible with the boundary element method capabilities of deal.II. In
  // particular we can use either UCD or GMSH formats. In both cases, we have
  // to be particularly careful with the orientation of the mesh, because,
  // unlike in the standard finite element case, no reordering or
  // compatibility check is performed here.  All meshes are considered as
  // oriented, because they are embedded in a higher dimensional space. (See
  // the documentation of the GridIn and of the Triangulation for further
  // details on orientation of cells in a triangulation.) In our case, the
  // normals to the mesh are external to both the circle in 2d or the sphere
  // in 3d.
  //
  // The other detail that is required for appropriate refinement of the
  // boundary element mesh, is an accurate description of the manifold that
  // the mesh is approximating. We already saw this several times for the
  // boundary of standard finite element meshes (for example in step-5 and
  // step-6), and here the principle and usage is the same, except that the
  // HyperBallBoundary class takes an additional template parameter that
  // specifies the embedding space dimension. The function object still has to
  // be static to live at least as long as the triangulation object to which
  // it is attached.

  template <int dim>
  void BEMProblem<dim>::read_domain()
  {
    static const Point<dim> center = Point<dim>();
    static const HyperBallBoundary<dim-1, dim> boundary(center,1.);

    std::ifstream in;
    switch (dim)
      {
      case 2:
        in.open ("coarse_circle.inp");
        break;

      case 3:
        in.open ("coarse_sphere.inp");
        break;

      default:
        Assert (false, ExcNotImplemented());
      }

    GridIn<dim-1, dim> gi;
    gi.attach_triangulation (tria);
    gi.read_ucd (in);

    tria.set_boundary(1, boundary);
  }

  // @sect4{BEMProblem::refine_and_resize}

  // This function globally refines the mesh, distributes degrees of freedom,
  // and resizes matrices and vectors.

  template <int dim>
  void BEMProblem<dim>::refine_and_resize()
  {
    tria.refine_global(1);

    dh.distribute_dofs(fe);

    const unsigned int n_dofs =  dh.n_dofs();

    system_matrix.reinit(n_dofs, n_dofs);

    system_rhs.reinit(n_dofs);
    phi.reinit(n_dofs);
    alpha.reinit(n_dofs);
  }

  // @sect4{BEMProblem::assemble_system}

  // The following is the main function of this program, assembling the matrix
  // that corresponds to the boundary integral equation.
  template <int dim>
  void BEMProblem<dim>::assemble_system()
  {

    // First we initialize an FEValues object with the quadrature formula for
    // the integration of the kernel in non singular cells. This quadrature is
    // selected with the parameter file, and needs to be quite precise, since
    // the functions we are integrating are not polynomial functions.
    FEValues<dim-1,dim> fe_v(mapping, fe, *quadrature,
                             update_values |
                             update_cell_normal_vectors |
                             update_quadrature_points |
                             update_JxW_values);

    const unsigned int n_q_points = fe_v.n_quadrature_points;

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

    std::vector<Vector<double> > cell_wind(n_q_points, Vector<double>(dim) );
    double normal_wind;

    // Unlike in finite element methods, if we use a collocation boundary
    // element method, then in each assembly loop we only assemble the
    // information that refers to the coupling between one degree of freedom
    // (the degree associated with support point $i$) and the current
    // cell. This is done using a vector of fe.dofs_per_cell elements, which
    // will then be distributed to the matrix in the global row $i$. The
    // following object will hold this information:
    Vector<double>      local_matrix_row_i(fe.dofs_per_cell);

    // The index $i$ runs on the collocation points, which are the support
    // points of the $i$th basis function, while $j$ runs on inner integration
    // points.

    // We construct a vector of support points which will be used in the local
    // integrations:
    std::vector<Point<dim> > support_points(dh.n_dofs());
    DoFTools::map_dofs_to_support_points<dim-1, dim>( mapping, dh, support_points);

    // After doing so, we can start the integration loop over all cells, where
    // we first initialize the FEValues object and get the values of
    // $\mathbf{\tilde v}$ at the quadrature points (this vector field should
    // be constant, but it doesn't hurt to be more general):
    typename DoFHandler<dim-1,dim>::active_cell_iterator
    cell = dh.begin_active(),
    endc = dh.end();

    for (cell = dh.begin_active(); cell != endc; ++cell)
      {
        fe_v.reinit(cell);
        cell->get_dof_indices(local_dof_indices);

        const std::vector<Point<dim> > &q_points = fe_v.get_quadrature_points();
        const std::vector<Point<dim> > &normals = fe_v.get_normal_vectors();
        wind.vector_value_list(q_points, cell_wind);

        // We then form the integral over the current cell for all degrees of
        // freedom (note that this includes degrees of freedom not located on
        // the current cell, a deviation from the usual finite element
        // integrals). The integral that we need to perform is singular if one
        // of the local degrees of freedom is the same as the support point
        // $i$. A the beginning of the loop we therefore check wether this is
        // the case, and we store which one is the singular index:
        for (unsigned int i=0; i<dh.n_dofs() ; ++i)
          {

            local_matrix_row_i = 0;

            bool is_singular = false;
            unsigned int singular_index = numbers::invalid_unsigned_int;

            for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
              if (local_dof_indices[j] == i)
                {
                  singular_index = j;
                  is_singular = true;
                  break;
                }

            // We then perform the integral. If the index $i$ is not one of
            // the local degrees of freedom, we simply have to add the single
            // layer terms to the right hand side, and the double layer terms
            // to the matrix:
            if (is_singular == false)
              {
                for (unsigned int q=0; q<n_q_points; ++q)
                  {
                    normal_wind = 0;
                    for (unsigned int d=0; d<dim; ++d)
                      normal_wind += normals[q][d]*cell_wind[q](d);

                    const Point<dim> R = q_points[q] - support_points[i];

                    system_rhs(i) += ( LaplaceKernel::single_layer(R)   *
                                       normal_wind                      *
                                       fe_v.JxW(q) );

                    for (unsigned int j=0; j<fe.dofs_per_cell; ++j)

                      local_matrix_row_i(j) -= ( ( LaplaceKernel::double_layer(R)     *
                                                   normals[q] )            *
                                                 fe_v.shape_value(j,q)     *
                                                 fe_v.JxW(q)       );
                  }
              }
            else
              {
                // Now we treat the more delicate case. If we are here, this
                // means that the cell that runs on the $j$ index contains
                // support_point[i]. In this case both the single and the
                // double layer potential are singular, and they require
                // special treatment.
                //
                // Whenever the integration is performed with the singularity
                // inside the given cell, then a special quadrature formula is
                // used that allows one to integrate arbitrary functions
                // against a singular weight on the reference cell.
                //
                // The correct quadrature formula is selected by the
                // get_singular_quadrature function, which is explained in
                // detail below.
                Assert(singular_index != numbers::invalid_unsigned_int,
                       ExcInternalError());

                const Quadrature<dim-1> & singular_quadrature =
                  get_singular_quadrature(cell, singular_index);

                FEValues<dim-1,dim> fe_v_singular (mapping, fe, singular_quadrature,
                                                   update_jacobians |
                                                   update_values |
                                                   update_cell_normal_vectors |
                                                   update_quadrature_points );

                fe_v_singular.reinit(cell);

                std::vector<Vector<double> > singular_cell_wind( singular_quadrature.size(),
                                                                 Vector<double>(dim) );

                const std::vector<Point<dim> > &singular_normals = fe_v_singular.get_normal_vectors();
                const std::vector<Point<dim> > &singular_q_points = fe_v_singular.get_quadrature_points();

                wind.vector_value_list(singular_q_points, singular_cell_wind);

                for (unsigned int q=0; q<singular_quadrature.size(); ++q)
                  {
                    const Point<dim> R = singular_q_points[q] - support_points[i];
                    double normal_wind = 0;
                    for (unsigned int d=0; d<dim; ++d)
                      normal_wind += (singular_cell_wind[q](d)*
                                      singular_normals[q][d]);

                    system_rhs(i) += ( LaplaceKernel::single_layer(R) *
                                       normal_wind                         *
                                       fe_v_singular.JxW(q) );

                    for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
                      {
                        local_matrix_row_i(j) -= (( LaplaceKernel::double_layer(R) *
                                                    singular_normals[q])                *
                                                  fe_v_singular.shape_value(j,q)        *
                                                  fe_v_singular.JxW(q)       );
                      }
                  }
              }

            // Finally, we need to add the contributions of the current cell
            // to the global matrix.
            for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
              system_matrix(i,local_dof_indices[j])
              += local_matrix_row_i(j);
          }
      }

    // The second part of the integral operator is the term
    // $\alpha(\mathbf{x}_i) \phi_j(\mathbf{x}_i)$. Since we use a collocation
    // scheme, $\phi_j(\mathbf{x}_i)=\delta_{ij}$ and the corresponding matrix
    // is a diagonal one with entries equal to $\alpha(\mathbf{x}_i)$.

    // One quick way to compute this diagonal matrix of the solid angles, is
    // to use the Neumann matrix itself. It is enough to multiply the matrix
    // with a vector of elements all equal to -1, to get the diagonal matrix
    // of the alpha angles, or solid angles (see the formula in the
    // introduction for this). The result is then added back onto the system
    // matrix object to yield the final form of the matrix:
    Vector<double> ones(dh.n_dofs());
    ones.add(-1.);

    system_matrix.vmult(alpha, ones);
    alpha.add(1);
    for (unsigned int i = 0; i<dh.n_dofs(); ++i)
      system_matrix(i,i) +=  alpha(i);
  }

  // @sect4{BEMProblem::solve_system}

  // The next function simply solves the linear system.
  template <int dim>
  void BEMProblem<dim>::solve_system()
  {
    SolverGMRES<Vector<double> > solver (solver_control);
    solver.solve (system_matrix, phi, system_rhs, PreconditionIdentity());
  }

  // @sect4{BEMProblem::compute_errors}

  // The computation of the errors is exactly the same in all other example
  // programs, and we won't comment too much. Notice how the same methods that
  // are used in the finite element methods can be used here.
  template <int dim>
  void BEMProblem<dim>::compute_errors(const unsigned int cycle)
  {
    Vector<float> difference_per_cell (tria.n_active_cells());
    VectorTools::integrate_difference (mapping, dh, phi,
                                       exact_solution,
                                       difference_per_cell,
                                       QGauss<(dim-1)>(2*fe.degree+1),
                                       VectorTools::L2_norm);
    const double L2_error = difference_per_cell.l2_norm();

    // The error in the alpha vector can be computed directly using the
    // Vector::linfty_norm() function, since on each node, the value should be
    // $\frac 12$. All errors are then output and appended to our
    // ConvergenceTable object for later computation of convergence rates:
    Vector<double> difference_per_node(alpha);
    difference_per_node.add(-.5);

    const double alpha_error = difference_per_node.linfty_norm();
    const unsigned int n_active_cells=tria.n_active_cells();
    const unsigned int n_dofs=dh.n_dofs();

    deallog << "Cycle " << cycle << ':'
            << std::endl
            << "   Number of active cells:       "
            << n_active_cells
            << std::endl
            << "   Number of degrees of freedom: "
            << n_dofs
            << std::endl;

    convergence_table.add_value("cycle", cycle);
    convergence_table.add_value("cells", n_active_cells);
    convergence_table.add_value("dofs", n_dofs);
    convergence_table.add_value("L2(phi)", L2_error);
    convergence_table.add_value("Linfty(alpha)", alpha_error);
  }

  // Singular integration requires a careful selection of the quadrature
  // rules. In particular the deal.II library provides quadrature rules which
  // are taylored for logarithmic singularities (QGaussLog, QGaussLogR), as
  // well as for 1/R singularities (QGaussOneOverR).
  //
  // Singular integration is typically obtained by constructing weighted
  // quadrature formulas with singular weights, so that it is possible to
  // write
  //
  // \f[ \int_K f(x) s(x) dx = \sum_{i=1}^N w_i f(q_i) \f]
  //
  // where $s(x)$ is a given singularity, and the weights and quadrature
  // points $w_i,q_i$ are carefully selected to make the formula above an
  // equality for a certain class of functions $f(x)$.
  //
  // In all the finite element examples we have seen so far, the weight of the
  // quadrature itself (namely, the function $s(x)$), was always constantly
  // equal to 1.  For singular integration, we have two choices: we can use
  // the definition above, factoring out the singularity from the integrand
  // (i.e., integrating $f(x)$ with the special quadrature rule), or we can
  // ask the quadrature rule to "normalize" the weights $w_i$ with $s(q_i)$:
  //
  // \f[ \int_K f(x) s(x) dx = \int_K g(x) dx = \sum_{i=1}^N
  //   \frac{w_i}{s(q_i)} g(q_i) \f]
  //
  // We use this second option, through the @p factor_out_singularity
  // parameter of both QGaussLogR and QGaussOneOverR.
  //
  // These integrals are somewhat delicate, especially in two dimensions, due
  // to the transformation from the real to the reference cell, where the
  // variable of integration is scaled with the determinant of the
  // transformation.
  //
  // In two dimensions this process does not result only in a factor appearing
  // as a constant factor on the entire integral, but also on an additional
  // integral altogether that needs to be evaluated:
  //
  // \f[ \int_0^1 f(x)\ln(x/\alpha) dx = \int_0^1 f(x)\ln(x) dx - \int_0^1
  //  f(x) \ln(\alpha) dx.  \f]
  //
  // This process is taken care of by the constructor of the QGaussLogR class,
  // which adds additional quadrature points and weights to take into
  // consideration also the second part of the integral.
  //
  // A similar reasoning should be done in the three dimensional case, since
  // the singular quadrature is taylored on the inverse of the radius $r$ in
  // the reference cell, while our singular function lives in real space,
  // however in the three dimensional case everything is simpler because the
  // singularity scales linearly with the determinant of the
  // transformation. This allows us to build the singular two dimensional
  // quadrature rules only once and, reuse them over all cells.
  //
  // In the one dimensional singular integration this is not possible, since
  // we need to know the scaling parameter for the quadrature, which is not
  // known a priori. Here, the quadrature rule itself depends also on the size
  // of the current cell. For this reason, it is necessary to create a new
  // quadrature for each singular integration.
  //
  // The different quadrature rules are built inside the
  // get_singular_quadrature, which is specialized for dim=2 and dim=3, and
  // they are retrieved inside the assemble_system function. The index given
  // as an argument is the index of the unit support point where the
  // singularity is located.

  template<>
  const Quadrature<2> &BEMProblem<3>::get_singular_quadrature(
    const DoFHandler<2,3>::active_cell_iterator &,
    const unsigned int index) const
  {
    Assert(index < fe.dofs_per_cell,
           ExcIndexRange(0, fe.dofs_per_cell, index));

    static std::vector<QGaussOneOverR<2> > quadratures;
    if (quadratures.size() == 0)
      for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
        quadratures.push_back(QGaussOneOverR<2>(singular_quadrature_order,
                                                fe.get_unit_support_points()[i],
                                                true));
    return quadratures[index];
  }

  template<>
  const Quadrature<1> &BEMProblem<2>::get_singular_quadrature(
    const DoFHandler<1,2>::active_cell_iterator &cell,
    const unsigned int index) const
  {
    Assert(index < fe.dofs_per_cell,
           ExcIndexRange(0, fe.dofs_per_cell, index));

    static Quadrature<1> *q_pointer = NULL;
    if (q_pointer) delete q_pointer;

    q_pointer = new QGaussLogR<1>(singular_quadrature_order,
                                  fe.get_unit_support_points()[index],
                                  1./cell->measure(), true);
    return (*q_pointer);
  }

  // @sect4{BEMProblem::compute_exterior_solution}

  // We'd like to also know something about the value of the potential $\phi$
  // in the exterior domain: after all our motivation to consider the boundary
  // integral problem was that we wanted to know the velocity in the exterior
  // domain!
  //
  // To this end, let us assume here that the boundary element domain is
  // contained in the box $[-2,2]^{\text{dim}}$, and we extrapolate the actual
  // solution inside this box using the convolution with the fundamental
  // solution. The formula for this is given in the introduction.
  //
  // The reconstruction of the solution in the entire space is done on a
  // continuous finite element grid of dimension dim. These are the usual
  // ones, and we don't comment any further on them. At the end of the
  // function, we output this exterior solution in, again, much the usual way.
  template <int dim>
  void BEMProblem<dim>::compute_exterior_solution()
  {
    Triangulation<dim>  external_tria;
    GridGenerator::hyper_cube(external_tria, -2, 2);

    FE_Q<dim>           external_fe(1);
    DoFHandler<dim>     external_dh (external_tria);
    Vector<double>      external_phi;

    external_tria.refine_global(external_refinement);
    external_dh.distribute_dofs(external_fe);
    external_phi.reinit(external_dh.n_dofs());

    typename DoFHandler<dim-1,dim>::active_cell_iterator
    cell = dh.begin_active(),
    endc = dh.end();

    FEValues<dim-1,dim> fe_v(mapping, fe, *quadrature,
                             update_values |
                             update_cell_normal_vectors |
                             update_quadrature_points |
                             update_JxW_values);

    const unsigned int n_q_points = fe_v.n_quadrature_points;

    std::vector<unsigned int> dofs(fe.dofs_per_cell);

    std::vector<double> local_phi(n_q_points);
    std::vector<double> normal_wind(n_q_points);
    std::vector<Vector<double> > local_wind(n_q_points, Vector<double>(dim) );

    std::vector<Point<dim> > external_support_points(external_dh.n_dofs());
    DoFTools::map_dofs_to_support_points<dim>(StaticMappingQ1<dim>::mapping,
                                              external_dh, external_support_points);

    for (cell = dh.begin_active(); cell != endc; ++cell)
      {
        fe_v.reinit(cell);

        const std::vector<Point<dim> > &q_points = fe_v.get_quadrature_points();
        const std::vector<Point<dim> > &normals = fe_v.get_normal_vectors();

        cell->get_dof_indices(dofs);
        fe_v.get_function_values(phi, local_phi);

        wind.vector_value_list(q_points, local_wind);

        for (unsigned int q=0; q<n_q_points; ++q)
          {
            normal_wind[q] = 0;
            for (unsigned int d=0; d<dim; ++d)
              normal_wind[q] += normals[q][d]*local_wind[q](d);
          }

        for (unsigned int i=0; i<external_dh.n_dofs(); ++i)
          for (unsigned int q=0; q<n_q_points; ++q)
            {

              const Point<dim> R =  q_points[q] - external_support_points[i];

              external_phi(i) += ( ( LaplaceKernel::single_layer(R) *
                                     normal_wind[q]
                                     +
                                     (LaplaceKernel::double_layer(R) *
                                      normals[q] )            *
                                     local_phi[q] )           *
                                   fe_v.JxW(q) );
            }
      }

    DataOut<dim> data_out;

    data_out.attach_dof_handler(external_dh);
    data_out.add_data_vector(external_phi, "external_phi");
    data_out.build_patches();

    const std::string
    filename = Utilities::int_to_string(dim) + "d_external.vtk";
    std::ofstream file(filename.c_str());

    data_out.write_vtk(file);
  }

  // @sect4{BEMProblem::output_results}

  // Outputting the results of our computations is a rather mechanical
  // tasks. All the components of this function have been discussed before.
  template <int dim>
  void BEMProblem<dim>::output_results(const unsigned int cycle)
  {
    DataOut<dim-1, DoFHandler<dim-1, dim> > dataout;

    dataout.attach_dof_handler(dh);
    dataout.add_data_vector(phi, "phi");
    dataout.add_data_vector(alpha, "alpha");
    dataout.build_patches(mapping,
                          mapping.get_degree(),
                          DataOut<dim-1, DoFHandler<dim-1, dim> >::curved_inner_cells);

    std::string filename = ( Utilities::int_to_string(dim) +
                             "d_boundary_solution_" +
                             Utilities::int_to_string(cycle) +
                             ".vtk" );
    std::ofstream file(filename.c_str());

    dataout.write_vtk(file);

    if (cycle == n_cycles-1)
      {
        convergence_table.set_precision("L2(phi)", 3);
        convergence_table.set_precision("Linfty(alpha)", 3);

        convergence_table.set_scientific("L2(phi)", true);
        convergence_table.set_scientific("Linfty(alpha)", true);

        convergence_table
        .evaluate_convergence_rates("L2(phi)", ConvergenceTable::reduction_rate_log2);
        convergence_table
        .evaluate_convergence_rates("Linfty(alpha)", ConvergenceTable::reduction_rate_log2);
        deallog << std::endl;
        convergence_table.write_text(std::cout);
      }
  }

  // @sect4{BEMProblem::run}

  // This is the main function. It should be self explanatory in its
  // briefness:
  template <int dim>
  void BEMProblem<dim>::run()
  {

    read_parameters("parameters.prm");

    if (run_in_this_dimension == false)
      {
        deallog << "Run in dimension " << dim
                << " explicitly disabled in parameter file. "
                << std::endl;
        return;
      }

    read_domain();

    for (unsigned int cycle=0; cycle<n_cycles; ++cycle)
      {
        refine_and_resize();
        assemble_system();
        solve_system();
        compute_errors(cycle);
        output_results(cycle);
      }

    if (extend_solution == true)
      compute_exterior_solution();
  }
}

// @sect3{The main() function}

// This is the main function of this program. It is exactly like all previous
// tutorial programs:
int main ()
{
  try
    {
      using namespace dealii;
      using namespace Step34;

      const unsigned int degree = 1;
      const unsigned int mapping_degree = 1;

      deallog.depth_console (3);
      BEMProblem<2> laplace_problem_2d(degree, mapping_degree);
      laplace_problem_2d.run();

      BEMProblem<3> laplace_problem_3d(degree, mapping_degree);
      laplace_problem_3d.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 (c)
//
// 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)
//=======================================================================
/**
 * @file 2_local_search_test.cpp
 * @brief
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2013-09-20
 */
#include "test_utils/sample_graph.hpp"
#include "test_utils/logger.hpp"
#include "test_utils/2_local_search_logger.hpp"

#include "paal/local_search/2_local_search/2_local_search.hpp"
#include "paal/data_structures/cycle/simple_cycle.hpp"

#include <boost/test/unit_test.hpp>

#include <vector>
#include <string>

using std::string;
using std::vector;
using namespace paal::local_search;
using namespace paal;

BOOST_AUTO_TEST_CASE(two_local_search_test) {
    //! [Two Local Search Example]
    // sample data
    typedef sample_graphs_metrics SGM;
    auto gm = SGM::get_graph_metric_small();
    const int size = gm.size();
    std::vector<int> v(size);
    std::iota(v.begin(), v.end(), 0);

    // create random solution
    std::random_shuffle(v.begin(), v.end());
    typedef data_structures::simple_cycle<int> Cycle;
    Cycle cycle(v.begin(), v.end());

    // creating local search components
    auto lsc = get_default_two_local_components(gm);

    // printing
    LOGLN("Length \t" << get_cycle_length(gm, cycle));

    // setting logger
    auto logger = utils::make_two_ls_logger(gm, 100);

    // search
    two_local_search(cycle, local_search::first_improving_strategy{}, logger,
                     utils::always_false(), lsc);
    //! [Two Local Search Example]
}


/******************************************************************************

  Triangulation algorithms for surface reconstruction problems.

  Copyright (c) 2013
  Alexander Rukletsov <rukletsov@gmail.com>
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
  1.  Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
  2.  Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  SUCH DAMAGE.

*******************************************************************************/

#ifndef TRIANGULATION_HPP_40CA4CA1_3752_4080_9BDE_D13393E21902
#define TRIANGULATION_HPP_40CA4CA1_3752_4080_9BDE_D13393E21902

#include <vector>
#include <boost/foreach.hpp>
#include <boost/noncopyable.hpp>

#include "bo/core/mesh.hpp"
#include "bo/surfaces/detail/indexed_tstrip.hpp"
#include "bo/surfaces/christiansen_tiling.hpp"

namespace bo {
namespace surfaces {

// This class contain various triangulation algorithms.
template <typename RealType>
class Triangulation
{
public:
    typedef bo::Mesh<RealType> RealMesh;
    typedef ChristiansenTiling<RealType> Christiansen;

public:
    // Performs modified Christiansen triangulation for two contours.
    template <typename ContourDescrPtr>
    static RealMesh christiansen(const ContourDescrPtr& contour1,
                                 const ContourDescrPtr& contour2)
    {

        detail::IndexedTStrip tstrip = Christiansen(0, contour1->contour(), contour1->is_closed(),
                                                    1, contour2->contour(), contour2->is_closed())
                .run();

        // Calculate the total number of vertices to create mesh efficiently.
        std::size_t total_vertices = contour1->contour()->size() + contour2->contour()->size();

        // Populate the result mesh with vertices and store vertices shift for the
        // second contour (it should be 0 for the first).
        RealMesh mesh(total_vertices);
        std::vector<std::size_t> lookup_table(2);
        lookup_table[0] = mesh.add_vertices(*(contour1->contour()));
        lookup_table[1] = mesh.add_vertices(*(contour2->contour()));

        // Populate the result mesh with faces. Transform old <contour_id, vertex_ix>
        // keys into new <mesh_vertex_id> keys using lookup table.
        BOOST_FOREACH (const detail::IndexedTStrip::Face& face, tstrip.get_faces())
        {
            std::size_t new_a = lookup_table[face.A().first] + face.A().second;
            std::size_t new_b = lookup_table[face.B().first] + face.B().second;
            std::size_t new_c = lookup_table[face.C().first] + face.C().second;
            mesh.add_face(typename RealMesh::Face(new_a, new_b, new_c));
        }

        return mesh;
    }

    // Performs modified Christiansen triangulation for a collection of contours.
    // Note that the collection must be sorted, because the algorithm connects adjacent
    // contours.
    template <typename ContourDescrPtr>
    static RealMesh christiansen(const std::vector<ContourDescrPtr>& contours)
    {
        std::size_t total_contours = contours.size();
        detail::IndexedTStrip::TStrips tstrips_;

        for (std::size_t idx = 1; idx < total_contours; ++idx)
        {
            ContourDescrPtr cur_contour = contours[idx];
            ContourDescrPtr prev_contour = contours[idx - 1];

            Christiansen triang(
                    idx - 1, prev_contour->contour(), prev_contour->is_closed(),
                    idx, cur_contour->contour(), cur_contour->is_closed());

            detail::IndexedTStrip tstrip = triang.run();
            tstrips_.push_back(tstrip);
        }

        // Union all tstrips into one mesh.
        detail::IndexedTStrip joined_tstrips = detail::IndexedTStrip::join(tstrips_);

        // Calculate the total number of vertices to create mesh efficiently.
        std::size_t total_vertices = 0;
        BOOST_FOREACH (const ContourDescrPtr& c, contours)
        { total_vertices += c->contour()->size(); }

        // Populate the result mesh with vertices and create lookup tables.
        RealMesh mesh(total_vertices);
        std::vector<std::size_t> lookup_table(total_contours);
        for (std::size_t idx = 0; idx < total_contours; ++idx)
        {
            std::size_t current_offset = mesh.add_vertices(*(contours[idx]->contour()));
            lookup_table[idx] = current_offset;
        }

        // Populate the result mesh with faces. Transform old <contour_id, vertex_ix>
        // keys into new <mesh_vertex_id> keys using lookup table.
        BOOST_FOREACH (const detail::IndexedTStrip::Face& face, joined_tstrips.get_faces())
        {
            std::size_t new_a = lookup_table[face.A().first] + face.A().second;
            std::size_t new_b = lookup_table[face.B().first] + face.B().second;
            std::size_t new_c = lookup_table[face.C().first] + face.C().second;
            mesh.add_face(typename RealMesh::Face(new_a, new_b, new_c));
        }

        return mesh;
    }
};

} // namespace surfaces
} // namespace bo

#endif // TRIANGULATION_HPP_40CA4CA1_3752_4080_9BDE_D13393E21902


//=======================================================================
// Copyright (c) 2013 Robert Rosolek
//
// 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)
//=======================================================================
/**
 * @file winner_determination_in_MUCA_long_test.cpp
 * @brief
 * @author Robert Rosolek
 * @version 1.0
 * @date 2014-3-20
 */

#include "test_utils/winner_determination_in_MUCA_test_utils.hpp"
#include "test_utils/winner_determination_in_MUCA_long_test.hpp"
#include "test_utils/system.hpp"

#include "paal/utils/functors.hpp"
#include "paal/utils/parse_file.hpp"

#include <boost/range/irange.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/property_map/vector_property_map.hpp>

#include <fstream>
#include <iterator>
#include <random>
#include <string>
#include <utility>
#include <vector>

BOOST_AUTO_TEST_CASE(testDetermineWinnersLong)
{
   std::default_random_engine generator(7);
   std::uniform_real_distribution<Value> distribution(1.0, 2.0);

   paal::parse(paal::system::build_path(test_dir, cases_file), [&](std::string test_name, paal::utils::ignore_param) {
      Value lower_bound;
      std::vector<Bids> bids;
      std::vector<int> item_count;
      int bidders_num, items_num;
      std::tie(lower_bound, bids, item_count, bidders_num, items_num) = read_auction(test_name);

      auto bidders = boost::irange(0, bidders_num);
      auto items = boost::irange(0, items_num);
      auto get_bids = [&](Bidder bidder) -> const Bids& { return bids.at(bidder); };
      auto get_value = [](const Bid& bid) { return bid.second; };
      auto get_items = [](const Bid& bid) -> const Items& { return bid.first; };
      auto get_copies_num = paal::utils::make_array_to_functor(item_count);
      auto gamma = distribution(generator);
      check_determine_winners_in_gamma_oracle(
         bidders,
         items,
         get_bids,
         get_value,
         get_items,
         get_copies_num,
         gamma,
         lower_bound,
         boost::vector_property_map<Value>(),
         1e-8
      );
   });
}


/*
 * magnetogram_test.cpp
 *
 *  Created on: Sep 23, 2009
 *      Author: dberrios
 */

#include <boost/lexical_cast.hpp>
#include <iostream>
#include <ccmc/Magnetogram.h>
#include <ccmc/Interpolator.h>
#include <string>

using namespace std;

/**
 * I have no idea what's contained in a magnetogram. Do they contain more than one variable?
 * magnetogram <inputfile> variable lat lon
 */
int main (int argc, char * argv[])
{
	if (argc != 5)
	{
		cout << "magnetogram <inputfile> variable lat lon" << endl;
		exit(1);
	}

	string filename = argv[1];
	string variable = argv[2];
	float lat = boost::lexical_cast<float>(argv[3]);
	float lon = boost::lexical_cast<float>(argv[4]);
	ccmc::Magnetogram magnetogram;
	magnetogram.open(filename);
	magnetogram.loadVariable(variable);

	ccmc::Interpolator * interpolator = magnetogram.createNewInterpolator();

	//needs three position components. Just ignore the last one.
	float value = interpolator->interpolate(variable, lat, lon, 0);
	delete interpolator;

	string units = magnetogram.getNativeUnit(variable);

	cout << "interpolated value: " << value << " " << units << endl;
	magnetogram.close();

}


/****************************************************************************
name: Most Frequent Words
author: Terry
date: 2019-08-16
****************************************************************************/
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <queue> 			// for priority_queue<T>
#include <boost/timer.hpp>  // for timer
using namespace std;

int main(int argc, char* argv[])
{
	boost::timer time; 		// record the elapsed time
	string word;            // the word in the file
	map <string, int> freq; // hash map for the words
	map <string, int>::const_iterator wordsit; // iterator for the hash map

	fstream test_file;      // test file from input argv
	test_file.open(argv[1], ios::in);

	if (!test_file.is_open())    // open attempt failed
	{
		cerr << "Error message : Unable to open "<< argv[1] << endl;
		return 1; 				 // exit
	}
	else
	{
		// Create a hash table and load file into string
		while (test_file >> word)
		{
			freq[word]++;
		}
		test_file.close();		// close the file
	}

	cout<<"There are "<<freq.size()<< " different words in this file." <<endl;

	// Get the top 10 frequent words
	priority_queue<pair<int,string>, vector<pair<int,string>>, greater<pair<int,string>> > most_words;
    for (wordsit = freq.begin(); wordsit != freq.end(); wordsit++)
    {
        most_words.push(make_pair(wordsit->second,wordsit->first));
        if (most_words.size()>10)
        {
            most_words.pop();
        }
    }

	// Print out ten most frequent words
	cout<<"The most ten frequent words are: \n"<<endl;
	cout.width(8);
    cout<<"Words"<<":";
	cout.width(6);
	cout<<"Times"<<endl;
    most_words.pop();

    while(!most_words.empty())
    {
		cout.width(8);
        cout<<most_words.top().second<<":";
		cout.width(6);
		cout<<most_words.top().first<<endl;
        most_words.pop();
    }

	// Print out elapsed time
    cout<<"\nTime elapsed :"<<time.elapsed()<<"s"<<endl;
	return 0;
}


#pragma once

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

using namespace std;
namespace ublas = boost::numeric::ublas;

/*********************************************************************************/
/*                                CLASS FOR TESTSET                              */
/*********************************************************************************/

class TestSet
{
public:
	TestSet(const string &directory); // Loads Data from TestSet
	void ReadInData(
		const string &directory,
		vector<double> &dj,
		vector<double> &bi,
		vector<double> &fi,
		ublas::matrix<double> &cij); // RAII Model to Read in Data

protected:
	const string m_directory; // Directory
	// Set Ranges
	size_t m_locationNumber; // I = 0, ..., I - 1
	size_t m_customerNumber; // J = 0, ..., J - 1
	// Vector
	vector<double> m_dj; // Demand of customer j
	vector<double> m_bi; // Capacity of facility i
	vector<double>m_fi; // Opening Costs of Facility i
	// Matrix
	ublas::matrix<double> m_cij; // Link Costs (i,j)
};


//------------------------------------------------------------------------------
/// \file
/// \ingroup extractor
/// \copyright (C) Copyright Aquaveo 2018. Distributed under FreeBSD License
/// (See accompanying file LICENSE or https://aqaveo.com/bsd/license.txt)
//------------------------------------------------------------------------------

//----- Included files ---------------------------------------------------------

// 1. Precompiled header

// 2. My own header
#include <xmsextractor/ugrid/XmUGridTriangles2d.h>

// 3. Standard library headers
#include <sstream>
#include <cmath>

// 4. External library headers
#include <boost/container/flat_map.hpp>

// 5. Shared code headers
#include <xmscore/misc/XmError.h>
#include <xmscore/misc/XmLog.h>
#include <xmsgrid/geometry/geoms.h>
#include <xmsgrid/geometry/GmTriSearch.h>
#include <xmsgrid/ugrid/XmUGrid.h>

// 6. Non-shared code headers

//----- Forward declarations ---------------------------------------------------

//----- External globals -------------------------------------------------------

//----- Namespace declaration --------------------------------------------------

/// XMS Namespace
namespace xms
{
//----- Constants / Enumerations -----------------------------------------------

//----- Classes / Structs ------------------------------------------------------

//----- Internal functions -----------------------------------------------------

//----- Class / Function definitions -------------------------------------------

namespace
{
typedef std::tuple<int, int, int> Triangle; ///< three consecutive polygon points for triangle
typedef boost::container::flat_map<Triangle, double>
  RatioCache; ///< ratio cache to speed up earcut calculation
typedef boost::container::flat_map<Triangle, bool>
  ValidCache; ///< valid cache to speed up earcut calculation

class XmUGridTriangles2dImpl : public XmUGridTriangles2d
{
public:
  XmUGridTriangles2dImpl();

  virtual void BuildTriangles(const XmUGrid& a_ugrid, bool a_addTriangleCenters) override;
  virtual void BuildEarcutTriangles(const XmUGrid& a_ugrid) override;
  virtual void SetCellActivity(const DynBitset& a_cellActivity) override;

  virtual const VecPt3d& GetPoints() const override;
  virtual const VecInt& GetTriangles() const override;
  virtual BSHP<VecPt3d> GetPointsPtr() override;
  virtual BSHP<VecInt> GetTrianglesPtr() override;

  int AddCellCentroid(int a_cellIdx, const Pt3d& a_point);
  void AddCellTriangle(int a_cellIdx, int a_idx1, int a_idx2, int a_idx3);

  virtual int GetCellCentroid(int a_cellIdx) const override;

  virtual int GetIntersectedCell(const Pt3d& a_point, VecInt& a_idxs, VecDbl& a_weights) override;

private:
  void Initialize(const XmUGrid& a_ugrid);
  BSHP<GmTriSearch> GetTriSearch();

  BSHP<VecPt3d> m_points;                ///< Triangle points for the UGrid
  BSHP<VecInt> m_triangles;              ///< Triangles for the UGrid
  VecInt m_centroidIdxs;                 ///< Index of each cell centroid or -1 if none
  VecInt m_triangleToCellIdx;            ///< The cell index for each triangle
  mutable BSHP<GmTriSearch> m_triSearch; ///< Triangle searcher for triangles
};

//------------------------------------------------------------------------------
/// \brief Calculate the magnitude of a vector.
/// \param[in] a_vec: the vector
//------------------------------------------------------------------------------
double iMagnitude(const Pt3d& a_vec)
{
  double magnitude = sqrt(a_vec.x * a_vec.x + a_vec.y * a_vec.y + a_vec.z * a_vec.z);
  return magnitude;
} // iMagnitude
//------------------------------------------------------------------------------
/// \brief Calculate a quality ratio to use to determine which triangles to cut
///        using earcut triangulation. Better triangles have a lower ratio.
/// \param[in] a_points: the array the points come from
/// \param[in] a_idx1: first point of first edge
/// \param[in] a_idx2: second point of first edge, first point of second edge
/// \param[in] a_idx2: second point of second edge
/// \
/// \return The ratio, -1.0 for an inverted triangle, or -2.0 for a zero area
///         triangle
//------------------------------------------------------------------------------
double iGetEarcutTriangleRatio(const VecPt3d& a_points,
                               int a_idx1,
                               int a_idx2,
                               int a_idx3,
                               RatioCache& a_ratioCache)
{
  Triangle triangle(a_idx1, a_idx2, a_idx3);
  auto ratioIter = a_ratioCache.find(triangle);
  if (ratioIter != a_ratioCache.end())
    return ratioIter->second;

  Pt3d pt1 = a_points[a_idx1];
  Pt3d pt2 = a_points[a_idx2];
  Pt3d pt3 = a_points[a_idx3];
  Pt3d v1 = pt1 - pt2;
  Pt3d v2 = pt3 - pt2;
  Pt3d v3 = pt3 - pt1;

  // get 2*area
  Pt3d cross;
  gmCross3D(v2, v1, &cross);
  double ratio;
  if (cross.z <= 0.0)
  {
    // inverted
    ratio = -1.0;
  }
  else
  {
    double area2 = iMagnitude(cross);
    if (area2 == 0.0)
    {
      // degenerate triangle
      ratio = -2.0;
    }
    else
    {
      double perimeter = iMagnitude(v1) + iMagnitude(v2) + iMagnitude(v3);
      ratio = perimeter * perimeter / area2;
    }
  }

  a_ratioCache[triangle] = ratio;
  return ratio;
} // iGetEarcutTriangleRatio
//------------------------------------------------------------------------------
/// \brief
//------------------------------------------------------------------------------
bool iValidTriangle(const VecPt3d& a_points,
                    const VecInt a_polygon,
                    int a_idx1,
                    int a_idx2,
                    int a_idx3,
                    ValidCache& a_validCache)
{
  Triangle triangle(a_idx1, a_idx2, a_idx3);
  auto validIter = a_validCache.find(triangle);
  if (validIter != a_validCache.end())
    return validIter->second;

  const Pt3d& pt1 = a_points[a_idx1];
  const Pt3d& pt2 = a_points[a_idx2];
  const Pt3d& pt3 = a_points[a_idx3];
  for (size_t pointIdx = 0; pointIdx < a_polygon.size(); ++pointIdx)
  {
    int idx = a_polygon[pointIdx];
    if (idx != a_idx1 && idx != a_idx2 && idx != a_idx3)
    {
      const Pt3d& pt = a_points[idx];
      if (gmTurn(pt1, pt2, pt, 0.0) == TURN_LEFT && gmTurn(pt2, pt3, pt) == TURN_LEFT &&
          gmTurn(pt3, pt1, pt, 0.0) == TURN_LEFT)
      {
        a_validCache[triangle] = false;
        return false;
      }
    }
  }

  a_validCache[triangle] = true;
  return true;
} // iValidTriangle
//------------------------------------------------------------------------------
/// \brief Attempt to generate triangles for a cell by adding a point at the
///        centroid.
/// \param[in] a_ugridTris The triangles to add to.
/// \param[in] a_cellIdx The cell index.
/// \param[in] a_polygonIdxs The indices for the cell polygon.
/// \return true on success (can fail for concave cell)
//------------------------------------------------------------------------------
bool iGenerateCentroidTriangles(XmUGridTriangles2dImpl& a_ugridTris,
                                int a_cellIdx,
                                const VecInt& a_polygonIdxs)
{
  const VecPt3d& points = a_ugridTris.GetPoints();
  size_t numPoints = a_polygonIdxs.size();

  VecPt3d polygon;
  for (size_t pointIdx = 0; pointIdx < numPoints; ++pointIdx)
    polygon.push_back(points[a_polygonIdxs[pointIdx]]);

  Pt3d centroid = gmComputeCentroid(polygon);

  // make sure none of the triangles connected to the centroid are inverted
  for (size_t pointIdx = 0; pointIdx < polygon.size(); ++pointIdx)
  {
    const Pt3d& pt1 = polygon[pointIdx];
    const Pt3d& pt2 = polygon[(pointIdx + 1) % numPoints];

    // centroid should be to the left of each edge
    if (gmTurn(pt1, pt2, centroid, 0.0) != TURN_LEFT)
      return false;
  }

  // add centroid to list of points
  int centroidIdx = a_ugridTris.AddCellCentroid(a_cellIdx, centroid);

  // add triangles
  for (size_t pointIdx = 0; pointIdx < polygon.size(); ++pointIdx)
  {
    int idx1 = a_polygonIdxs[pointIdx];
    int idx2 = a_polygonIdxs[(pointIdx + 1) % numPoints];
    a_ugridTris.AddCellTriangle(a_cellIdx, idx1, idx2, centroidIdx);
  }

  return true;
} // iGenerateCentroidTriangles
//------------------------------------------------------------------------------
/// \brief Generate triangles using ear cut algorithm for plan view 2D cells.
/// \param[in] a_ugridTris The triangles to add to.
/// \param[in] a_cellIdx The cell index.
/// \param[in] a_polygonIdxs The indices for the cell polygon.
//------------------------------------------------------------------------------
void iBuildEarcutTriangles(XmUGridTriangles2dImpl& a_ugridTris,
                           int a_cellIdx,
                           const VecInt& a_polygonIdxs)
{
  VecInt polygonIdxs = a_polygonIdxs;
  const VecPt3d& points = a_ugridTris.GetPoints();

  // continually find best triangle on adjacent edges and cut it off polygon
  RatioCache ratioCache;
  ValidCache validCache;
  while (polygonIdxs.size() >= 4)
  {
    int bestIdx = -1;
    int secondBestIdx = -1;

    int numPoints = (int)polygonIdxs.size();
    double bestRatio = std::numeric_limits<double>::max();
    double secondBestRatio = std::numeric_limits<double>::max();
    for (int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
    {
      int idx1 = polygonIdxs[(pointIdx + numPoints - 1) % numPoints];
      int idx2 = polygonIdxs[pointIdx];
      int idx3 = polygonIdxs[(pointIdx + 1) % numPoints];

      // make sure triangle is valid (not inverted and doesn't have other points in it)
      double ratio = iGetEarcutTriangleRatio(points, idx1, idx2, idx3, ratioCache);
      if (ratio > 0.0)
      {
        if (iValidTriangle(points, polygonIdxs, idx1, idx2, idx3, validCache))
        {
          if (ratio < bestRatio)
          {
            secondBestRatio = bestRatio;
            bestRatio = ratio;
            secondBestIdx = bestIdx;
            bestIdx = pointIdx;
          }
          else if (ratio < secondBestRatio)
          {
            secondBestRatio = ratio;
            secondBestIdx = pointIdx;
          }
        }
      }
    }

    if (bestIdx >= 0)
    {
      if (numPoints == 4 && secondBestIdx >= 0)
        bestIdx = secondBestIdx;

      // cut off the ear triangle
      int polygonIdx1 = (bestIdx + numPoints - 1) % numPoints;
      int polygonIdx2 = bestIdx;
      int polygonIdx3 = (bestIdx + 1) % numPoints;
      int idx1 = polygonIdxs[polygonIdx1];
      int idx2 = polygonIdxs[polygonIdx2];
      int idx3 = polygonIdxs[polygonIdx3];
      a_ugridTris.AddCellTriangle(a_cellIdx, idx1, idx2, idx3);
      polygonIdxs.erase(polygonIdxs.begin() + polygonIdx2);
    }
    else
    {
      std::ostringstream ss;
      ss << "Unable to split cell number " << a_cellIdx + 1 << " into triangles.";
      XM_LOG(xmlog::error, ss.str());
      return;
    }
  }

  // push on remaining triangle
  a_ugridTris.AddCellTriangle(a_cellIdx, polygonIdxs[0], polygonIdxs[1], polygonIdxs[2]);
} // iBuildEarcutTriangles

////////////////////////////////////////////////////////////////////////////////
/// \class XmUGridTriangles2dImpl
/// \brief Class to store XmUGrid triangles. Tracks where midpoints and
///        triangles came from.
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
/// \brief Constructor
//------------------------------------------------------------------------------
XmUGridTriangles2dImpl::XmUGridTriangles2dImpl()
: m_points(new VecPt3d)
, m_triangles(new VecInt)
, m_centroidIdxs()
, m_triangleToCellIdx()
, m_triSearch()
{
} // XmUGridTriangles2dImpl::XmUGridTriangles2dImpl
//------------------------------------------------------------------------------
/// \brief Generate triangles for the UGrid.
/// \param[in] a_ugrid The UGrid for which triangles are generated.
/// \param[in] a_addTriangleCenters Whether or not triangle cells get a centroid added.
//------------------------------------------------------------------------------
void XmUGridTriangles2dImpl::BuildTriangles(const XmUGrid& a_ugrid, bool a_addTriangleCenters)
{
  Initialize(a_ugrid);

  int numCells = a_ugrid.GetCellCount();
  VecInt cellPoints;
  for (int cellIdx = 0; cellIdx < numCells; ++cellIdx)
  {
    if (a_ugrid.GetCellDimension(cellIdx) != 2)
      continue;
    a_ugrid.GetCellPoints(cellIdx, cellPoints);
    bool builtTriangles = false;
    if (a_addTriangleCenters)
      builtTriangles = iGenerateCentroidTriangles(*this, cellIdx, cellPoints);
    if (!builtTriangles)
      iBuildEarcutTriangles(*this, cellIdx, cellPoints);
  }
} // XmUGridTriangles2dImpl::BuildTriangles
//------------------------------------------------------------------------------
/// \brief Generate triangles for the UGrid using earcut algorithm.
/// \param[in] a_ugrid The UGrid for which triangles are generated.
//------------------------------------------------------------------------------
void XmUGridTriangles2dImpl::BuildEarcutTriangles(const XmUGrid& a_ugrid)
{
  Initialize(a_ugrid);

  int numCells = a_ugrid.GetCellCount();
  VecInt cellPoints;
  for (int cellIdx = 0; cellIdx < numCells; ++cellIdx)
  {
    if (a_ugrid.GetCellDimension(cellIdx) != 2)
      continue;
    a_ugrid.GetCellPoints(cellIdx, cellPoints);
    iBuildEarcutTriangles(*this, cellIdx, cellPoints);
  }
} // XmUGridTriangles2dImpl::BuildEarcutTriangles
//------------------------------------------------------------------------------
/// \brief Set triangle activity based on each triangles cell.
//------------------------------------------------------------------------------
void XmUGridTriangles2dImpl::SetCellActivity(const DynBitset& a_cellActivity)
{
  if (a_cellActivity.empty())
  {
    DynBitset emptyActivity;
    GetTriSearch()->SetTriActivity(emptyActivity);
    return;
  }

  DynBitset triangleActivity;
  int numTriangles = (int)m_triangleToCellIdx.size();
  triangleActivity.resize(numTriangles);
  for (size_t triangleIdx = 0; triangleIdx < numTriangles; ++triangleIdx)
  {
    int cellIdx = m_triangleToCellIdx[triangleIdx];
    triangleActivity[triangleIdx] = cellIdx >= a_cellActivity.size() || a_cellActivity[cellIdx];
  }
  GetTriSearch()->SetTriActivity(triangleActivity);
} // XmUGridTriangles2dImpl::SetCellActivity
//------------------------------------------------------------------------------
/// \brief Get the generated triangle points.
/// \return The triangle points
//------------------------------------------------------------------------------
const VecPt3d& XmUGridTriangles2dImpl::GetPoints() const
{
  return *m_points;
} // XmUGridTriangles2dImpl::GetPoints
//------------------------------------------------------------------------------
/// \brief Get the generated triangles.
/// \return a vector of indices for the triangles.
//------------------------------------------------------------------------------
const VecInt& XmUGridTriangles2dImpl::GetTriangles() const
{
  return *m_triangles;
} // XmUGridTriangles2dImpl::GetTriangles
//------------------------------------------------------------------------------
/// \brief Get the generated triangle points as a shared pointer.
/// \return The triangle points
//------------------------------------------------------------------------------
BSHP<VecPt3d> XmUGridTriangles2dImpl::GetPointsPtr()
{
  return m_points;
} // XmUGridTriangles2dImpl::GetPointsPtr
//------------------------------------------------------------------------------
/// \brief Get the generated triangles as a shared pointer.
/// \return a vector of indices for the triangles.
//------------------------------------------------------------------------------
BSHP<VecInt> XmUGridTriangles2dImpl::GetTrianglesPtr()
{
  return m_triangles;
} // XmUGridTriangles2dImpl::GetTrianglesPtr
//------------------------------------------------------------------------------
/// \brief Add a cell centroid point.
/// \param a_cellIdx The cell index for the centroid point
/// \param a_point The centroid point
/// \return The index of the added point
//------------------------------------------------------------------------------
int XmUGridTriangles2dImpl::AddCellCentroid(int a_cellIdx, const Pt3d& a_point)
{
  int centroidIdx = (int)m_points->size();
  m_points->push_back(a_point);
  m_centroidIdxs[a_cellIdx] = centroidIdx;
  return centroidIdx;
} // XmUGridTriangles2dImpl::AddCellCentroid
//------------------------------------------------------------------------------
/// \brief Add a triangle cell.
/// \param[in] a_cellIdx The cell index the triangle is from
/// \param[in] a_idx1 The first triangle point index (counter clockwise)
/// \param[in] a_idx2 The second triangle point index (counter clockwise)
/// \param[in] a_idx3 The third triangle point index (counter clockwise)
//------------------------------------------------------------------------------
void XmUGridTriangles2dImpl::AddCellTriangle(int a_cellIdx, int a_idx1, int a_idx2, int a_idx3)
{
  m_triangles->push_back(a_idx1);
  m_triangles->push_back(a_idx2);
  m_triangles->push_back(a_idx3);
  m_triangleToCellIdx.push_back(a_cellIdx);
} // XmUGridTriangles2dImpl::AddCellTriangle
//------------------------------------------------------------------------------
/// \brief Get the centroid of a cell.
/// \param[in] a_cellIdx The cell index.
/// \return The index of the cell point.
//------------------------------------------------------------------------------
int XmUGridTriangles2dImpl::GetCellCentroid(int a_cellIdx) const
{
  int pointIdx = -1;
  if (a_cellIdx >= 0 && a_cellIdx < (int)m_centroidIdxs.size())
    pointIdx = m_centroidIdxs[a_cellIdx];
  return pointIdx;
} // XmUGridTriangles2dImpl::GetCellCentroid
//------------------------------------------------------------------------------
/// \brief Get the cell index and interpolation values intersected by a point.
/// \param[in] a_point The point to intersect with the UGrid.
/// \param[out] a_idxs The interpolation points.
/// \param[out] a_weights The interpolation weights.
/// \return The cell intersected by the point or -1 if outside of the UGrid.
//------------------------------------------------------------------------------
int XmUGridTriangles2dImpl::GetIntersectedCell(const Pt3d& a_point,
                                               VecInt& a_idxs,
                                               VecDbl& a_weights)
{
  if (!m_triSearch)
    GetTriSearch();
  int cellIdx = -1;
  int triangleLocation;
  if (m_triSearch->InterpWeightsTriangleIdx(a_point, triangleLocation, a_idxs, a_weights))
  {
    int triangleIdx = triangleLocation / 3;
    cellIdx = m_triangleToCellIdx[triangleIdx];
  }
  return cellIdx;
} // XmUGridTriangles2dImpl::GetIntersectedCell
//------------------------------------------------------------------------------
/// \brief Initialize triangulation for a UGrid.
/// \param[in] a_ugrid The UGrid for which triangles are generated.
//------------------------------------------------------------------------------
void XmUGridTriangles2dImpl::Initialize(const XmUGrid& a_ugrid)
{
  *m_points = a_ugrid.GetLocations();
  m_triangles->clear();
  m_centroidIdxs.assign(a_ugrid.GetCellCount(), -1);
  m_triangleToCellIdx.clear();
  m_triSearch.reset();
} // XmUGridTriangles2dImpl::Initialize
//------------------------------------------------------------------------------
/// \brief Get triangle search object.
//------------------------------------------------------------------------------
BSHP<GmTriSearch> XmUGridTriangles2dImpl::GetTriSearch()
{
  if (!m_triSearch)
  {
    m_triSearch = GmTriSearch::New();
    m_triSearch->TrisToSearch(m_points, m_triangles);
  }
  return m_triSearch;
} // XmUGridTriangles2dImpl::GetTriSearch

} // namespace

////////////////////////////////////////////////////////////////////////////////
/// \class XmUGridTriangles2d
/// \brief Class to store XmUGrid triangles. Tracks where midpoints and
///        triangles came from.
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
/// \brief Build an instance of XmUGridTriangles2d
/// \return The new instance.
//------------------------------------------------------------------------------
BSHP<XmUGridTriangles2d> XmUGridTriangles2d::New()
{
  BSHP<XmUGridTriangles2d> triangles(new XmUGridTriangles2dImpl);
  return triangles;
} // XmUGridTriangles2d::New
//------------------------------------------------------------------------------
/// \brief Default contructor.
//------------------------------------------------------------------------------
XmUGridTriangles2d::XmUGridTriangles2d()
{
} // XmUGridTriangles2d::XmUGridTriangles2d
//------------------------------------------------------------------------------
/// \brief Destructor.
//------------------------------------------------------------------------------
XmUGridTriangles2d::~XmUGridTriangles2d()
{
} // XmUGridTriangles2d::XmUGridTriangles2d

} // namespace xms

#ifdef CXX_TEST
//------------------------------------------------------------------------------
// Unit Tests
//------------------------------------------------------------------------------
using namespace xms;
#include <xmsextractor/ugrid/XmUGridTriangles2d.t.h>

#include <xmscore/testing/TestTools.h>

////////////////////////////////////////////////////////////////////////////////
/// \class XmUGridTriangles2dUnitTests
/// \brief Class to to test XmUGridTriangles2d
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
/// \brief Test creating triangles using cell centroid.
//------------------------------------------------------------------------------
void XmUGridTriangles2dUnitTests::testBuildCentroidTrianglesOnTriangle()
{
  VecPt3d points = {{0, 0, 0}, {1, 0, 0}, {0.5, 1, 0}};
  VecInt cells = {XMU_TRIANGLE, 3, 0, 1, 2};
  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
  TS_REQUIRE_NOT_NULL(ugrid);
  XmUGridTriangles2dImpl triangles;

  // test building cetroid in triangle cell
  triangles.BuildTriangles(*ugrid, true);

  VecPt3d triPointsOut = triangles.GetPoints();
  VecPt3d triPointsExpected = {{0, 0, 0}, {1, 0, 0}, {0.5, 1, 0}, {0.5, 1 / 3.0, 0}};
  TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

  VecInt trianglesOut = triangles.GetTriangles();
  VecInt trianglesExpected = {0, 1, 3, 1, 2, 3, 2, 0, 3};
  TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);

  TS_ASSERT_EQUALS(3, triangles.GetCellCentroid(0));

  VecInt idxs;
  VecDbl weights;
  // point intersecting last triangle
  int cellIdx = triangles.GetIntersectedCell(Pt3d(0.25, 0.25, 0), idxs, weights);
  TS_ASSERT_EQUALS(0, cellIdx);
  VecInt idxsExpected = {2, 0, 3};
  TS_ASSERT_EQUALS(idxsExpected, idxs);
  VecDbl weightsExpected = {0.125, 0.5, 0.375};
  TS_ASSERT_EQUALS(weightsExpected, weights);
  cellIdx = triangles.GetIntersectedCell(Pt3d(0.75, 0.25, 0), idxs, weights);
  TS_ASSERT_EQUALS(0, cellIdx);
  idxsExpected = {1, 2, 3};
  TS_ASSERT_EQUALS(idxsExpected, idxs);
  weightsExpected = {0.5, 0.125, 0.375};
  TS_ASSERT_EQUALS(weightsExpected, weights);
  cellIdx = triangles.GetIntersectedCell(Pt3d(0.5, 0.25, 0), idxs, weights);
  TS_ASSERT_EQUALS(0, cellIdx);
  idxsExpected = {0, 1, 3};
  TS_ASSERT_EQUALS(idxsExpected, idxs);
  weightsExpected = {0.125, 0.125, 0.75};
  TS_ASSERT_EQUALS(weightsExpected, weights);

  // test without building centroid in triangle cell
  triangles.BuildTriangles(*ugrid, false);

  triPointsOut = triangles.GetPoints();
  TS_ASSERT_EQUALS(points, triPointsOut);

  trianglesOut = triangles.GetTriangles();
  trianglesExpected = {0, 1, 2};
  TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);

  TS_ASSERT_EQUALS(-1, triangles.GetCellCentroid(0));

  cellIdx = triangles.GetIntersectedCell(Pt3d(0.5, 0.25, 0), idxs, weights);
  TS_ASSERT_EQUALS(0, cellIdx);
  idxsExpected = {0, 1, 2};
  TS_ASSERT_EQUALS(idxsExpected, idxs);
  weightsExpected = {0.375, 0.375, 0.25};
  TS_ASSERT_EQUALS(weightsExpected, weights);

} // XmUGridTriangles2dUnitTests::testBuildCentroidTrianglesOnTriangle
//------------------------------------------------------------------------------
/// \brief Test creating triangles on a quad using cell centroid.
//------------------------------------------------------------------------------
void XmUGridTriangles2dUnitTests::testBuildCentroidTrianglesOnQuad()
{
  VecPt3d points = {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}};
  VecInt cells = {XMU_QUAD, 4, 0, 1, 2, 3};
  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
  TS_REQUIRE_NOT_NULL(ugrid);
  XmUGridTriangles2dImpl triangles;
  triangles.BuildTriangles(*ugrid, true);
  VecPt3d triPointsOut = triangles.GetPoints();
  VecPt3d triPointsExpected = {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0.5, 0.5, 0}};
  TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

  VecInt trianglesOut = triangles.GetTriangles();
  VecInt trianglesExpected = {0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4};
  TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);

  TS_ASSERT_EQUALS(4, triangles.GetCellCentroid(0));
} // XmUGridTriangles2dUnitTests::testBuildCentroidTrianglesOnQuad
//------------------------------------------------------------------------------
/// \brief Test creating triangles using cell centroid for linear 2D cell types.
//------------------------------------------------------------------------------
void XmUGridTriangles2dUnitTests::testBuildCentroidTriangles2dCellTypes()
{
  // clang-format off
  VecPt3d points = {
    {0, 0, 0},   // 0
    {10, 0, 0},  // 1
    {20, 0, 0},  // 2
    {30, 0, 0},  // 3
    {40, 0, 0},  // 4
    {0, 10, 0},  // 5
    {10, 10, 0}, // 6
    {20, 10, 0}, // 7
    {40, 10, 0}, // 8
    {0, 20, 0},  // 9
    {10, 20, 0}, // 10
    {20, 20, 0}, // 11
    {30, 20, 0}, // 12
    {40, 20, 0}  // 13
  };

  // Cell type (5), number of points (3), point numbers, counterclockwise
  std::vector<int> cells = {(int)XMU_QUAD, 4, 0, 1, 6, 5,             // 0
                            (int)XMU_PIXEL, 4, 1, 2, 6, 7,            // 1
                            (int)XMU_TRIANGLE, 3, 2, 3, 7,            // 2
                            (int)XMU_POLYGON, 6, 3, 4, 8, 13, 12, 7}; // 3
  // clang-format on

  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
  TS_REQUIRE_NOT_NULL(ugrid);
  XmUGridTriangles2dImpl triangles;
  triangles.BuildTriangles(*ugrid, true);

  VecPt3d triPointsOut = triangles.GetPoints();
  // clang-format off
  VecPt3d triPointsExpected = {
    {0.0, 0.0, 0.0},
    {10.0, 0.0, 0.0},
    {20.0, 0.0, 0.0},
    {30.0, 0.0, 0.0},
    {40.0, 0.0, 0.0},
    {0.0, 10.0, 0.0},
    {10.0, 10.0, 0.0},
    {20.0, 10.0, 0.0},
    {40.0, 10.0, 0.0},
    {0.0, 20.0, 0.0},
    {10.0, 20.0, 0.0},
    {20.0, 20.0, 0.0},
    {30.0, 20.0, 0.0},
    {40.0, 20.0, 0.0},

    // added centroids
    {5.0, 5.0, 0.0},                               // 14 - quad centroid
    {15.0, 5.0, 0.0},                              // 15 - pixel centroid
    {23.333333333333332, 3.3333333333333335, 0.0}, // 16 - triangle centroid
    {33.333333333333336, 10.0, 0.0}                // 17 - polygon centroid
  };
  // clang-format on
  TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

  VecInt trianglesOut = triangles.GetTriangles();
  // clang-format off
  VecInt trianglesExpected = {
    0, 1, 14, 1, 6, 14, 6, 5, 14, 5, 0, 14, // quad
    1, 2, 15, 2, 7, 15, 7, 6, 15, 6, 1, 15, // pixel
    2, 3, 16, 3, 7, 16, 7, 2, 16,           // triangle
    3, 4, 17, 4, 8, 17, 8, 13, 17, 13, 12, 17, 12, 7, 17, 7, 3, 17}; // polygon
  // clang-format on
  TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);
} // XmUGridTriangles2dUnitTests::testBuildCentroidTriangles2dCellTypes
//------------------------------------------------------------------------------
/// \brief Test creating plan view 2D triangles using ear cut algorithm.
//------------------------------------------------------------------------------
void XmUGridTriangles2dUnitTests::testBuildEarcutTriangles()
{
  {
    // V shaped cell
    // clang-format off
    VecPt3d points = {
      {0, 0, 0},   // 0
      {10, 0, 0},  // 1
      {1, 1, 0},   // 2
      {0, 10, 0},  // 3
      {10, 10, 0}  // 4
    };

    std::vector<int> cells = {
      XMU_QUAD, 4, 0, 1, 2, 3,
    };
    // clang-format on

    std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
    XmUGridTriangles2dImpl ugridTris;

    ugridTris.BuildTriangles(*ugrid, true);

    VecPt3d triPointsOut = ugridTris.GetPoints();
    VecPt3d triPointsExpected = points;
    TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

    VecInt trianglesOut = ugridTris.GetTriangles();
    VecInt trianglesExpected = {2, 3, 0, 0, 1, 2};
    TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);
  }

  {
    // house shaped cell
    // clang-format off
    VecPt3d points = {
      {0, 0, 0},   // 0
      {10, 0, 0},  // 1
      {10, 10, 0}, // 2
      {5, 11, 0},  // 3
      {0, 10, 0},  // 4
    };

    std::vector<int> cells = {(int)XMU_POLYGON, 5, 0, 1, 2, 3, 4};
    // clang-format on

    std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
    XmUGridTriangles2dImpl ugridTris;
    ugridTris.BuildEarcutTriangles(*ugrid);

    VecPt3d triPointsOut = ugridTris.GetPoints();
    VecPt3d triPointsExpected = points;
    TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

    VecInt trianglesOut = ugridTris.GetTriangles();
    VecInt trianglesExpected = {4, 0, 1, 1, 2, 3, 1, 3, 4};
    TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);
  }
} // XmUGridTriangles2dUnitTests::testBuildEarcutTriangles
//------------------------------------------------------------------------------
/// \brief Test creating triangles for centroid and earcut cells.
//------------------------------------------------------------------------------
void XmUGridTriangles2dUnitTests::testBuildCentroidAndEarcutTriangles()
{
  // 7----6---------3----2
  // |    |         |    |
  // |    |         |    |
  // |    |         |    |
  // |    |   (8)   |    |
  // |    |         |    |
  // |    |         |    |
  // |    |         |    |
  // |    5---------4    |
  // |                   |
  // |                   |
  // |                   |
  // 0-------------------1
  // clang-format off
  VecPt3d points = {
    { 0,  0, 0}, // 0
    {15,  0, 0}, // 1
    {15, 15, 0}, // 2
    {10, 15, 0}, // 3
    {10,  5, 0}, // 4
    { 5,  5, 0}, // 5
    { 5, 15, 0}, // 6
    { 0, 15, 0}  // 7
  };

  // Cell type (5), number of points (3), point numbers, counterclockwise
  std::vector<int> cells = {
    XMU_POLYGON, 8, 0, 1, 2, 3, 4, 5, 6, 7,
    XMU_QUAD, 4, 3, 6, 5, 4
  };
  // clang-format on

  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
  XmUGridTriangles2dImpl ugridTris;

  ugridTris.BuildTriangles(*ugrid, true);

  VecPt3d triPointsOut = ugridTris.GetPoints();
  VecPt3d triPointsExpected = points;
  triPointsExpected.push_back({7.5, 10, 0});
  TS_ASSERT_EQUALS(triPointsExpected, triPointsOut);

  VecInt trianglesOut = ugridTris.GetTriangles();
  VecInt trianglesExpected = {
    // clang-format off
    2, 3, 4,   5, 6, 7,   1, 2, 4,   0, 1, 4,   0, 4, 5,   0, 5, 7, // earcut
    3, 6, 8,   6, 5, 8,   5, 4, 8,   4, 3, 8 // centroid
    // clang-format off
  };
  TS_ASSERT_EQUALS(trianglesExpected, trianglesOut);
} // XmUGridTriangles2dUnitTests::testBuildCentroidAndEarcutTriangles

#endif


//
// $Id: ParameterEstimator.cpp 2051 2010-06-15 18:39:13Z chambm $
//
//
// Original author: Darren Kessner <darren@proteowizard.org>
//
// Copyright 2006 Louis Warschaw Prostate Cancer Center
//   Cedars Sinai Medical Center, Los Angeles, California  90048
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "ParameterEstimator.hpp"
//#include "DerivativeTest.hpp" // for testing numerical derivatives only

#include "pwiz/utility/misc/Std.hpp"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace ublas = boost::numeric::ublas;

namespace pwiz {
namespace frequency {

class ParameterEstimatorImpl : public ParameterEstimator
{
    public:

    ParameterEstimatorImpl(const Function& function,
                               const Data& data,
                               const Parameters& initialEstimate);

    virtual const Parameters& estimate() const {return p_;}
    virtual void estimate(const Parameters& p) {p_ = p;}
    virtual double error() const {return e_(p_);}
    virtual double iterate(ostream* log);

    private:

    const Function& f_;
    const Data& data_;
    Parameters p_;
    Function::ErrorFunction e_;

    Parameters solve(const ublas::matrix<double>& A , const ublas::vector<double>& y) const;
};

auto_ptr<ParameterEstimator> ParameterEstimator::create(const Function& function,
                                                                const Data& data,
                                                                const Parameters& initialEstimate)
{
    return auto_ptr<ParameterEstimator>(new ParameterEstimatorImpl(function, data, initialEstimate));
}

ParameterEstimatorImpl::ParameterEstimatorImpl(const Function& function,
                                                       const Data& data,
                                                       const Parameters& initialEstimate)
:   f_(function),
    data_(data),
    p_(initialEstimate),
    e_(f_, data_)
{
    if (function.parameterCount() != initialEstimate.size())
        throw logic_error("[ParameterEstimator::ParameterEstimatorImpl()] Wrong number of parameters.");
}

double ParameterEstimatorImpl::iterate(ostream* log)
{
    // DerivativeTest::testDerivatives< complex<double> >(e_, p_); // testing only

    double error_old = error();

    ublas::vector<double> d = e_.dp(p_);
    ublas::matrix<double> d2 = e_.dp2(p_);

    // calculate new estimate:
    //   correction == inverse(d2) * d
    //   p_new = p_old - correction

    Parameters correction = solve(d2, d);

    // compare error change to prediction from parabolic approximation
    ublas::vector<double> dp = -correction;
    double error_change_predicted = inner_prod(d, dp) + .5*inner_prod(dp, prod(d2,dp));
    double error_change_actual = e_(p_-correction) - error_old;

    if (log) *log << "d: " << d << endl;
    if (log) *log << "d2: " << d2 << endl;
    if (log) *log << "correction: " << correction << endl;
    if (log) *log << "error_change_predicted: " << error_change_predicted << endl;
    if (log) *log << "error_change_actual: " << error_change_actual << endl;

    // if we can decrease error -- go for it!
    if (error_change_actual < 0)
    {
        p_ -= correction;
        return error_change_actual;
    }

    // error is going to increase if we make the full correction;
    // backtrack along correction gradient to find decreasing error

    Parameters correction_backtrack = correction;
    int zeroCount = 0;

    for (int i=0; i<10; i++)
    {
        correction_backtrack /= 2;
        double error_change_backtrack = e_(p_ - correction_backtrack) - error_old;
        if (log) *log << "error_change_backtrack: " << error_change_backtrack << endl;
        if (error_change_backtrack < 0)
        {
            // found negative error change -- go for it!
            p_ -= correction_backtrack;
            return error_change_backtrack;
        }
        else if (error_change_backtrack == 0)
        {
            zeroCount++;
            if (zeroCount >= 3) // stuck on zero -- we're outta here
                break;
        }
    }

    // don't correct
    if (log) *log << "No correction.\n";
    return 0;
}

ParameterEstimatorImpl::Parameters ParameterEstimatorImpl::solve(const ublas::matrix<double>& A , const ublas::vector<double>& y) const
{
    // solve Ax = y

    ublas::matrix<double> A_factorized = A;

    ublas::permutation_matrix<size_t> pm(e_.parameterCount());
    int singular = lu_factorize(A_factorized, pm);
    if (singular)
        throw runtime_error("[ParameterEstimatorImpl::solve()] A is singular.");

    ublas::vector<double> result(y);
    lu_substitute(A_factorized, pm, result);
    return result;
}

} // namespace frequency
} // namespace pwiz


#include <gtest/gtest.h>
#include "pitts_tensor2_random.hpp"
#include "pitts_tensor2_eigen_adaptor.hpp"
#include <Eigen/Dense>

namespace
{
  // helper function for copy with a return instead of an argument
  template<typename T>
  auto copy_return(const PITTS::Tensor2<T>& a)
  {
    PITTS::Tensor2<T> b(a.r1(), a.r2());
    copy(a, b);
    return b;
  }
}

TEST(PITTS_Tensor2_EigenAdaptor, simple_const)
{
  using Tensor2_double = PITTS::Tensor2<double>;

  Tensor2_double t2(3,10);

  randomize(t2);
  const Tensor2_double t2_const = copy_return(t2);
  const auto t2Map = ConstEigenMap(t2_const);
  ASSERT_EQ(t2.r1(), t2Map.rows());
  ASSERT_EQ(t2.r2(), t2Map.cols());

  for(int i = 0; i < t2.r1(); i++)
    for(int j = 0; j < t2.r2(); j++)
    {
      EXPECT_EQ(t2(i,j), t2Map(i,j));
    }
}

TEST(PITTS_Tensor2_EigenAdaptor, simple_modify)
{
  using Tensor2_double = PITTS::Tensor2<double>;

  Tensor2_double t2(3,10);

  randomize(t2);
  auto t2Map = EigenMap(t2);
  ASSERT_EQ(t2.r1(), t2Map.rows());
  ASSERT_EQ(t2.r2(), t2Map.cols());

  const Tensor2_double oldT2 = copy_return(t2);
  t2Map = Eigen::MatrixXd::Random(3,10);

  for(int i = 0; i < t2.r1(); i++)
    for(int j = 0; j < t2.r2(); j++)
    {
      EXPECT_EQ(t2(i,j), t2Map(i,j));
      EXPECT_NE(oldT2(i,j), t2(i,j));
    }
}