/*-------------------------------------------------------------------------------------*/
/*  NOMAD - Nonsmooth Optimization by Mesh Adaptive Direct search - version 3.0.0      */
/*                                                                                     */
/*  Copyright (C) 2001-2008  Mark Abramson        - the Boeing Company, Seattle        */
/*                           Charles Audet        - Ecole Polytechnique, Montreal      */
/*                           Gilles Couture       - Ecole Polytechnique, Montreal      */
/*                           John Dennis          - Rice University, Houston           */
/*                           Sebastien Le Digabel - Ecole Polytechnique, Montreal      */
/*                                                                                     */
/*  funded in part by AFOSR and Exxon Mobil                                            */
/*                                                                                     */
/*  Author: Sebastien Le Digabel                                                       */
/*                                                                                     */
/*  Contact information:                                                               */
/*    Ecole Polytechnique de Montreal - GERAD                                          */
/*    C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada                  */
/*    e-mail: Sebastien.Le.Digabel@gerad.ca                                            */
/*    phone : 1-514-340-6053 #6673                                                     */
/*    fax   : 1-514-340-5665                                                           */
/*                                                                                     */
/*  This program is free software: you can redistribute it and/or modify it under the  */
/*  terms of the GNU General Public License as published by the Free Software          */
/*  Foundation, either version 3 of the License, or (at your option) any later         */
/*  version.                                                                           */
/*                                                                                     */
/*  This program is distributed in the hope that it will be useful, but WITHOUT ANY    */
/*  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A    */
/*  PARTICULAR PURPOSE.  See the GNU General Public License for more details.          */
/*                                                                                     */
/*  You should have received a copy of the GNU General Public License along with this  */
/*  program. If not, see <http://www.gnu.org/licenses/>.                               */
/*                                                                                     */
/*  You can find information on the NOMAD software at www.gerad.ca/nomad               */
/*-------------------------------------------------------------------------------------*/
#ifndef __MESH__
#define __MESH__

#include "Point.hpp"
#include "Uncopyable.hpp"

class Mesh : private Uncopyable {

  /*--------------------------------------------------------------*/

private:

  static double _mesh_update_basis;         // mesh update basis (tau)
  static int    _mesh_coarsening_exponent;  // mesh coarsening exponent
  static int    _mesh_refining_exponent;    // mesh refining exponent
  static int    _initial_mesh_index;        // initial mesh index (l0)
  static int    _mesh_index;                // mesh index         (lk)

  static int    _min_mesh_index;            // minimal value reached by the mesh index
  static int    _max_mesh_index;            // maximal ''''' ''''''' '' ''' '''' '''''

  Point         _initial_mesh_size;         // \Delta_0^m (absolute values; one delta/var.)

  Point         _min_mesh_size;             // equivalent of _min_poll_size for the mesh size
                                            // parameter \Delta_k^m

  Point         _min_poll_size;             // \Delta^p_min (absolute values; one delta/var.)
                                            // _min_poll_size can be undefined or incomplete

  /*--------------------------------------------------------------*/

public:

  // constructor:
  explicit Mesh ( const Point            & delta_m_0                ,
		  const Point            & delta_p_min   = Point()  ,
		  const Point            & delta_m_min   = Point()    );

  // destructor:
  ~Mesh ( void ) {}

  // static members initialization:
  static void init ( double mesh_update_basis        ,
		     int    mesh_coarsening_exponent ,
		     int    mesh_refining_exponent   ,
		     int    initial_mesh_index         );

  // display:
  void display( std::ostream & out ) const;

  // get/set the mesh index:
  static int  get_mesh_index ( void  ) { return Mesh::_mesh_index; }
  static void set_mesh_index ( int l ) { Mesh::_mesh_index = l;    }

  // get min/max mesh indexes:
  static int  get_max_mesh_index ( void ) { return Mesh::_max_mesh_index; }
  static int  get_min_mesh_index ( void ) { return Mesh::_min_mesh_index; }

  // get tau:
  static double get_mesh_update_basis ( void ) { return Mesh::_mesh_update_basis; }

  // update the mesh:
  static void update ( success_type success , int & mesh_index );
  static void update ( success_type success ) {
    Mesh::update ( success , Mesh::_mesh_index );
  }

  // reset the mesh index (invoked by Mads::phase_one()):
  static void reset_mesh_index ( void ) { Mesh::_mesh_index = Mesh::_initial_mesh_index; }

  // get_n:
  int get_n ( void ) const { return _initial_mesh_size.size(); }

  // get delta_m (mesh size parameter), of size nc:
  void get_delta_m ( Point & delta_m , int mesh_index ) const;

  // get delta_p (poll size parameter), of size nc:
  void get_delta_p ( Point & delta_p , int mesh_index ) const;

  // check the minimal poll size criterion:
  bool check_min_poll_size_criterion ( int mesh_index ) const;

  // check the minimal mesh size criterion:
  bool check_min_mesh_size_criterion ( int mesh_index ) const;
};

/*--------------------------------------------------------------*/

// display:
inline std::ostream & operator << ( std::ostream & out ,
				    const Mesh   & m     ) {
  m.display(out);
  return out;
}

#endif

