// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// EnergyStorage.hh
//  --- declaration of class EnergyStorageDev and related classes
// -----
// ChangeLog:
// 2007. 12. 5
//  File created.
// -----


#ifndef EnergyStorage_HH
#define EnergyStorage_HH

#include <cstdlib>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <utility>
#include "tinyxml.h"
#include "Expandable.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 ;



// -----
// A struct containing two double variables to express a "Thevenin's
// equivalent circuit.
// テブナン等価回路を表現する構造体.
// -----
struct TheveninElements
{
  double _vs ;	// Voltage source
  double _ri ;	// Series impedance
} ;



// -----
// Typedef of the initialiser of the energy storage device / system model.
// エネルギー蓄積素子/装置モデルの初期化クラスの typedef.
// -----
typedef TiXmlNode const * ESD_Initialiser ;
typedef TiXmlNode const * ESS_Initialiser ;



// -----
// Abstract class expressing the electric energy storage device.
// NOTE::: Charge current is NEGATIVE.
// エネルギー蓄積素子を模擬する抽象クラス.
// 注意★★★充電電流は負となる。
// -----
class EnergyStorageDevice
{
public :

  // Virtual destructor
  virtual ~EnergyStorageDevice () {}

  // Get a clone.
  virtual EnergyStorageDevice * getMyClone () const = 0 ;

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

  // Virtual function to get the Thevenin equivalent circuit parameters
  virtual TheveninElements getTheveninElements ( double ) const = 0 ;

  // Virtual function to calculate ESD voltage and current.
  virtual void calculateESDVoltageAndCurrent ( double ) = 0 ;

  // Virtual function to renew SOC and other state variables.
  virtual void renewElectricalStates ( double ) = 0 ;

  // -----
  // Virtual functions for finding maximum charge / discharge power.
  // Assumption: these values will be determined solely by the internal
  //  state of the device, i.e. SOC. Hence no input argument.
  // Returns: power in [W]. Both functions return positive value.
  //  The two arguments are also used to return values --- voltage [V] and
  //  current [A] of the device at which the maximum power is achieved.
  //  Current is negative when charging.
  // -----
  virtual double getMaximumChargePower ( double & , double & ) const = 0 ;
  virtual double getMaximumDischargePower ( double & , double & ) const = 0 ;

  // -----
  // Virtual functions for interfacing. Argument is the current. SOC is to be
  // returned in "per cent" (%). Voltage, current and energy will be returned
  // in [V], [A] and [J], respectively.
  // -----
  virtual double getDevVoltage ( double = 0 ) const = 0 ;
  virtual double getDevCurrent ( double = 0 ) const = 0 ;
  virtual double getDevSOC () const = 0 ;
  virtual double getMinimumVoltage () const = 0 ;
  virtual double getMaximumVoltage () const = 0 ;
  virtual double getEnergyCapacity () const = 0 ;
  virtual void setStartSOC () = 0 ;
  virtual void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const = 0 ;
} ;



// -----
// Typedef of the energy storage device model "expander".
// エネルギー蓄積装置モデルの "Expander" の typedef.
// -----
typedef Expandable < EnergyStorageDevice , ESD_Initialiser > ESD_Expander ;



