/* agent_circuit.cc */

#ifdef COMPILE_AGENT_CIRCUIT


#include "pipe.h"
#include "agent_circuit.h"

dc_agent_circuit circuit_agent; /* declared ectern */

/* check for a valid type */
inline bool is_circuit_pfn( dc_component *c )
{ }

inline bool     cir_set_dV   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::dV, &v );}
inline dc_data *cir_get_dV   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::dV );}
inline bool     cir_set_I    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::I, &v );}
inline dc_data *cir_get_I    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::I );}
inline bool     cir_set_QHeat( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::QHeat, &v );}
inline dc_data *cir_get_QHeat( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::QHeat );}
inline bool     cir_set_R    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::R, &v );}
inline dc_data *cir_get_R    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::R );}
inline bool     cir_set_C    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::C, &v );}
inline dc_data *cir_get_C    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::C );}
inline bool     cir_set_L    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::L, &v );}
inline dc_data *cir_get_L    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::L );}
inline bool     cir_set_dVMax( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::dVMax, &v );}
inline dc_data *cir_get_dVMax( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::dVMax );}
inline bool     cir_set_dVMin( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::dVMin, &v );}
inline dc_data *cir_get_dVMin( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::dVMin );}
inline bool     cir_set_IMax ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::IMax, &v );}
inline dc_data *cir_get_IMax ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::IMax );}
inline bool     cir_set_IMin ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::IMin, &v );}
inline dc_data *cir_get_IMin ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::IMin );}
inline bool     cir_set_VZn  ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::VZn, &v );}
inline dc_data *cir_get_VZn  ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::VZn );}
inline bool     cir_set_Spd  ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::Spd, &v );}
inline dc_data *cir_get_Spd  ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::Spd );}
inline bool     cir_set_kI   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::kI, &v );}
inline dc_data *cir_get_kI   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::kI );}
inline bool     cir_set_kV   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::kV, &v );}
inline dc_data *cir_get_kV   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::kV );}
inline bool     cir_set_On   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::On, &v );}
inline dc_data *cir_get_On   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::On );}
inline bool     cir_set_Y    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::Y, &v );}
inline dc_data *cir_get_Y    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::Y );}
inline bool     cir_set_Ig   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::Ig, &v );}
inline dc_data *cir_get_Ig   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::Ig );}
inline bool     cir_set_Nu   ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::Nu, &v );}
inline dc_data *cir_get_Nu   ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::Nu );}
inline bool     cir_set_T    ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::T, &v );}
inline dc_data *cir_get_T    ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::T );}
inline bool     cir_set_TMax ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::TMax, &v );}
inline dc_data *cir_get_TMax ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::TMax );}
inline bool     cir_set_TMin ( dc_pipe &p, dc_data &v )
{ return circuit_agent.set_element( p.get_tag(), dc_agent_circuit::TMin, &v );}
inline dc_data *cir_get_TMin ( dc_pipe &p )
{ return circuit_agent.get_element( p.get_tag(), dc_agent_circuit::TMin );}


dc_agent_circuit::dc_agent_circuit(void)
{
  NNodes = 0;
  A_mx = Y_mx = nil;
  Is_vec = Vn_vec = Vb_vec = nil;
  Ebranch.clear();
  set_min_dt_criteria(); // Set the default values using functions
  set_termination_criteria(); 
  return;
}

dc_agent_circuit::~dc_agent_circuit(void)
{
  NNodes = 0;
  delete A_mx; delete Y_mx;
  delete Is_vec; delete Vn_vec; delete Vb_vec;
  dic_item di;
  forall_items(di, Ebranch) {
    delete Ebranch.inf(di);
    Ebranch.del_item(di);
  }
  set_min_dt_criteria(); // Set the default values using functions
  set_termination_criteria(); 
  return;  
}

bool model_reset(void) // reset every thing as if new 
{
  ~dc_agent_circuit();
}

bool dc_agent_circuit::set_min_dt_criteria(double dt)
{
  if (dt > 0.0)
    {minDt = dt; return false;}
  else
    {cerr << " Bad dt value :" << dt << " in dc_agent_circuit::set_min_dt_criteria, ignoring \n";
     return true;}
}

bool dc_agent_circuit::set_termination_criteria(double dV, double vbfrac, int maxIter)
{
  if ( (dV > 0.0) || (vbfrac > 0.0) || (maxiter > 0) )
    { minDv = dV; minVbfrac = vbfrac; this->maxIter = maxIter; 
      return false;}
  else
    {cerr << " Bad values dv,vbfrac,maxiter :" << dV << "," << vbfrac << "," <<
       maxIter<< " in dc_agent_circuit::set_termination_criteria, ignoring \n";
     return true;}
}

bool set_connection( tag src, bool sPlus, tag tgt, tPlus)
{
  
  return false;
}

dc_data *get_element(tag branch, info_type infoIndex)
{
 dic_item di = Ebranch.lookup(branch);
 if (!(di)) 
   {cerr << "dc_agent_circuit::get_element, tag not found : " <<branch<< "\n";
    return nil;} // return error if bad tag

 Eag_branch *eb = di.inf();
 if ((infoIndex <= CV_Undef) || (infoIndex >= Qheat))
   {cerr << "dc_agent_circuit::get_element, enum infoIndex not valid : " 
      <<infoIndex<< "\n"; return nil;} // return error if bad info

 dc_data *d = (*(eb->info))[infoIndex];
 if (!(d)) // return error if bad info
   {cerr << "dc_agent_circuit::get_element, no data corresp to infoIndex: "
      << infoIndex << " in branch : " <<infoIndex<< "\n"; return nil;} 

 // return data otherwise
 return(d);
}

bool model_gen( void ) // currently used internally
{
  if (A_mx || Y_mx || Is_vec || Vn_vec || Vb_vec)
    {cerr << "dc_agent_circuit::model_gen, already set Matrix or vectors "
       "A:" << A_mx << " Y:" << Y_mx << " Is:" << Is_vec << " Vn:" 
	 Vn_vec << " Vb:" << Vb_vec << "\n";
     return true;}
  
  if (NNodes <= 0)
    {cerr << "dc_agent_circuit::model_gen, Nodes still zero or bad code N = " 
       << NNodes << "\n";
     return true;}

  A_mx->dc_rect_matrix(n,m, "dc_agent_circuit_A_mx", nil);
  Y_mx->dc_rect_matrix(n,m, "dc_agent_circuit_Y_mx", nil);
  Is_vec->dc_rect_matrix(n,m, "dc_agent_circuit_Is_vec", nil);
  Vn_vec->dc_rect_matrix(n, "dc_agent_circuit_Vn_vec", nil);
  Vb_vec->dc_rect_matrix(m, "dc_agent_circuit_Vb_vec", nil);
  
  // Fill matrices and do precomputing
    
  return false;
}

bool model_sim(dc_real *dc_dt) // simulate circuit for dt seconds
{
  double dt = dc_dt->get_mag();

  if (dt <= 0)
    {cerr << "dc_agent_circuit::model_sim, Bad time dt = " 
       << dt << " " << (*dc_dt) << "\n";
     return true;}

  double t = 0.0;
  while (t < dt)
    {
      
    }

  return false;
}

#endif // end ifdef COMPILE_AGENT_CIRCUIT

