// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// OBESS_Voltage_Controlled.hh
//  --- declaration of class OBESS_Voltage_Controlled


#ifndef OBESS_Voltage_Controlled_HH
#define OBESS_Voltage_Controlled_HH


#include <cstdlib>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <utility>
#include "EnergyStorage.hh"

using std :: vector ;
using std :: string ;
using std :: ostream ;
using std :: ostringstream ;
using std :: cerr ;
using std :: endl ;
using std :: pair ;
using std :: make_pair ;



// -----
// Generic on-board energy storage system class. Uses V-I characteristics
// parameters similar to Generic_ESS_Substation class.
// 汎用車載エネルギー蓄積装置クラス。Generic_ESS_Substation クラスに似た
// V-I 特性パラメータを使用。
// -----
class OBESS_Voltage_Controlled
  : public ESS_OnBoard ,
    public OBESS_Expander
{
private :

  // -----
  // Energy storage device model.
  // エネルギー蓄積素子モデル。
  // -----
  EnergyStorageDevice * _esd ;

  // -----
  // DC-DC converter losses model.
  // DC-DC コンバータ損失モデル。
  // -----
  DC_DC_Converter_Losses * _ddcl ;

  // -----
  // Characteristic parameters of the system. Compared with class
  // OBESS_RefSOC_Controlled, current limiter when the train is at
  // standstill is the only component used in this class. 
  // 装置の特性パラメータ群。OBESS_RefSOC_Controlled クラスと比較すると，
  // 列車停止時の電流リミッタのみが利用される。
  // -----
  double _max_accelerating_current_low_speed ;
  double _max_regenerating_current_low_speed ;
  double _lowest_velocity_threshold ;
  double _low_velocity_threshold ;
  double _max_accelerating_current ;
  double _max_regenerating_current ;
  double _max_charge_current ;
  double _max_charge_soc_low_threshold ;
  double _max_charge_soc_high_threshold ;
  double _max_discharge_current ;
  double _max_discharge_soc_low_threshold ;
  double _max_discharge_soc_high_threshold ;

  // -----
  // Voltage parameters in the V-I characteristics of the system.
  // 装置のV-I特性の電圧パラメータ群。
  // -----
  SOCDependent * _g_ess_voltage_lowest ;
  SOCDependent * _g_ess_voltage_low_limiter ;
  SOCDependent * _g_ess_voltage_discharge_th_low ;
  SOCDependent * _g_ess_voltage_discharge_th_high ;
  SOCDependent * _g_ess_voltage_charge_th_low ;
  SOCDependent * _g_ess_voltage_charge_th_high ;
  SOCDependent * _g_ess_voltage_high_limiter ;
  SOCDependent * _g_ess_voltage_maximum ;
  double _voltage_lowest ;
  double _voltage_low_limiter ;
  double _voltage_discharge_th_low ;
  double _voltage_discharge_th_high ;
  double _voltage_charge_th_low ;
  double _voltage_charge_th_high ;
  double _voltage_high_limiter ;
  double _voltage_maximum ;

  // -----
  // Current parameters in the V-I characteristics of the system.
  // 装置のV-I特性の電流パラメータ群。
  // -----
  SOCDependent * _g_ess_current_discharge ;
  SOCDependent * _g_ess_current_floating ;
  SOCDependent * _g_ess_current_charge ;
  double _current_discharge ;
  double _current_floating ;
  double _current_charge ;

  // -----
  // Voltage, current, dv/dth and di/dth.
  // 電圧，電流，dv/dθ および di/dθ.
  // -----
  double _v ;
  double _i ;
  double _dv_dth ;
  double _di_dth ;

  // Prohibiting use of default constructor.
  explicit OBESS_Voltage_Controlled () ;

private :

  // Processing the maximum charge/discharge limit imposed by the ESD.
  // This will supersede the I-V characteristics given by the reference
  // SOC curve and other characteristic parameters.
  void processESDMaximumLimits () ;

  // Getting the ESD voltage and current using Newton-Raphson method.
  void getESDVoltageAndCurrent
  ( double , double , double & , double & ) const ;

  // "mutable" variables for getESDVoltageAndCurrent ()
  mutable double _mc_v_in ;
  mutable double _mc_i_in ;
  mutable double _mc_vi ;
  mutable double _mc_idev ;

public :

  // Constructors
  OBESS_Voltage_Controlled ( ESD_Initialiser const & ) ;
  OBESS_Voltage_Controlled ( OBESS_Voltage_Controlled const & ) ;

  // (virtual) destructor
  ~OBESS_Voltage_Controlled () ;

  // (virtual) function cloning itself
  OBESS_Voltage_Controlled * getMyClone ()
  { return new OBESS_Voltage_Controlled ( * this ) ; }

  // (virtual) operator=.
  OBESS_Voltage_Controlled & operator= ( ESS_OnBoard const & ) ;

  // (virtual) function writing out to a CSV file
  void writeToCSV ( ostream & , bool ) const ;
  void writeHeaderToCSV ( ostream & , bool , string const & ) const ;

  // (virtual) function calculating current and di from voltage, etc. of
  // the converter of the substation.
  void calculateVoltagesAndCurrents ( train_ParamFunc * x ) ;

  // (virtual) function to calculate ESD voltage and current
  void calculateESDVoltageAndCurrent ( train_ParamFunc * x ) ;

  // (virtual) function to renew the states
  void renewElectricalStates ( train_ParamFunc * x ) ;

  // -----
  // (Virtual) function for regeneration limiter processing.
  // -----
  void processRegenerationLimiter ( train_ParamFunc * x ) ;

  // -----
  // (Virtual) functions for interfacing. SOC is to be returned in
  // "per cent" (%).
  // -----
  double getCurrent () const { return _i ; }
  double getDeltaI () const { return _di_dth ; }
  double getSOC () const { return _esd -> getDevSOC () ; }
  double getEnergyCapacity () const { return _esd -> getEnergyCapacity () ; }
  void setStartSOC () { _esd -> setStartSOC () ; }
  void printSOCStoredResults
  ( ostream & x , ostringstream & y , ostringstream & z ) const
  { _esd -> printSOCStoredResults ( x , y , z ) ; }

  // -----
  // (Non-virtual) functions calculating maximum charge / discharge current.
  // -----
  double getMaximumChargeCurrent () const ;	// Non-positive
  double getMaximumDischargeCurrent () const ;	// Non-negative
} ;




// -----
// Creator of class OBESS_Voltage_Controlled.
// OBESS_Voltage_Controlled の Creator.
// -----
class OBESS_Voltage_Controlled_Creator
  : public OBESS_Expander :: ObjectCreator
{
public :
  OBESS_Voltage_Controlled_Creator ()
  { add_to_creators_list ( "voltage_controlled" ) ; }
  OBESS_Voltage_Controlled_Creator ( char const * x )
    : OBESS_Expander :: ObjectCreator () { add_to_creators_list ( x ) ; }
  OBESS_Voltage_Controlled * create () const
  {
    cerr << "Error: OBESS_Voltage_Controlled... default constructor prohibited"
         << endl ;
    exit ( 1 ) ;
  }
  OBESS_Voltage_Controlled * create ( ESS_Initialiser const & x ) const
  { return new OBESS_Voltage_Controlled ( x ) ; }
} ;



#endif	// OBESS_Voltage_Controlled_HH