// -----
// A simple EDLC model.
// EDLC の簡易モデル.
// -----
class SimpleEDLCModel
  : public EnergyStorageDevice ,
    public ESD_Expander
{

private :

  double _c ;		// Capacitance [F].
  double _ri ;		// Internal resistance [ohm].
  double _sdr ;		// Self-discharge resistance [ohm].
  double _vmin ;	// Minimum operating voltage [V].
  double _vmax ;	// Maximum operating voltage [V].
  double _icm ;		// Maximum charge current [A]. Must be positive.
  double _idm ;		// Maximum discharge current [A]. Must be positive.

  double _storeable ;	// Maximum storeable energy in [J].

  double _vmax_sq_minus_vmin_sq ;
  double _vmin_sq ;

  double _vcur ;	// Current voltage --- expresses the state of charge.

  // -----
  // SOC recording variables. _soc_init records the SOC value at the start
  // of the simulation cycle(s). _soc_max and _soc_min record the maximum
  // and minimum SOC values during the simulation cycle(s).
  // -----
  double _soc_init ;
  double _soc_max ;
  double _soc_min ;

  // -----
  // Maximum power cache.
  // -----
  mutable double _max_power_c ;
  mutable double _max_power_c_at_v ;
  mutable double _max_power_c_at_i ;
  mutable double _max_power_c_vcur ;
  mutable double _max_power_d ;
  mutable double _max_power_d_at_v ;
  mutable double _max_power_d_at_i ;
  mutable double _max_power_d_vcur ;

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

public :

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

  // (Virtual) destructor.
  ~SimpleEDLCModel () {}

  // Get a clone.
  SimpleEDLCModel * getMyClone () const
  { return new SimpleEDLCModel ( * this ) ; }

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

  // (Virtual) function to get the Thevenin equivalent circuit parameters
  TheveninElements getTheveninElements ( double ) const ;

  // (Virtual) function to calculate ESD voltage and current
  void calculateESDVoltageAndCurrent ( double x ) {}

  // (Virtual) function to renew SOC and other state variables.
  void renewElectricalStates ( double ) ;

  // -----
  // (Virtual) functions for finding maximum charge / discharge power.
  // -----
  double getMaximumChargePower ( double & , double & ) const ;
  double getMaximumDischargePower ( double & , double & ) const ;

  // -----
  // (Virtual) functions for interfacing. Argument is the current. SOC is to
  // be returned in "per cent" (%). Voltage, current and energy will be
  // returned in [V], [A] and [J], respectively.
  // -----
  double getDevVoltage ( double = 0 ) const ;
  double getDevCurrent ( double = 0 ) const ;
  double getDevSOC () const ;
  double getMinimumVoltage () const { return _vmin ; }
  double getMaximumVoltage () const { return _vmax ; }
  double getEnergyCapacity () const { return _storeable ; }
  void setStartSOC () { _soc_init = _soc_max = _soc_min = getDevSOC () ; }
  void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const ;

} ;




// -----
// Creator of class SimpleEDLCModel.
// SimpleEDLCModel の Creator.
// -----
class SimpleEDLCModelCreator
  : public ESD_Expander :: ObjectCreator
{
public :
  SimpleEDLCModelCreator () { add_to_creators_list ( "simple_edlc" ) ; }
  SimpleEDLCModelCreator ( char const * x )
    : ESD_Expander :: ObjectCreator () { add_to_creators_list ( x ) ; }
  SimpleEDLCModel * create () const
  {
    cerr << "Error: SimpleEDLCModel... default constructor prohibited"
         << endl ;
    exit ( 1 ) ;
  }
  SimpleEDLCModel * create ( ESD_Initialiser const & x ) const
  { return new SimpleEDLCModel ( x ) ; }
} ;




// -----
// Data initialised by the tag "soc_dependent".
// "soc_dependent" タグから初期化されるデータ。
// -----
struct SOCDependentNode
{
  // -----
  // The data for the node.
  // このノードのデータ.
  // -----
  double _data ;

  // -----
  // The SOC for the node.
  // このノードのSOC.
  // -----
  double _soc ;

  // -----
  // True if the tag marks this node as "independent" of the SOC.
  // タグにおいて，このノードが SOC と独立とマークされていれば true.
  // -----
  bool _indep ;

  SOCDependentNode () : _data ( 0 ) , _soc ( 0 ) , _indep ( false ) {}
  SOCDependentNode ( TiXmlNode const * ) ;
  SOCDependentNode ( double _d_ , double _s_ , bool _idp_in )
    : _data ( _d_ ) , _soc ( _s_ ) , _indep ( _idp_in ) {}

  SOCDependentNode ( SOCDependentNode const & x )
    : _data ( x . _data ) , _soc ( x . _soc ) , _indep ( x . _indep ) {}

  SOCDependentNode & operator= ( SOCDependentNode const & x )
  { if ( & x == this ) return * this ; _data = x . _data ; _soc = x . _soc ;
  _indep = x . _indep ; return * this ; }
} ;



// -----
// An object containing one or more SOCDependent object instances.
// SOCDependent オブジェクトのインスタンスを1〜複数個保有するオブジェクト.
// -----
class SOCDependent
{
private :

  vector < SOCDependentNode * > _dt ;

  mutable vector < SOCDependentNode * > :: size_type _pcur ;

  explicit SOCDependent () ;

public :

  SOCDependent ( TiXmlNode const * ) ;
  SOCDependent ( SOCDependent const & ) ;
  ~SOCDependent () ;

