// GenFem - A high-level finite element library
// Copyright (C) 2010-2026 Eric Bechet
//
// See the LICENSE file for license information and contributions.
// Please report all bugs and problems to <bechet@cadxfem.org>.

#ifndef _SPACEREDUCERFORSTABLEMULTIPLIERS_H_
#define _SPACEREDUCERFORSTABLEMULTIPLIERS_H_


#include "simpleFunction.h"
#include "GModel.h"
#include "groupOfElements.h"
#include "gmshLevelset.h"
#include "dofManager.h"

class SpaceReducerForStableMultipliers
{
  private :
    typedef MVertex * NodeType;
    typedef std::pair <NodeType , NodeType > EdgeType;
    typedef std::pair <EdgeType , double > EdgeScoreType;
    
  private :
    groupOfLagMultElements * _LevelSetElements;
    std::map < NodeType , EdgeType > _NodeToEdgeMap;
    std::set< NodeType > _winner_nodes;
    std::set< EdgeType > _AllEdges; // set of all edges
    std::set< int > _PhV; // set of edge'nodes of vital vertices
    std::set< NodeType > _looser_nodes;
//     gLevelset *_ls;
    
  private :
    // field tag
    int _FieldTag;
    // decimation algorithm result in _winner_nodes set
    void SortNodes (void) ;
    // initialisation of needed sets
    void fillNodeToEdgeMap(std::set< EdgeType > & Se , std::set< NodeType > & Sn) ;
    // find edge in the element associate with node
    EdgeType findEdge(NodeType v, MElement * e);
    // verify if node belong to edge  // ...normaly has to be done when cutting model ...
    bool NodeBelongToEdge(NodeType v, EdgeType edge);
    // compute score
    void ComputeScore(std::set< EdgeType > & Se, std::set< NodeType > & Sn, std::map < NodeType , int > & NodesScore);
    // compute number of incident edges in Se to node v
    int ComputeIncidentEdges(std::set< EdgeType > & Se, NodeType & v);
    // compute number of incident edges in Se to node v
    int ComputeIncidentEdges(std::set< EdgeType > & Se, NodeType & v, std::set< NodeType > & Nr);
    // get lowest  (no need to sort just get the lowest)
    NodeType getNodeWithLowestScore(std::map < NodeType , int > & NodesScore);
    // kill connected edges
    void killConnectedEdges (std::set< EdgeType > & Se , std::set< NodeType > & Sn, NodeType v);
    void killConnectedEdges (std::set< EdgeType > & Se , std::set< NodeType > & Sn, NodeType v, std::map<NodeType, int > & NodesScore);
    
  public :
    SpaceReducerForStableMultipliers(groupOfLagMultElements * LevelSetElements , /*gLevelset *ls, */int FieldTag) : /*_ls(ls),*/ _FieldTag(FieldTag)
    {
      _LevelSetElements = LevelSetElements;
      SortNodes();
    }
    virtual void BuildLinearConstraints( bool comp [], dofManager<double> *pAssembler);
};

#endif