  SOCDependent * getMyClone () const { return new SOCDependent ( * this ) ; }
  

  double getData ( double ) const ;
} ;



// -----
// A simple battery model.
// 2次電池の簡易モデル.
// -----
class SimpleBatteryModel
  : public EnergyStorageDevice ,
    public ESD_Expander
{

private :

  double _storeable ;	// Maximum storeable energy in [J].
  double _vmin ;	// Minimum operating voltage [V].
  double _vmax ;	// Maximum operating voltage [V].
  double _icm ;		// Maximum charge current [A]. Must be positive.
  double _idm ;		// Maximum discharge current [A]. Must be positive.
  int _n_series ;	// Number of series connected cells
  int _n_parallel ;	// Number of parallel connected cells

  double _soc ;		// The state of charge (In percent!!!)

  // -----
  // SOC dependent terminal voltage data.
  // -----
  vector < pair < double , SOCDependent * > > _tv ;

  // -----
  // SOC recording variables. _soc_init records the SOC value at the start
  // of the simulation cycle(s). _soc_max and _soc_min record the maximum
  // and minimum SOC values during the simulation cycle(s).
  // -----
  double _soc_init ;
  double _soc_max ;
  double _soc_min ;

  // -----
  // Maximum power cache.
  // -----
  mutable double _max_power_c ;
  mutable double _max_power_c_at_v ;
  mutable double _max_power_c_at_i ;
  mutable double _max_power_c_soc ;
  mutable double _max_power_d ;
  mutable double _max_power_d_at_v ;
  mutable double _max_power_d_at_i ;
  mutable double _max_power_d_soc ;

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

public :

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

  // (Virtual) destructor.
  ~SimpleBatteryModel () {}

  // Get a clone.
  SimpleBatteryModel * getMyClone () const
  { return new SimpleBatteryModel ( * this ) ; }

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

  // (Virtual) function to get the Thevenin equivalent circuit parameters
  TheveninElements getTheveninElements ( double ) const ;

  // (Virtual) function to calculate ESD voltage and current.
  void calculateESDVoltageAndCurrent ( double x ) {}

  // (Virtual) function to renew SOC and other state variables.
  void renewElectricalStates ( double ) ;

  // -----
  // (Virtual) functions for finding maximum charge / discharge power.
  // -----
  double getMaximumChargePower ( double & , double & ) const ;
  double getMaximumDischargePower ( double & , double & ) const ;

  // -----
  // (Virtual) functions for interfacing. Argument is the current. SOC is to
  // be returned in "per cent" (%). Voltage, current and energy will be
  // returned in [V], [A] and [J], respectively.
  // -----
  double getDevVoltage ( double = 0 ) const ;
  double getDevCurrent ( double = 0 ) const ;
  double getDevSOC () const { return _soc ; }

  double getMinimumVoltage () const
  { return _vmin * static_cast < double > ( _n_series ) ; }
  double getMaximumVoltage () const
  { return _vmax * static_cast < double > ( _n_series ) ; }
  double getEnergyCapacity () const
  { return _storeable * static_cast < double > ( _n_parallel )
      * static_cast < double > ( _n_series ) ; }

  void setStartSOC () { _soc_init = _soc_max = _soc_min = getDevSOC () ; }
  void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const ;

} ;




// -----
// Creator of class SimpleBatteryModel.
// SimpleBatteryModel の Creator.
// -----
class SimpleBatteryModelCreator
  : public ESD_Expander :: ObjectCreator
{
public :
  SimpleBatteryModelCreator () { add_to_creators_list ( "simple_battery" ) ; }
  SimpleBatteryModelCreator ( char const * x )
    : ESD_Expander :: ObjectCreator () { add_to_creators_list ( x ) ; }
  SimpleBatteryModel * create () const
  {
    cerr << "Error: SimpleBatteryModel... default constructor prohibited"
         << endl ;
    exit ( 1 ) ;
  }
  SimpleBatteryModel * create ( ESD_Initialiser const & x ) const
  { return new SimpleBatteryModel ( x ) ; }
} ;




// -----
// Typedef of the initialiser of the DC-DC converter submodel.
// DC-DC コンバータサブモデルの初期化クラスの typedef.
// -----
typedef TiXmlNode const * DC_DC_Initialiser ;



// -----
// Abstract class expressing the DC-DC converter losses.
// DC-DC コンバータの損失モデルの抽象クラス.
// -----
class DC_DC_Converter_Losses
{
public :

  // Virtual destructor
  virtual ~DC_DC_Converter_Losses () {}

  // Get a clone.
  virtual DC_DC_Converter_Losses * getMyClone () const = 0 ;

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

  // Virtual function to get the losses in [W].
  // Arguments: Power [W], Line Voltage [V], Device Voltage [V], Switch.
  // Power is positive when discharging. If Switch is true then the power
  // is assumed to be the input power (power at the main circuit = pantograph
  // side); if false then it is assumed to be the output power (power at the
  // ESD side).
  virtual double getLosses
  ( double , double , double , bool = true ) const = 0 ;

  // Virtual function to calculate ESD voltage and current.
  virtual void calculateESDVoltageAndCurrent ( double , double ) = 0 ;

  // Virtual function to renew SOC and other state variables.
  virtual void renewElectricalStates ( double , double ) = 0 ;
} ;



// -----
// Typedef of the energy storage device model "expander".
// エネルギー蓄積装置モデルの "Expander" の typedef.
// -----
typedef Expandable < DC_DC_Converter_Losses , DC_DC_Initialiser >
DC_DC_Expander ;



// -----
// A simple DC-DC converter losses model.
//  L = | P * K1 |
//  L: losses [W], K1: percentage of losses, P: power inflow [W].
//  Since P is "inflow power", it means power input from the main circuit
//  side when charging, while it means power input from the ESD side when
//  discharging.
// DC-DC コンバータの簡易損失モデル.
//  L = | P * K1 |
//  L: 損失 [W], K1: 損失割合, P: 流入電力 [W].
//  P は「流入電力」を表すので，充電時は主回路側からの入力電力を表す一方，
//  放電時はESDからの入力電力を表す。
// -----
class Fixed_Percentage_Losses_Model
  : public DC_DC_Converter_Losses ,
    public DC_DC_Expander
{

private :

  double _percentage_c ;	// K1 (Loss percentage) when charging
  double _percentage_d ;	// K1 (Loss percentage) when discharging
  double _device_current ;	// Current through the storage device
  double _device_voltage ;	// Terminal voltage of the storage device

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

public :

  // Constructors
  Fixed_Percentage_Losses_Model ( DC_DC_Initialiser const & ) ;
  Fixed_Percentage_Losses_Model ( Fixed_Percentage_Losses_Model const & ) ;

  // (Virtual) destructor.
  ~Fixed_Percentage_Losses_Model () {}

  // Get a clone.
  Fixed_Percentage_Losses_Model * getMyClone () const
  { return new Fixed_Percentage_Losses_Model ( * this ) ; }

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

  // (Virtual) function to get the losses
  // Arguments: Power [W], Line Voltage [V], Device Voltage [V], Switch.
  double getLosses ( double , double , double , bool = true ) const ;

  // (Virtual) function to calculate ESD voltage and current.
  void calculateESDVoltageAndCurrent ( double , double ) ;

  // (Virtual) function to renew SOC and other state variables.
  void renewElectricalStates ( double , double ) ;
} ;




// -----
// Creator of class Fixed_Percentage_Losses_Model.
// Fixed_Percentage_Losses_Model の Creator.
// -----
class Fixed_Percentage_Losses_ModelCreator
  : public DC_DC_Expander :: ObjectCreator
{
public :
  Fixed_Percentage_Losses_ModelCreator ()
  { add_to_creators_list ( "fixed_percentage" ) ; }
  Fixed_Percentage_Losses_ModelCreator ( char const * x )
    : DC_DC_Expander :: ObjectCreator () { add_to_creators_list ( x ) ; }
  Fixed_Percentage_Losses_Model * create () const
  {
    cerr << "Error: Fixed_Percentage_Losses_Model... "
         << "default constructor prohibited" << endl ;
    exit ( 1 ) ;
  }
  Fixed_Percentage_Losses_Model * create ( ESD_Initialiser const & x ) const
  { return new Fixed_Percentage_Losses_Model ( x ) ; }
} ;




// -----
// Abstract class expressing the electric energy storage system at the
// substation.
// 変電所におけるエネルギー蓄積装置を模擬する抽象クラス.
// -----
class ESS_Substation
{
public :

  // Virtual destructor
  virtual ~ESS_Substation () {}

  // Get a clone.
  virtual ESS_Substation * getMyClone () const = 0 ;

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

  // Virtual function calculating current and di from voltage, etc. of
  // the converter of the substation.
  // Arguments: voltage, current, dv / dth, di / dth.
  virtual void calculateVoltagesAndCurrents
  ( double , double , double , double ) = 0 ;

  // Virtual function to calculate ESD voltage and current.
  // Arguments: voltage, current.
  virtual void calculateESDVoltageAndCurrent ( double , double ) = 0 ;

  // Virtual function to renew the states.
  // Arguments: voltage, current.
  virtual void renewElectricalStates ( double , double ) = 0 ;

  // -----
  // Virtual functions for interfacing. SOC is to be returned in
  // "per cent" (%). Voltage, current and energy will be returned in
  // [V], [A] and [J], respectively.
  // -----
  virtual double getCurrent () const = 0 ;
  virtual double getDeltaI () const = 0 ;
  virtual double getSOC () const = 0 ;
  virtual double getEnergyCapacity () const = 0 ;
  virtual void setStartSOC () = 0 ;
  virtual void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const = 0 ;
} ;





// -----
// Default substation energy storage system class expressing "there is NO
// energy storage system at the substation".
// 「当該変電所にはエネルギー蓄積装置は存在しない」ことを表す，デフォルトの
// 地上設置エネルギー蓄積装置クラス。
// -----
class No_ESS_Substation
  : public ESS_Substation
{
public :

  // (virtual) destructor
  ~No_ESS_Substation () {}

  // (virtual) function cloning itself
  No_ESS_Substation * getMyClone () const { return new No_ESS_Substation ; }

  // (virtual) function writing out to a CSV file. Actually does nothing.
  void writeToCSV ( ostream & x , bool b ) const {}
  void writeHeaderToCSV ( ostream & x , bool b , string const & s ) const {}

  // (virtual) function calculating current and di from voltage, etc. of
  // the converter of the substation.
  void calculateVoltagesAndCurrents
  ( double x , double y , double z , double w ) {}

  // (virtual) function to calculate ESD voltage and current.
  void calculateESDVoltageAndCurrent ( double x , double y ) {}

  // (virtual) function to renew the states.
  void renewElectricalStates ( double x , double y ) {}

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

} ;




// -----
// Typedef of the energy storage system model "expander".
// エネルギー蓄積素子モデルの "Expander" の typedef.
// -----
typedef Expandable < ESS_Substation , ESS_Initialiser > ESS_Expander ;



// -----
// Generic energy storage system class.
// 汎用エネルギー蓄積装置クラス。
// -----
class Generic_ESS_Substation
  : public ESS_Substation ,
    public ESS_Expander
{
private :

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

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

  // -----
  // 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 Generic_ESS_Substation () ;

private :

  // Processing the maximum charge/discharge limit imposed by the ESD.
  // This will supersede the I-V characteristics given by the
  // _g_ess_voltage_* and _g_ess_current_* variables.
  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
  Generic_ESS_Substation ( ESD_Initialiser const & ) ;
  Generic_ESS_Substation ( Generic_ESS_Substation const & ) ;

  // (virtual) destructor
  ~Generic_ESS_Substation () ;

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

  // (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
  ( double , double , double , double ) ;

  // (virtual) function to calculate ESD voltage and current
  void calculateESDVoltageAndCurrent ( double , double ) ;

  // (virtual) function to renew the states
  void renewElectricalStates ( double , double ) ;

  // -----
  // (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 ) ; }
} ;




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




// -----
// Abstract class expressing the electric energy storage system on trains.
// 車載エネルギー蓄積装置を模擬する抽象クラス.
// -----

class train_ParamFunc ;

class ESS_OnBoard
{

public :

  // Virtual destructor
  virtual ~ESS_OnBoard () {}

  // Get a clone.
  virtual ESS_OnBoard * getMyClone () = 0 ;

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

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

  // Virtual function calculating current and di from the conditions of the
  // train itself.
  virtual void calculateVoltagesAndCurrents ( train_ParamFunc * ) = 0 ;

  // Virtual function to calculate ESD voltage and current.
  virtual void calculateESDVoltageAndCurrent ( train_ParamFunc * ) = 0 ;

  // Virtual function to renew the states.
  virtual void renewElectricalStates ( train_ParamFunc * ) = 0 ;

  // -----
  // Virtual functions for interfacing. SOC is to be returned in
  // "per cent" (%).
  // -----
  virtual double getCurrent () const = 0 ;
  virtual double getDeltaI () const = 0 ;
  virtual double getSOC () const = 0 ;
  virtual void setStartSOC () = 0 ;
  virtual void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const = 0 ;

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

} ;





// -----
// Default on-board energy storage system class expressing "there is NO
// energy storage system on this train".
// 「エネルギー蓄積装置は存在しない」ことを表す，デフォルトの車載エネルギー
// 蓄積装置クラス。
// -----
class No_ESS_OnBoard
  : public ESS_OnBoard
{
public :

  // (virtual) destructor
  ~No_ESS_OnBoard () {}

  // Constructor.
  No_ESS_OnBoard () {}

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

  // (virtual) operator=. Actually does nothing...
  No_ESS_OnBoard & operator= ( ESS_OnBoard const & x )
  { return * this ; }

  // (virtual) function writing out to a CSV file. Actually does nothing.
  void writeToCSV ( ostream & x , bool b ) const {}
  void writeHeaderToCSV ( ostream & x , bool b , string const & s ) const {}

  // (virtual) function calculating current and di from the conditions of the
  // train itself.
  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 0 ; }
  double getDeltaI () const { return 0 ; }
  double getSOC () const { return 0 ; }
  double getEnergyCapacity () const { return 0 ; }
  void setStartSOC () {}
  void printSOCStoredResults
  ( ostream & , ostringstream & , ostringstream & ) const {}
  
} ;


// -----
// Typedef of the energy storage system model "expander".
// エネルギー蓄積素子モデルの "Expander" の typedef.
// -----
typedef Expandable < ESS_OnBoard , ESS_Initialiser > OBESS_Expander ;



// -----
// Generic on-board energy storage system class. Uses Ref_SOC_Curve class to
// hold the "reference SOC curves".
// 汎用車載エネルギー蓄積装置クラス。
// -----
class OBESS_RefSOC_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.
  // 装置の特性パラメータ群。
  // -----
  double _follower_max_discharge_current ;
  double _follower_max_discharge_current_low_speed ;
  double _follower_delta_soc_max_discharge_threshold ;
  double _follower_delta_soc_discharge_threshold ;
  double _follower_max_charge_current ;
  double _follower_max_charge_current_low_speed ;
  double _follower_delta_soc_max_charge_threshold ;
  double _follower_delta_soc_charge_threshold ;
  double _follower_lowest_velocity_threshold ;
  double _follower_low_velocity_threshold ;
  double _follower_delta_soc_lowest_nofollow_threshold ;
  double _follower_delta_soc_low_nofollow_threshold ;
  double _follower_delta_soc_high_nofollow_threshold ;
  double _follower_delta_soc_highest_nofollow_threshold ;
  double _max_accelerating_current ;
  double _max_regenerating_current ;
  double _max_discharge_current ;
  double _max_discharge_soc_low_threshold ;
  double _max_discharge_soc_high_threshold ;
  double _max_charge_current ;
  double _max_charge_soc_low_threshold ;
  double _max_charge_soc_high_threshold ;

  // -----
  // 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_RefSOC_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_RefSOC_Controlled ( ESD_Initialiser const & ) ;
  OBESS_RefSOC_Controlled ( OBESS_RefSOC_Controlled const & ) ;

  // (virtual) destructor
  ~OBESS_RefSOC_Controlled () ;

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

  // (virtual) operator=.
  OBESS_RefSOC_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_RefSOC_Controlled.
// OBESS_RefSOC_Controlled の Creator.
// -----
class OBESS_RefSOC_Controlled_Creator
  : public OBESS_Expander :: ObjectCreator
{
public :
  OBESS_RefSOC_Controlled_Creator ()
  { add_to_creators_list ( "refsoc_controlled" ) ; }
  OBESS_RefSOC_Controlled_Creator ( char const * x )
    : OBESS_Expander :: ObjectCreator () { add_to_creators_list ( x ) ; }
  OBESS_RefSOC_Controlled * create () const
  {
    cerr << "Error: OBESS_RefSOC_Controlled... default constructor prohibited"
         << endl ;
    exit ( 1 ) ;
  }
  OBESS_RefSOC_Controlled * create ( ESS_Initialiser const & x ) const
  { return new OBESS_RefSOC_Controlled ( x ) ; }
} ;



#endif	// EnergyStorage_HH
