

// Refer to  "Roberts_BDFM_dissertation_2005-(Modified).pdf".
//
// We are modeling a single stator induction motor here. We will lump the mutual inductances of the stator and rotor into simple representations of windings
// without regard to physical layout.
//
// The machine will be reduced to:
//
//     p1 = 1, p2 = 0   (This is a 2 pole machine traditional induction motor)
//     S = 2  (With a single set of windings, the meaning of S has changed. However in Robert's, S = p1 + p2 = 2 + 4 = 6. Six circuits defined the requirement
//             that for a 4/8 pole BDFM, there must always be a point in rotation that any two of the six rotor bars line up with the "pitch" of a 4 pole or
//             8 pole stator. With this in mind, we define S = 2.
//
//     This reduces the mutual inductance matrix to the following (from Eq 2.30 and Eq. 2.56)
//
//
//      | Ms     Msr |
//      | Msr_T  Mr  |
//
//      where Ms is a 3 x 3 matrix, Ms is a 2 x 2 matrix, Msr is a 3 x 2 matrix and Msr_T is a 2 x 3 matrix.
//
//
//      We will use the top left block of Equation B.9 on age 256 for Ms.
//
//				| 210.0e-3    -96.3e-3   -96.3e-3 |
//              | -96.3e-3    210.0e-3   -96.3e-3 |
//              | -96.3e-3    -96.3e-3   210.0e-3 |
//
//      Msr of Equation 2.53 on page 63 reduces to this (for S = 2).
//
//
//              | Sum{M*cos(theta_r 		- B)        Sum{M*cos(theta_r 		  - PI -  B) |
//				| Sum{M*cos(theta_r - 2PI/3 - B)        Sum{M*cos(theta_r - 2PI/3 - PI -  B) |
//				| Sum{M*cos(theta_r - 4PI/3 - B)        Sum{M*cos(theta_r - 4PI/3 - PI -  B) |
//
//
//      For S = 2, Mr will be interperted from the "Rotor 5: 6 bar cage rotor design", Section B.7, Equation B.29
//
//
//      		|  271.0e-7  -271.0e-7 |
//              | -271.0e-7   271.0e-7 |
//
//




typedef enum {
  SRC_FUNC_NULL = -1,
  SRC_FUNC_TriangleWave,
  SRC_FUNC_PwmA,
  SRC_FUNC_PwmB,
  SRC_FUNC_PwmC,

} SRC_FUNCTION;

	// ODE Functions based on Equations 2.56 and 2.59 on page 65 of "Roberts_BDFM_dissertation_2005-(Modified).pdf"
typedef enum {
  ODE_FUNC_NULL = -1,
  ODE_FUNC_Is3_Isr3_1,
  ODE_FUNC_Is3_Isr3_2,
  ODE_FUNC_Is3_Isr3_3,
  ODE_FUNC_Isr6_Ir6_1,
  ODE_FUNC_Isr6_Ir6_2,
  ODE_FUNC_Isr6_Ir6_3,
  ODE_FUNC_Isr6_Ir6_4,
  ODE_FUNC_Isr6_Ir6_5,
  ODE_FUNC_Isr6_Ir6_6,
  ODE_FUNC_Theta,
  ODE_FUNC_Omega
  
} ODE_FUNCTION;

//(NOTE: As of 6/12/08, "pTranslationList" and "pTrajectoryList" CTRL's have been 
//       deprecated and replaced with a "group" structure. However, we still maintain
//       only one "CTRL_FUNCTION" enumeration for all groups)
typedef enum {
  CTRL_FUNC_NULL = -1,
  CTRL_FUNC_RefGen,
  CTRL_FUNC_VDqCmd,


} CTRL_FUNCTION;

typedef enum {
  COEF_FUNC_NULL = -1,
} COEF_FUNCTION;



typedef enum {
  SWITCH_FUNC_NULL = -1,

} SWITCH_FUNCTION;

typedef enum {
  SPICE_FUNC_NULL = -1,

} SPICE_FUNCTION;



#include "Simulation.hpp" 





     // un-comment to plot all probes and object outputs.
//#define RECORD_ALL_PROBES


//Parameters....

// Inductance matrix's calculated from test "Section_2_7_2", "Section_B_2", and "Section_B_7"
#include "../BDFM-Dissertation-2005-Tests/Section_2_7_2/Stator_Rotor_Mutual_Inductance.h"
#include "../BDFM-Dissertation-2005-Tests/Section_2_7_2/Stator_Rotor_Derivative_Mutual_Inductance.h"
#include "../BDFM-Dissertation-2005-Tests/Section_B_2/Stator_Stator_Mutual_Inductance.h"
#include "../BDFM-Dissertation-2005-Tests/Section_B_7/Rotor_Rotor_Mutual_Inductance.h"



#define PI 3.1415926535897932384626433832795

// Form "Roberts..."  Section 2.5.3, Equation 2.31 and Equation 2.32, page 49.
//
//    R = rho * l / A    (length in meters, area in square meters)
//
//    l_stator = 2.0 * 1.1 * N *((_coil_pitch_ * d / 2.0) + w)             //(used to calculate the stator winding resistance. All distances in meters)
//

//
//
//
// From "Section_2_7_2" experiment....
//
//
//	w = .1955 m
//  d = .175065 m
//  N = 10 * 16    //(For stator calculation, actually from Table B.1 page and Table B.3 page 252 of "Roberts..." for 4 pole winding (2 pole pairs))
//
//  A = 1.13 mm**2    //(For stator calculation, also from Table B.3 page 252 of "Roberts..." )
//  _coil_pitch_  =  2.0 * PI * ( d / 2.0) * 10.0 / 48.0  //See "Ack" in "Section_2_7_2.c" for stator coil pitch)
//
//  A = 205.84 mm**2   //(Rotor bar conductor area, see Table B.4, Section B.10 on page 274 of "Roberts...")
//
//
//
//  Interpertation for bar resistance from Section B.7.1, Figure B.8 page 267
//
//	  l_rotor_bar = d (approximate)
//    l_rotor_end = 2.0 * PI * (d / 2.0) / 6.0 (approximate)
//
//
//
//  rho (copper) = 1.68e-8

//
//
//  From Section B.7.1, Figure B.8 page 267 calculate the  the elements of the resistor matrix for "6 bar cage rotor design"
#define Rr_matrix_loop  (2.0 * 1.68e-8 * (0.1955 + (2.0 * PI * (0.175065 / 2.0) / 6.0))  / (205.84 / 1.0e6))
#define Rr_matrix_bar   (- 1.68e-8 * 0.1955 (205.84 / 1.0e6))

double Rr_res[6][6] = {
							{R_matrix_loop,    R_matrix_bar,    0,               0,               0,               R_matrix_bar  },
							{R_matrix_bar,     R_matrix_loop,   R_matrix_bar,    0,               0,               0             },
							{0,                R_matrix_bar,    R_matrix_loop,   R_matrix_bar,    0,               0             },
							{0,                0,               R_matrix_bar,    R_matrix_loop,	  R_matrix_bar,    0             },
							{0,                0,               0,               R_matrix_bar,    R_matrix_loop,   R_matrix_bar  },
							{R_matrix_bar,     0,               0,               0,               R_matrix_bar,    R_matrix_loop }
					  };


#define Rs_matrix_elem  (1.68e-8 *  2.0 * 1.1 * (10 * 16) * ((2.0 * PI * ( .175065 / 2.0) * 10.0 / 48.0)  + 0.1955))

double Rs_res[3][3] = {
							{Rs_matrix_elem,   0,				0				},
							{0,				   Rs_matrix_elem,	0				},
							{0,				   0,				Rs_matrix_elem	}
					  };

// Mechanical Parameters:
//
// 1 Newton = 1 kg * m / sec**2  (eg. F = mass * acceleration)
// T (torque) in units of Newton * meters (N*m)
// J (moment of interia) in units of kg * meter**2  (kg*m**2)
//
// Therefore:
// T / J = (m * kg * m / sec**2) / kg * m**2 = rad / sec**2


#define Ti  50.0  //N*m, can be as high as 143 N*m, see Table B.2, Section B.1, page 250.

#define Jm  .11   //kg * m**2 (Also from Table B.2, Section B.1, page 250.)






// These modulus based on "QUARTER_PWM_CYCLE" time below
#define REF_GEN_QUANTUM_CNT       8
#define VDQ_CMD_QUANTUM_CNT       4
#define PWM_CYCLE_QUANTUM_CNT     4

#define QUANTUM_PERIOD .0000125   




#define QUARTER_PWM_CYCLE QUANTUM_PERIOD
 


   




#define  RT_TRAJ     .2      
#define  CT_TRAJ     .5
#define  VO_TRAJ   100.0








          //uncoment if linear mode....
//#define LINEAR_AMP_MODE 
         
#define PWM_GAIN    5.0
#define PWM_OFFSET  0



	//Unlike the original "App_Observer.hpp" simulation, we are going to
    //keep all the state variables defined in Equation 2.59, page 66 of "Roberts..."
    //global to make debugging easier.
double is[3] = {0};
double ir[6] = {0};
double vs[3] = {0};
double theta_r = 0;
double omega_r = 0;

double pwm_sig[3] = {0};

double TriAngWave = 0;
double V_xo[3] = {0};


	//Global function to interpolate "theta_r" lookup for arrays "Msr[][3][6]" and "d_Msr[]3][6]"
double InterpolateThetaRArray(double (* Msr_or_d_Msr)[360][3][6], unsigned int stator_phase, unsigned rotor_bar)
{
	double base_index;
	double frac_interpotate;
	unsigned int index_plus_one;
	fract_interpolate = modf(theta_r * 360.0 / (2.0 * PI), &base_index);
	index_plus_one = ((unsigned int) index + 1) % 360;

	return(Msr_or_d_Msr[(unsigned int) base_index][stator_phase][rotor_bar](1.0 - fract_interpolate) + fract_interpolate * Msr_or_d_Msr[index_plus_one][stator_phase][rotor_bar]);

}



// **** SrcObject Classes ********************************

// ---- TriangleWave ---------------------------------------

class TriangleWave : public SrcObject
{
public:
  virtual void SrcFunction(double t);
  TriangleWave(void);
  ~TriangleWave(void);
  double t_mod;
  double t_prev;
  double PwmRampDir;
  double PwmFreqScale;



};


TriangleWave Inst_TriangleWave;


// --------------------------------------------------------

// ---- PwmA  ---------------------------------------------

class PwmA : public SrcObject
{
public:
  virtual void SrcFunction(double t);
  PwmA(void);
  ~PwmA(void);
  //source for this ODE
  //(All variables are declared global.)


 
};



PwmA Inst_PwmA;

// -------------------------------------------------------------

// ---- PwmB  ---------------------------------------------

class PwmB : public SrcObject
{
public:
  virtual void SrcFunction(double t);
  PwmB(void);
  ~PwmB(void);
  //source for this ODE
  //(All variables are declared global.)



};



PwmB Inst_PwmB;

// -------------------------------------------------------------

// ---- PwmC  ---------------------------------------------

class PwmC : public SrcObject
{
public:
  virtual void SrcFunction(double t);
  PwmC(void);
  ~PwmC(void);
  //source for this ODE
  //(All variables are declared global.)

 

};



PwmC Inst_PwmC;

// -------------------------------------------------------------


SrcObject * SrcObjectList[] = {(SrcObject *) &Inst_TriangleWave,
			       (SrcObject *) &Inst_PwmA,
			       (SrcObject *) &Inst_PwmB,
			       (SrcObject *) &Inst_PwmC,
			       0};


// ***********************************************************

// **** OdeObject Classes ********************************



// ---- Is3_Isr3_1 -----------------------------------------

class Is3_Isr3_1 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void OdeGroupMSolve(double dydt[],  double dmdt[]);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Is3_Isr3_1(void);
  ~Is3_Isr3_1(void);
  //locals for this ODE
  double d_Msr_ir;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  V_s1;
  vector<double>  Cemf_s1;
  vector<double>  Vr_s1;

};

Is3_Isr3_1 Inst_Is3_Isr3_1;


// --------------------------------------------------------

// ---- Is3_Isr3_2 -----------------------------------------

class Is3_Isr3_2 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void OdeGroupMSolve(double dydt[],  double dmdt[]);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Is3_Isr3_2(void);
  ~Is3_Isr3_2(void);
  //locals for this ODE
  double d_Msr_ir;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  V_s2;
  vector<double>  Cemf_s2;
  vector<double>  Vr_s2;

};

Is3_Isr3_2 Inst_Is3_Isr3_2;


// --------------------------------------------------------


// ---- Is3_Isr3_3 -----------------------------------------

class Is3_Isr3_3 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void OdeGroupMSolve(double dydt[],  double dmdt[]);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Is3_Isr3_3(void);
  ~Is3_Isr3_3(void);
  //locals for this ODE
  double d_Msr_ir;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  V_s3;
  vector<double>  Cemf_s3;
  vector<double>  Vr_s3;

};

Is3_Isr3_3 Inst_Is3_Isr3_3;


// --------------------------------------------------------




// ---- Isr6_Ir6_1 -----------------------------------------

class Isr6_Ir6_1 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void OdeGroupMSolve(double dydt[],  double dmdt[]);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_1(void);
  ~Isr6_Ir6_1(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r1;
  vector<double>  Vr_r1;

};

Isr6_Ir6_1 Inst_Isr6_Ir6_1;


// --------------------------------------------------------

// ---- Isr6_Ir6_2 -----------------------------------------

class Isr6_Ir6_2 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_2(void);
  ~Isr6_Ir6_2(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r2;
  vector<double>  Vr_r2;

};

Isr6_Ir6_2 Inst_Isr6_Ir6_2;

// --------------------------------------------------------

// ---- Isr6_Ir6_3 -----------------------------------------

class Isr6_Ir6_3 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_3(void);
  ~Isr6_Ir6_3(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r3;
  vector<double>  Vr_r3;

};

Isr6_Ir6_3 Inst_Isr6_Ir6_3;

// --------------------------------------------------------

// ---- Isr6_Ir6_4 -----------------------------------------

class Isr6_Ir6_4 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_4(void);
  ~Isr6_Ir6_4(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r4;
  vector<double>  Vr_r4;

};

Isr6_Ir6_4 Inst_Isr6_Ir6_4;

// --------------------------------------------------------

// ---- Isr6_Ir6_5 -----------------------------------------

class Isr6_Ir6_5 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_5(void);
  ~Isr6_Ir6_5(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r5;
  vector<double>  Vr_r5;

};

Isr6_Ir6_5 Inst_Isr6_Ir6_5;

// --------------------------------------------------------

// ---- Isr6_Ir6_6 -----------------------------------------

class Isr6_Ir6_6 : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  Isr6_Ir6_6(void);
  ~Isr6_Ir6_6(void);
  //locals for this ODE
  double d_Msr_t_is;
  //source for this ODE
  //(All variables are declared global.)
  //storage for probes...
  vector<double>  Cemf_r6;
  vector<double>  Vr_r6;

};

Isr6_Ir6_6 Inst_Isr6_Ir6_6;

// --------------------------------------------------------





// ---- Omega ---------------------------------------------

class Omega : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  Omega(void);
  ~Omega(void);
  //locals for this ODE
   double d_Msr_ir[3];
   double is_d_Msr_ir;
  //source for this ODE
  //(All variables are declared global.)


};

Omega Inst_Omega;


// --------------------------------------------------------

// ---- Theta ---------------------------------------------

class Theta : public OdeObject
{
public:
  virtual double OdeFunction(double y, double t);
  Theta(void);
  ~Theta(void);
  //source for this ODE
  //(All variables are declared global.)


};

Theta Inst_Theta;

// --------------------------------------------------------






OdeObject * OdeObjectList[] = {(OdeObject *) &Inst_Is3_Isr3_1, //the next three are in a group and must be maintained in this order.
			       (OdeObject *) &Inst_Is3_Isr3_2,
			       (OdeObject *) &Inst_Is3_Isr3_3,
				   (OdeObject *) &Inst_Isr6_Ir6_1,								    //the next six are in a group and must be maintained in this order.
				   (OdeObject *) &Inst_Isr6_Ir6_2,
				   (OdeObject *) &Inst_Isr6_Ir6_3,
				   (OdeObject *) &Inst_Isr6_Ir6_4,
				   (OdeObject *) &Inst_Isr6_Ir6_5,
				   (OdeObject *) &Inst_Isr6_Ir6_6,
			       (OdeObject *) &Inst_Omega,
			       (OdeObject *) &Inst_Theta,
			       0};


// ***********************************************************



// **** CtrlObject Classes **********************************

	!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! STOP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


// ---- VDqCmd  ---------------------------------------------

class VDqCmd : public CtrlObject
{
public:
  virtual void CtrlFunction(double t);
  virtual void OdeRValueUpdate(void);
  virtual void CtrlRValueUpdate(void);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  VDqCmd(void);
  ~VDqCmd(void);
  void SpaceVectorControl(void);
  //source for this CTRL
  double V_xo[3];
  double theta;
  double omega;    
  double alpha;    
  double vdd;
  double vqd;
     // Commands for magnitude and angle in the rotating D/Q plane. (These
     // commands ultimately come from another CTRL that is not part
     // of this simulation).
  double vcmd_mag;
  double vcmd_ang;
     // This signal is ultimate feed by a SRC or ODE that simulates the DC bus with
     // ripple voltage. For now, it will be set to a constant.
  double v_bus;
     // This table used to construct the reference commands for each phase.
  REFERENCE_CONSTRUCT SVTable[6][3];  
     // Set to FALSE if operation is SVPWM "clamped" mode (minus side).
  bool HighSpeedSVPwm;
  //intermediary varables need for debugging only.
  double V_xo_debug[3];
  double PwmFreqScale;
  //storage for probes..
  vector<double> VCmd_a;  //value of V_xo[0].
  vector<double> VCmd_b;  //value of V_xo[1].
  vector<double> VCmd_c;  //value of V_xo[2].
  vector<double> VCmd_mag; 
  vector<double> VCmd_ang; 
  vector<double> FreqScale;
};



VDqCmd Inst_VDqCmd;

// -------------------------------------------------------------




// ---- RefGen  ---------------------------------------------

class RefGen : public CtrlObject
{

public:
  virtual void CtrlFunction(double t);
  virtual void CtrlRValueUpdate(void);
  virtual void RecordProbes(void);
  virtual void PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[]);
  double sgn(double omegad);
  double impulse(double sgn_omegad);
  RefGen(void);
  ~RefGen(void);
  //source for this CTRL
  double betad;
  double alphad;
  double omegad;
  double thetad;
  double zetad;
  double idd;
  double iqd;
  double didd;
  double diqd;
  double vdd;
  double vqd;
  //storage for probes..
  vector<double> beta_d;
  vector<double> alpha_d;
  vector<double> omega_d;
  vector<double> theta_d;
  vector<double> zeta_d;
  vector<double> id_d;
  vector<double> iq_d;
  vector<double> did_d;
  vector<double> diq_d;
  vector<double> vd_d;
  vector<double> vq_d;  




};








RefGen Inst_RefGen;

// -------------------------------------------------------------





//(NOTE: As of 6/12/08, "pTranslationList" and "pTrajectoryList" CTRL's have been 
//       deprecated and replaced with a "group" structure. However, we still maintain
//       only one "CtrlObjectList[]" array for all groups, but we add a "CtrlObjGroupStatus[]"
//       array to specify the "quantum" value for each CTRL object)

CtrlObject * CtrlObjectList[] = {(CtrlObject *) &Inst_RefGen,
                                 (CtrlObject *) &Inst_VDqCmd,
				 0};
        //This array contains the value of the execution quantium for each CtrlObject listed above
        //The order of this list must be relative to the order of the "CtrlObjectList[]" above.
        //CtrlObjects with the same quantum values may be considered a "group" of CtrlObjects.
        //However, there is no requirement that these CtrlObjects be related to each other.
      
int CtrlObjectQuantum[] = { REF_GEN_QUANTUM_CNT,
                            VDQ_CMD_QUANTUM_CNT,
                          };

// **************************************************************











// **** SrcObject Functions **************************************

// ---- TriangleWave  ----------------------------------------------------

TriangleWave::TriangleWave(void)
{
 

  SrcFuncName = SRC_FUNC_TriangleWave;
  LiteralName = "TriangleWave";


  //build the SRC Rvalue list.
  //(All variables are declared global.)



  PwmRampDir = 1.0;

  PlotThisOutput = TRUE;
  Plot_Tag = "TriangleWave";
}

TriangleWave::~TriangleWave(void)
{



}

void TriangleWave::SrcFunction(double t)
{
  t_mod += (t - t_prev);
  t_prev = t;

  if(t_mod > QUARTER_PWM_CYCLE){
    t_mod -=  QUARTER_PWM_CYCLE;
    PwmRampDir *= -1.0;
  }
 
  TriAngWave = PWM_GAIN*(t_mod/QUARTER_PWM_CYCLE - .5)*PwmRampDir + PWM_OFFSET;

}



// -----------------------------------------------------------------

// ---- PwmA ---------------------------------------------------

PwmA::PwmA(void)
{

  SrcFuncName = SRC_FUNC_PwmA;
  LiteralName = "PwmA";
  
  //build the ODE Rvalue list.
  //(All variables are declared global.)


}

PwmA::~PwmA(void)
{



}

void PwmA::SrcFunction(double t)
{



  //For simulation, "V_xo" is space vector reference to a triangle wave
  //running between 0 and PWM_GAIN.

#ifndef LINEAR_AMP_MODE
	pwm_sig[0] = V_xo[0]  > TriAngWave ? 1.0 : 0;
#endif



}



// -----------------------------------------------------------------


// ---- PwmB ---------------------------------------------------


PwmB::PwmB(void)
{

  SrcFuncName = SRC_FUNC_PwmB;
  LiteralName = "PwmB";
  
  //build the ODE Rvalue list.
  //(All variables are declared global.)


}


PwmB::~PwmB(void)
{


}


void PwmB::SrcFunction(double t)
{



  //For simulation, "V_xo" is space vector reference to a triangle wave
  //running between 0 and PWM_GAIN.

#ifndef LINEAR_AMP_MODE
	pwm_sig[1] = V_xo[1] > TriAngWave ? 1.0 : 0;
#endif





}


// ----------------------------------------------------------------- 


// ---- PwmC ---------------------------------------------------

PwmC::PwmC(void)
{

  SrcFuncName = SRC_FUNC_PwmC;
  LiteralName = "PwmC";
  
  //build the ODE Rvalue list.
  //(All variables are declared global.)


}

PwmC::~PwmC(void)
{


}


void PwmC::SrcFunction(double t)
{



  //For simulation, "V_xo" is space vector reference to a triangle wave
  //running between 0 and PWM_GAIN.

#ifndef LINEAR_AMP_MODE
	pwm_sig[2] = V_xo[2] > TriAngWave ? 1.0 : 0;
#endif




}



// ----------------------------------------------------------------- 





// ***************************************************************


// **** OdeObject Functions **************************************


// ---- Is3_Isr3_1  ----------------------------------------------------

Is3_Isr3_1::Is3_Isr3_1(void)
{

  OdeFuncName = ODE_FUNC_Is3_Isr3_1;
  LiteralName = "Is3_Isr3_1";
  

  //this object marks the beginning of a "group solve" of
  //three objects.
  GroupSolve = 1;
  NumberOfGrpOdes = 3;

  //build the ODE Rvalue list.
  //(All variables are declared global.)

 

  PlotThisOutput = TRUE;
  Plot_Tag = "Is1";
  DoProbes = TRUE;
  
}

Is3_Isr3_1::~Is3_Isr3_1(void)
{

}

double Is3_Isr3_1::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

          //"vs[0] - Rs_res[0][0]*is[0] - omega_r * d_Msr[theta_r][0][0 to 5] x ir[0 to 5]"

#ifdef LINEAR_AMP_MODE
     //generating the voltage command directly through CtrlObject "VDqCmd" 
  vs[0] = pwm_sig[0] + .5*DC_BUS_VOLTAGE;
#else
  vs[0] = ShapeSquareWaveSource(((pwm_sig[0] > 0) ? DC_BUS_VOLTAGE : 0), SRC_SLEW_RATE ,t);
#endif 
  d_Msr_ir = 0;
  for(i = 0; i < 6; i++)
  {
	  d_Msr_ir += InterpolateThetaRArray(d_Msr, 0, i) * ir[i];

  }
  is[0] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(vs[0] - Rs_res[0][0] * is[0] - omega_r * d_Msr_ir);
}


void Is3_Isr3_1::RecordProbes(void)
{
  V_s1.push_back(vs[0]);
#ifdef RECORD_ALL_PROBES
  Cemf_s1.push_back(omega_r * d_Msr_ir);
  Vr_s1.push_back(Rs_res[0][0] * is[0]);
#endif

}




void Is3_Isr3_1::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_s1"){
	SimuPlot.plot_xy(Plot_t, Cemf_s1, "Cemf_s1");
      }
      else if(TagNamesToPlot[i] == "V_s1"){
	SimuPlot.plot_xy(Plot_t, V_s1, "V_s1");
      }
      else if(TagNamesToPlot[i] == "Vr_s1"){
	SimuPlot.plot_xy(Plot_t, Vr_s1, "Vr_s1");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

       

void Is3_Isr3_1::OdeGroupMSolve(double dydt[], double dmdt[])
{
  //Note: This instance is the first of the group. As such, this
  //      is where the "group solve" of the individual 
  //      "dy/dt's" is performed.


}


// -----------------------------------------------------------------


// ---- Is3_Isr3_2  ----------------------------------------------------

Is3_Isr3_2::Is3_Isr3_2(void)
{

  OdeFuncName = ODE_FUNC_Is3_Isr3_2;
  LiteralName = "Is3_Isr3_2";

  //build the ODE Rvalue list.
  //(All variables are declared global.)

 

  PlotThisOutput = TRUE;
  Plot_Tag = "Is2";
  DoProbes = TRUE;
  
}

Is3_Isr3_2::~Is3_Isr3_2(void)
{

}

double Is3_Isr3_2::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

          //"vs[1] - Rs_res[1][1]*is[1] - omega_r * d_Msr[1][0 to 5] x ir[0 to 5]"

#ifdef LINEAR_AMP_MODE
     //generating the voltage command directly through CtrlObject "VDqCmd" 
  vs[1] = pwm_sig[1] + .5*DC_BUS_VOLTAGE;
#else
  vs[1] = ShapeSquareWaveSource(((pwm_sig[1] > 0) ? DC_BUS_VOLTAGE : 0), SRC_SLEW_RATE ,t);
#endif
  d_Msr_ir = 0;
  for(i = 0; i < 6; i++)
  {
	  d_Msr_ir += InterpolateThetaRArray(d_Msr, 1, i) * ir[i];

  }
  is[1] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(vs[1] - Rs_res[1][1] * is[1] - omega_r * d_Msr_ir);
}


void Is3_Isr3_2::RecordProbes(void)
{
  V_s2.push_back(vs[1]);
#ifdef RECORD_ALL_PROBES
  Cemf_s2.push_back(omega_r * d_Msr_ir);
  Vr_s2.push_back(Rs_res[1][1] * is[1]);
#endif

}




void Is3_Isr3_2::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_s2"){
	SimuPlot.plot_xy(Plot_t, Cemf_s2, "Cemf_s2");
      }
      else if(TagNamesToPlot[i] == "V_s2"){
	SimuPlot.plot_xy(Plot_t, V_s2, "V_s2");
      }
      else if(TagNamesToPlot[i] == "Vr_s2"){
	SimuPlot.plot_xy(Plot_t, Vr_s2, "Vr_s2");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}



// -----------------------------------------------------------------


// ---- Is3_Isr3_3  ----------------------------------------------------

Is3_Isr3_3::Is3_Isr3_3(void)
{

  OdeFuncName = ODE_FUNC_Is3_Isr3_3;
  LiteralName = "Is3_Isr3_3";

  //build the ODE Rvalue list.
  //(All variables are declared global.)

 

  PlotThisOutput = TRUE;
  Plot_Tag = "Is3";
  DoProbes = TRUE;
  
}

Is3_Isr3_3::~Is3_Isr3_3(void)
{

}

double Is3_Isr3_3::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

          //"vs[2] - Rs_res[2][2]*is[2] - omega_r * d_Msr[2][0 to 5] x ir[0 to 5]"

#ifdef LINEAR_AMP_MODE
     //generating the voltage command directly through CtrlObject "VDqCmd" 
  vs[2] = pwm_sig[2] + .5*DC_BUS_VOLTAGE;
#else
  vs[2] = ShapeSquareWaveSource(((pwm_sig[2]  > 0) ? DC_BUS_VOLTAGE : 0), SRC_SLEW_RATE ,t);
#endif
  d_Msr_ir = 0;
  for(i = 0; i < 6; i++)
  {
	  d_Msr_ir += InterpolateThetaRArray(d_Msr, 2, i) * ir[i];

  }
  is[2] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(vs[2] - Rs_res[2][2] * is[2] - omega_r * d_Msr_ir);
}


void Is3_Isr3_3::RecordProbes(void)
{
  V_s3.push_back(vs[2]);
#ifdef RECORD_ALL_PROBES
  Cemf_s3.push_back(omega_r * d_Msr_ir);
  Vr_s3.push_back(Rs_res[2][2] * is[2]);
#endif

}




void Is3_Isr3_3::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_s3"){
	SimuPlot.plot_xy(Plot_t, Cemf_s3, "Cemf_s3");
      }
      else if(TagNamesToPlot[i] == "V_s3"){
	SimuPlot.plot_xy(Plot_t, V_s3, "V_s3");
      }
      else if(TagNamesToPlot[i] == "Vr_s3"){
	SimuPlot.plot_xy(Plot_t, Vr_s3, "Vr_s3");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}



// -----------------------------------------------------------------



// ----  Isr6_Ir6_1  ----------------------------------------------------

Isr6_Ir6_1::Isr6_Ir6_1(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_1;
  LiteralName = "Isr6_Ir6_1";


  //this object marks the beginning of a "group solve" of
  //three objects.
  GroupSolve = 1;
  NumberOfGrpOdes = 6;

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir1";
  DoProbes = TRUE;

}

Isr6_Ir6_1::~Isr6_Ir6_1(void)
{

}

double Isr6_Ir6_1::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

          //"0 - Rr_res[0][0]*ir[0]  -  Rr_res[0][1]*ir[1]  -  Rr_res[0][5]*ir[5]  - omega_r * d_Msr[theta_r][0 to 3][0] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 0) * is[i];

  }
  ir[0] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[0][0] * ir[0]  -  Rr_res[0][1]*ir[1]  -  Rr_res[0][5] * ir[5] - omega_r * d_Msr_is);
}


void Isr6_Ir6_1::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r1.push_back(omega_r * d_Msr_is);
  Vr_r1.push_back( Rr_res[0][0] * ir[0]  +  Rr_res[0][1]*ir[1]  + Rr_res[0][5] * ir[5]);
#endif

}




void Isr6_Ir6_1::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r1"){
	SimuPlot.plot_xy(Plot_t, Cemf_r1, "Cemf_r1");
      }
      else if(TagNamesToPlot[i] == "Vr_r1"){
	SimuPlot.plot_xy(Plot_t, Vr_r1, "Vr_r1");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}



void Isr6_Ir6_1::OdeGroupMSolve(double dydt[], double dmdt[])
{
  //Note: This instance is the first of the group. As such, this
  //      is where the "group solve" of the individual
  //      "dy/dt's" is performed.


}


// -----------------------------------------------------------------


// ----  Isr6_Ir6_2  ----------------------------------------------------

Isr6_Ir6_2::Isr6_Ir6_2(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_2;
  LiteralName = "Isr6_Ir6_2";

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir2";
  DoProbes = TRUE;

}

Isr6_Ir6_2::~Isr6_Ir6_2(void)
{

}

double Isr6_Ir6_2::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

  	  	  //"0 - Rr_res[1][0]*ir[0]  -  Rr_res[1][1]*ir[1]  -  Rr_res[1][2]*ir[2]  - omega_r * d_Msr[theta_r][0 to 3][1] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 1) * is[i];

  }
  ir[1] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[1][0]*ir[0]  -  Rr_res[1][1]*ir[1]  -  Rr_res[1][2]*ir[2] - omega_r * d_Msr_is);
}


void Isr6_Ir6_2::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r2.push_back(omega_r * d_Msr_is);
  Vr_r2.push_back( Rr_res[1][0]*ir[0]  +  Rr_res[1][1]*ir[1]  +  Rr_res[1][2]*ir[2]);
#endif

}




void Isr6_Ir6_2::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r2"){
	SimuPlot.plot_xy(Plot_t, Cemf_r2, "Cemf_r2");
      }
      else if(TagNamesToPlot[i] == "Vr_r2"){
	SimuPlot.plot_xy(Plot_t, Vr_r2, "Vr_r2");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

// -----------------------------------------------------------------



// ----  Isr6_Ir6_3  ----------------------------------------------------

Isr6_Ir6_3::Isr6_Ir6_3(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_3;
  LiteralName = "Isr6_Ir6_3";

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir3";
  DoProbes = TRUE;

}

Isr6_Ir6_3::~Isr6_Ir6_3(void)
{

}

double Isr6_Ir6_3::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

  	  	  //"0 - Rr_res[2][1]*ir[1]  -  Rr_res[2][2]*ir[2]  -  Rr_res[2][3]*ir[3]  - omega_r * d_Msr[theta_r][0 to 3][2] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 2) * is[i];

  }
  ir[2] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[2][1]*ir[1]  -  Rr_res[2][2]*ir[2]  -  Rr_res[2][3]*ir[3] - omega_r * d_Msr_is);
}


void Isr6_Ir6_3::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r3.push_back(omega_r * d_Msr_is);
  Vr_r3.push_back( Rr_res[2][1]*ir[1]  +  Rr_res[2][2]*ir[2]  +  Rr_res[2][3]*ir[3]);
#endif

}




void Isr6_Ir6_3::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r3"){
	SimuPlot.plot_xy(Plot_t, Cemf_r3, "Cemf_r3");
      }
      else if(TagNamesToPlot[i] == "Vr_r3"){
	SimuPlot.plot_xy(Plot_t, Vr_r3, "Vr_r3");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

// -----------------------------------------------------------------



// ----  Isr6_Ir6_4  ----------------------------------------------------

Isr6_Ir6_4::Isr6_Ir6_4(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_4;
  LiteralName = "Isr6_Ir6_4";

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir4";
  DoProbes = TRUE;

}

Isr6_Ir6_4::~Isr6_Ir6_4(void)
{

}

double Isr6_Ir6_4::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

  	  	  //"0 - Rr_res[3][2]*ir[2]  -  Rr_res[3][3]*ir[3]  -  Rr_res[3][4]*ir[4]  - omega_r * d_Msr[theta_r][0 to 3][3] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 3) * is[i];

  }
  ir[3] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[3][2]*ir[2]  -  Rr_res[3][3]*ir[3]  -  Rr_res[3][4]*ir[4] - omega_r * d_Msr_is);
}


void Isr6_Ir6_4::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r4.push_back(omega_r * d_Msr_is);
  Vr_r4.push_back( Rr_res[3][2]*ir[2]  +  Rr_res[3][3]*ir[3]  +  Rr_res[3][4]*ir[4]);
#endif

}




void Isr6_Ir6_4::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r4"){
	SimuPlot.plot_xy(Plot_t, Cemf_r4, "Cemf_r4");
      }
      else if(TagNamesToPlot[i] == "Vr_r4"){
	SimuPlot.plot_xy(Plot_t, Vr_r4, "Vr_r4");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

// -----------------------------------------------------------------



// ----  Isr6_Ir6_5  ----------------------------------------------------

Isr6_Ir6_5::Isr6_Ir6_5(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_5;
  LiteralName = "Isr6_Ir6_5";

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir5";
  DoProbes = TRUE;

}

Isr6_Ir6_5::~Isr6_Ir6_5(void)
{

}

double Isr6_Ir6_5::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

  	  	  //"0 - Rr_res[4][3]*ir[3]  -  Rr_res[4][4]*ir[4]  -  Rr_res[4][5]*ir[5]  - omega_r * d_Msr[theta_r][0 to 3][4] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 4) * is[i];

  }
  ir[4] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[4][3]*ir[3]  -  Rr_res[4][4]*ir[4]  -  Rr_res[4][5]*ir[5] - omega_r * d_Msr_is);
}


void Isr6_Ir6_5::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r5.push_back(omega_r * d_Msr_is);
  Vr_r5.push_back( Rr_res[4][3]*ir[3]  +  Rr_res[4][4]*ir[4]  +  Rr_res[4][5]*ir[5]);
#endif

}




void Isr6_Ir6_5::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r5"){
	SimuPlot.plot_xy(Plot_t, Cemf_r5, "Cemf_r5");
      }
      else if(TagNamesToPlot[i] == "Vr_r5"){
	SimuPlot.plot_xy(Plot_t, Vr_r5, "Vr_r5");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

// -----------------------------------------------------------------




// ----  Isr6_Ir6_6  ----------------------------------------------------

Isr6_Ir6_6::Isr6_Ir6_6(void)
{

  OdeFuncName = ODE_FUNC_Isr6_Ir6_6;
  LiteralName = "Isr6_Ir6_6";

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Ir6";
  DoProbes = TRUE;

}

Isr6_Ir6_6::~Isr6_Ir6_6(void)
{

}

double Isr6_Ir6_6::OdeFunction(double y, double t)
{
  int i;
  //Note: This is within a "group" ODE so we are really returning for "dm/dt + v_n"

  	  	  //"0 - Rr_res[5][4]*ir[4]  -  Rr_res[5][5]*ir[5]  -  Rr_res[5][0]*ir[0]  - omega_r * d_Msr[theta_r][0 to 3][5] x is[0 to 3]"


  d_Msr_ir = 0;
  for(i = 0; i < 3; i++)
  {
	  d_Msr_is += InterpolateThetaRArray(d_Msr, i, 5) * is[i];

  }
  ir[5] = y;
  //(Note: "v_n" is really part of the LValue when we are doing the calculations).
  return(0 - Rr_res[5][4]*ir[4]  -  Rr_res[5][5]*ir[5]  -  Rr_res[5][0]*ir[0] - omega_r * d_Msr_is);
}


void Isr6_Ir6_6::RecordProbes(void)
{

#ifdef RECORD_ALL_PROBES
  Cemf_r6.push_back(omega_r * d_Msr_is);
  Vr_r6.push_back( Rr_res[5][4]*ir[4]  +  Rr_res[5][5]*ir[5]  +  Rr_res[5][0]*ir[0]);
#endif

}




void Isr6_Ir6_6::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{
  int i;
  if(TagNamesToPlot[0] == ""){
	  return;
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "Cemf_r6"){
	SimuPlot.plot_xy(Plot_t, Cemf_r6, "Cemf_r6");
      }
      else if(TagNamesToPlot[i] == "Vr_r6"){
	SimuPlot.plot_xy(Plot_t, Vr_r6, "Vr_r6");
      }
      else if(TagNamesToPlot[i] == ""){
	break;
      }
    }

  }
}

// -----------------------------------------------------------------




// ---- Omega  ----------------------------------------------------

Omega::Omega(void)
{

  OdeFuncName = ODE_FUNC_Omega;
  LiteralName = "Omega";     

  //build the ODE Rvalue list.
  //(All variables are declared global.)


  PlotThisOutput = TRUE;
  Plot_Tag = "Omega";

}

Omega::~Omega(void)
{

}

double Omega::OdeFunction(double y, double t)
{
	int i,j;
	//"(is[0 to 3] x d_Msr[theta_r][0 to 3]][0 to 5] x ir[0 to 5] )/ Jm"

	is_d_Msr_ir = 0;
	for(j = 0; j < 3; j++)
	{
		d_Msr_ir[j] = 0;
		for(i = 0; i < 6; i++)
		{
			d_Msr_ir[j] += InterpolateThetaRArray(d_Msr, 0, i) * ir[i];

		}
		is_d_Msr_ir += is[j] * d_Msr_ir[j];
	}

	omega_r =  y;

	return((is_d_Msr_ir - Ti) / Jm);

}


// -----------------------------------------------------------------




// ---- Theta  ----------------------------------------------------

Theta::Theta(void)
{

  OdeFuncName = ODE_FUNC_Theta;
  LiteralName = "Theta";    

  //build the ODE Rvalue list.
  //(All variables are declared global.)



  PlotThisOutput = TRUE;
  Plot_Tag = "Theta";

}

Theta::~Theta(void)
{

}

double Theta::OdeFunction(double y, double t)
{
 
	theta_r = y;

	//omega;
	return(omega_r);

}


// -----------------------------------------------------------------


// ******************************************************************




// ***** CtrlObject Functions ***************************************


// ** (Control of D/Q voltage command) **


// ---- VDqCmd  ---------------------------------------------------

VDqCmd::VDqCmd(void)
{
  SrcObjItem * pCurSrcItem;
  OdeObjItem * pCurOdeItem;

  CtrlFuncName = CTRL_FUNC_VDqCmd;
  LiteralName = "VDqCmd";

  // Refering to Figure 11 of "SpaceVector_PWM_Inverter.pdf", we set  up the reference constructs.
  // The form here is:
  //
  //       SVTable[<sector_index>][<phase>] = <reference construct>
  //
  //                    where
  //                        <sector_index> == SectorNumber - 1
  //
  //                        <phase> == 0 -> "A", 1 -> "B", 2 -> "C"
  //
  //                        <reference construct> == TIME_T1_T2 -> "T1 + T2", TIME_T1 -> "T1", TIME_T2 -> "T2", TIME_NONE -> 0
  //                                                 (for non-clamped SVPWM, add ".5*T0" to all references.
  //

  // Definitions here are for minus side "clamped" SVPWM. For regular SVPWM, add ".5*TO" to all reference values.
  SVTable[0][0] = TIME_T1_T2;
  SVTable[0][1] = TIME_T2;
  SVTable[0][2] = TIME_NONE;
  SVTable[1][0] = TIME_T1;
  SVTable[1][1] = TIME_T1_T2;
  SVTable[1][2] = TIME_NONE;
  SVTable[2][0] = TIME_NONE;
  SVTable[2][1] = TIME_T1_T2;
  SVTable[2][2] = TIME_T2;
  SVTable[3][0] = TIME_NONE;
  SVTable[3][1] = TIME_T1;
  SVTable[3][2] = TIME_T1_T2;
  SVTable[4][0] = TIME_T2;
  SVTable[4][1] = TIME_NONE;
  SVTable[4][2] = TIME_T1_T2;
  SVTable[5][0] = TIME_T1_T2;
  SVTable[5][1] = TIME_NONE;
  SVTable[5][2] = TIME_T1;

  //for now, we run strictly in SVPWM "clamped" mode.
  HighSpeedSVPwm = FALSE;
  //until we can simulate DC bus ripple voltage, we set for a constant value.
  v_bus = DC_BUS_VOLTAGE;

  //build the SRC Rvalue list.

  pSrcObjRValList = new SrcObjItem;
  pCurSrcItem = pSrcObjRValList;

  pCurSrcItem->pSrcObject = SrcObjectList[SRC_FUNC_PwmA];
  pCurSrcItem->pNextSrcItem = new SrcObjItem;
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  pCurSrcItem->pSrcObject = SrcObjectList[SRC_FUNC_PwmB];
  pCurSrcItem->pNextSrcItem = new SrcObjItem;
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  pCurSrcItem->pSrcObject = SrcObjectList[SRC_FUNC_PwmC];
  pCurSrcItem->pNextSrcItem = new SrcObjItem;
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  pCurSrcItem->pSrcObject = SrcObjectList[SRC_FUNC_TriangleWave];


  //build the ODE Rvalue list.

  pOdeObjRValList = new OdeObjItem;
  pCurOdeItem = pOdeObjRValList;

  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_ISample];
  pCurOdeItem->pNextOdeItem = new OdeObjItem;
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_ISample];
  pCurOdeItem->pNextOdeItem = new OdeObjItem;
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_ISample];

#ifdef LINEAR_AMP_MODE
  //we are send the analog voltage commands directly to the "Ia_Ib_Ic_x" OdeObjects's
  pCurOdeItem->pNextOdeItem = new OdeObjItem;
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_Ia_Ib_Ic_1];
  pCurOdeItem->pNextOdeItem = new OdeObjItem;
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_Ia_Ib_Ic_2];
  pCurOdeItem->pNextOdeItem = new OdeObjItem;
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  pCurOdeItem->pOdeObject = OdeObjectList[ODE_FUNC_Ia_Ib_Ic_3];

#endif

  DoProbes = TRUE;

}

VDqCmd::~VDqCmd(void)
{



}



void VDqCmd::CtrlFunction(double t)
{
  int i;

  //(Note: "y" is not used in this CTRL. We use this CTRL to send command
  //       to the "PwmA", "PwmB" and "PwmC" CTRL's directly.


  //For simulation mode, we generate space vector PWM references.

  //#define CONSTANT_VDQ_COMMAND
#ifdef CONSTANT_VDQ_COMMAND

  //For now, we provide constant commands for magnitude and angle.
  //These will come form seperate CTRL later.
  vcmd_mag = 10.0;
  vcmd_ang = PI/2;   //valid values are  +/-PI/2 <= vcmd_ang < +/-PI (pure "q" to pure "d")
#else

  //#define FSF_CTRL_VDQ_COMMAND
#ifdef FSF_CTRL_VDQ_COMMAND

  //"vcmd_mag" and "vcmd_ang" will be generated from signals "vd" and "vq", the command voltages
  //originating form CtrlObject 'FSFCtrl".

#else



  //This is a "Space Vector" command reference test....

  //VDQ command is generated by "RefGen" CtrlObject. This is a test to see
  //"theta", "omega", and "alpha" tracks "thedad", "omegad", and "alphad". Also if "id" and "iq" (generated in
  //"FSFCtrl" tracks "idd" and "idq"

  vcmd_mag = sqrt(vdd*vdd + vqd*vqd);

  if(vqd != 0){

     if(vqd >= 0)
       vcmd_ang = PI/2.0;
     else
       vcmd_ang = - PI/2.0;


     vcmd_ang -= atan(vdd/vqd);

  }
  else{
    vcmd_ang = PI/2.0;
  }


#endif

#endif


  //#define DEBUG_SPACE_VECTOR_CONTROL   //un-comment this to debug function "SpaceVectorControl()"
#ifdef DEBUG_SPACE_VECTOR_CONTROL
  //force feedback position to sweep a number of cycles so
  //that we may view "V_xo[]"
  theta = PI*t*10;   //specify "- PI*t*10" for minus test.
#endif

  //generate the references.
  SpaceVectorControl();

#ifdef DEBUG_SPACE_VECTOR_CONTROL
  for(i = 0; i < 3; i++){
    //transfer over to debug buffers.
    V_xo_debug[i] = V_xo[i];
    //keep the actual commands zero to prevent the simulation from running away.
    V_xo[i] = 0;
  }

#endif






}

void VDqCmd::RecordProbes(void)
{
#ifdef DEBUG_SPACE_VECTOR_CONTROL

  VCmd_a.push_back(V_xo_debug[0]);
  VCmd_b.push_back(V_xo_debug[1]);
#ifdef RECORD_ALL_PROBES
  VCmd_c.push_back(V_xo_debug[2]);
#endif

#else

  VCmd_a.push_back(V_xo[0]);
  VCmd_b.push_back(V_xo[1]);
#ifdef RECORD_ALL_PROBES
  VCmd_c.push_back(V_xo[2]);
#endif


#endif

  VCmd_mag.push_back(vcmd_mag);
  VCmd_ang.push_back(vcmd_ang);
  FreqScale.push_back(PwmFreqScale);

}

void VDqCmd::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{

  int i;
  if(TagNamesToPlot[0] == ""){
    SimuPlot.plot_xy(Plot_t, VCmd_a, "VCmd_a");
    SimuPlot.plot_xy(Plot_t, VCmd_b, "VCmd_b");
    SimuPlot.plot_xy(Plot_t, VCmd_c, "VCmd_c");
    SimuPlot.plot_xy(Plot_t, VCmd_mag, "VCmd_mag");
    SimuPlot.plot_xy(Plot_t, VCmd_ang, "VCmd_ang");
    SimuPlot.plot_xy(Plot_t, FreqScale, "FreqScale");
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "VCmd_a"){
	SimuPlot.plot_xy(Plot_t, VCmd_a, "VCmd_a");
      }
      else if(TagNamesToPlot[i] == "VCmd_b"){
	SimuPlot.plot_xy(Plot_t, VCmd_b, "VCmd_b");
      }
      else if(TagNamesToPlot[i] == "VCmd_c"){
	SimuPlot.plot_xy(Plot_t, VCmd_c, "VCmd_c");
      }
      else if(TagNamesToPlot[i] == "VCmd_mag"){
	SimuPlot.plot_xy(Plot_t, VCmd_mag, "VCmd_mag");
      }
      else if(TagNamesToPlot[i] == "VCmd_ang"){
	SimuPlot.plot_xy(Plot_t, VCmd_ang, "VCmd_ang");
      }
      else if(TagNamesToPlot[i] == "FreqScale"){
	SimuPlot.plot_xy(Plot_t, FreqScale, "FreqScale");
      }

    }
  }


}

void  VDqCmd::CtrlRValueUpdate(void)     //!!!!! Pwm's should be in SrcRValueUpdate() (should not change operation) !!!!!!1
{
  SrcObjItem * pCurSrcItem;

  //Update Rvalues
  pCurSrcItem = pSrcObjRValList;

  ((PwmA *) pCurSrcItem->pSrcObject)->V_xo = V_xo[0];
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  ((PwmB *) pCurSrcItem->pSrcObject)->V_xo = V_xo[1];
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  ((PwmC *) pCurSrcItem->pSrcObject)->V_xo = V_xo[2];
  pCurSrcItem = pCurSrcItem->pNextSrcItem;
  ((TriangleWave *) pCurSrcItem->pSrcObject)->PwmFreqScale = PwmFreqScale;


}

void VDqCmd::OdeRValueUpdate(void)
{
  OdeObjItem * pCurOdeItem;

  //Update Rvalues
  pCurOdeItem = pOdeObjRValList;

  ((ISample *) pCurOdeItem->pOdeObject)->V_xo[0] = V_xo[0];
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  ((ISample *) pCurOdeItem->pOdeObject)->V_xo[1] = V_xo[1];
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  ((ISample *) pCurOdeItem->pOdeObject)->V_xo[2] = V_xo[2];

#ifdef LINEAR_AMP_MODE

  //we are sending the analog voltage commands directly to the "Ia_Ib_Ic_x" OdeObjects's
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  ((Ia_Ib_Ic_1 *) pCurOdeItem->pOdeObject)->pwm_sig = V_xo[0];
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  ((Ia_Ib_Ic_2 *) pCurOdeItem->pOdeObject)->pwm_sig = V_xo[1];
  pCurOdeItem = pCurOdeItem->pNextOdeItem;
  ((Ia_Ib_Ic_3 *) pCurOdeItem->pOdeObject)->pwm_sig = V_xo[2];

#endif

}


void VDqCmd::SpaceVectorControl(void)
{



  double CtrlAngle;
  double Amplitude;






  CtrlAngle = Nr*theta;

#ifdef LINEAR_AMP_MODE
  //Here we generate analog voltage commands directly....

  Amplitude = (2.0/3.0);

  V_xo[0] = Amplitude*(vdd*cos(CtrlAngle) - vqd*sin(CtrlAngle));
  V_xo[1] = Amplitude*(vdd*cos(CtrlAngle - 2*PI/3) - vqd*sin(CtrlAngle - 2*PI/3));
  V_xo[2] = Amplitude*(vdd*cos(CtrlAngle - 4*PI/3) - vqd*sin(CtrlAngle - 4*PI/3));

#else

  Amplitude = (2.0/3.0)*PWM_GAIN;

  V_xo[0] = Amplitude*(vdd*cos(CtrlAngle) - vqd*sin(CtrlAngle)) / v_bus;
  V_xo[1] = Amplitude*(vdd*cos(CtrlAngle - 2*PI/3) - vqd*sin(CtrlAngle - 2*PI/3)) / v_bus;
  V_xo[2] = Amplitude*(vdd*cos(CtrlAngle - 4*PI/3) - vqd*sin(CtrlAngle - 4*PI/3)) / v_bus;

#endif



}


// ---------------------------------------------------------------



// ---- RefGen  ---------------------------------------------------

RefGen::RefGen(void)
{
  CtrlObjItem * pCurCtrlItem;

  CtrlFuncName = CTRL_FUNC_RefGen;
  LiteralName = "RefGen";

    //We want this "RefGen" to immediately update "VDqCmd" and other selected CtrlObject's ahead of it after it's
    //control function is executed.
  DoImmedCtrlUpdate = TRUE;

    //build the CTRL Rvalue list

  pCtrlObjRValList = new CtrlObjItem;
  pCurCtrlItem = pCtrlObjRValList;

  pCurCtrlItem->pCtrlObject = CtrlObjectList[CTRL_FUNC_VDqCmd];
  pCurCtrlItem->pNextCtrlItem = new CtrlObjItem;
  pCurCtrlItem = pCurCtrlItem->pNextCtrlItem;
  pCurCtrlItem->pCtrlObject = CtrlObjectList[CTRL_FUNC_VDqCmd];

  //!!!!!!!!!!!!!!!
  //
  //   Here is where we setup to write the following R-values to "FSFCtrl" below
  //
  //   vdd, vqd, idd, iqd, omegad, thetad, zetad
  //
  //
  //
  //!!!!!!!!!!

  DoProbes = TRUE;


}

RefGen::~RefGen(void)
{



}



void RefGen::CtrlFunction(double t)
{




  //#define EXPONENTIAL_RAMPING
#ifdef EXPONENTIAL_RAMPING

  //  To do:
  //
  //   Implement exponential ramping (with linear ramping within accel/decel segments)
  //
  //     Something like this....
  //
  //     - Generate a velocity profile out of seven (7) segments.
  //     - For t0 <= t < t1, v = t**k
  //     - For t1 <= t < t2, v = t1**k + k*(t - t1)**k-1
  //     - For t2 <= t < t3, v = t1**k + k*(t2 - t1)**k-1 + (t1**k - ((t1 - t0) - (t - t2))**k
  //     - For t3 <= t < t4, v = v_const = t1**k + k*(t2 - t1)**k-1 + (t1**k - ((t1 - t0) - (t3 - t2))**k
  //     - (Similar calculations for ramping down...)
  //
  //
  //     - Now, integrate the final equation above for t between t0 and t7 and equate it to the desired position.
  //
  //     - Given t0, t1, t2, k, v_const and position with t7 - t6 == t1 - t0, t6 - t5 == t2 - t1, and t5 - t4 == t3 - t2
  //       and t3 - t2 == t1 - t0, solve for t3, t4, t5, t6 and t7.
  //
  //     - Execute each equation based on the current value of t within it's time segment.
  //
  //


#else


  //Point to point, "modified sin" trajectory generator.


  if(t < RT_TRAJ){
    omegad = VO_TRAJ*(sin(t*PI/RT_TRAJ - PI/2.0) + 1)/2.0;
    thetad =  VO_TRAJ*(-(RT_TRAJ/PI)*cos(t*PI/RT_TRAJ - PI/2.0) + t)/2.0;
    alphad = VO_TRAJ*(PI/RT_TRAJ)*cos(t*PI/RT_TRAJ - PI/2.0)/2.0;
    betad = VO_TRAJ*(-PI/RT_TRAJ)*(PI/RT_TRAJ)*sin(t*PI/RT_TRAJ - PI/2.0)/2.0;

  }
  else if(t < (RT_TRAJ + CT_TRAJ)){
    omegad = VO_TRAJ;
    thetad = VO_TRAJ*RT_TRAJ/2.0 + VO_TRAJ*(t-RT_TRAJ);
    alphad = 0;
    betad = 0;

  }
  else if(t < (2*RT_TRAJ + CT_TRAJ)){
    omegad = VO_TRAJ*(sin((CT_TRAJ+2*RT_TRAJ-t)*PI/RT_TRAJ - PI/2.0) + 1)/2.0;
    thetad =  VO_TRAJ*RT_TRAJ/2.0 + VO_TRAJ*(CT_TRAJ) + VO_TRAJ*(-(RT_TRAJ/PI)*cos((CT_TRAJ+RT_TRAJ-t)*PI/RT_TRAJ - PI/2.0) +
							      t-(RT_TRAJ+CT_TRAJ))/2.0;
    alphad = VO_TRAJ*(-PI/RT_TRAJ)*cos((CT_TRAJ+2*RT_TRAJ-t)*PI/RT_TRAJ - PI/2.0)/2.0;
    betad = VO_TRAJ*(PI/RT_TRAJ)*(-PI/RT_TRAJ)*sin((CT_TRAJ+2*RT_TRAJ-t)*PI/RT_TRAJ - PI/2.0)/2.0;

  }
  else{
    omegad = 0;
    thetad = VO_TRAJ*RT_TRAJ + VO_TRAJ*(CT_TRAJ);
    alphad = 0;
    betad = VO_TRAJ*(PI/RT_TRAJ)*(-PI/RT_TRAJ)*(-1.0/2.0);
    
  }

  //!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!1

  //"betad" being discontinuous causes small trajectory generation.

  betad = 0;

  //This is why exponential based ramping is ideal (no discontinuities at higher differencials)
  //Interesting howerver, if we force to "0", we can get a pretty good representation without generating
  //a "bump" on vdq.

  //In any event, this enforces the idea that the trajectory should be generated with using exponential ramping.

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#endif





  //generate the commands "vdd" and "vqd"


  idd = - ((Lm + M)*K*(3.0/2.0)*Nr*omegad*omegad) / (R*R + (Lm + M)*(Lm + M)*Nr*Nr*omegad*omegad);
  iqd = (Jm*alphad  + Bm*omegad + Cm*sgn(omegad) + Dm*sin(2*Nr*thetad)) / K;
  didd = - (2*K*(3.0/2.0)*(Lm + M)*R*R*Nr*omegad*alphad) / (R*R + (Lm + M)*(Lm + M)*Nr*Nr*omegad*omegad);
  diqd = (Jm*betad  + Bm*alphad  + Cm*impulse(sgn(omegad)) + Dm*2*Nr*cos(2*Nr*thetad)) / K;


  vdd = (Lm + M)*didd + R*idd - Nr*omegad*(Lm + M)*iqd;
                           //Like above, note the "3/2" scale factor on "K" below.
  vqd = (Lm + M)*diqd + R*iqd + Nr*omegad*(Lm + M)*idd + K*(3.0/2.0)*omegad;

  //For the full state feedback controller, we will integrate "thedad"

  zetad = zetad + thetad*(QUANTUM_PERIOD  * (double) REF_GEN_QUANTUM_CNT);

}

void RefGen::RecordProbes(void)
{
#ifdef RECORD_ALL_PROBES
  beta_d.push_back(betad);
  alpha_d.push_back(alphad);
#endif
  omega_d.push_back(omegad);
#ifdef RECORD_ALL_PROBES
  theta_d.push_back(thetad);
  zeta_d.push_back(zetad);
  id_d.push_back(idd);
  iq_d.push_back(iqd);
  did_d.push_back(didd);
  diq_d.push_back(diqd);
#endif
  vd_d.push_back(vdd);
  vq_d.push_back(vqd);

}


void RefGen::PlotProbes(Gnuplot & SimuPlot, vector<double> & Plot_t, string TagNamesToPlot[])
{

  int i;
  if(TagNamesToPlot[0] == ""){
    SimuPlot.plot_xy(Plot_t, beta_d, "betad");
    SimuPlot.plot_xy(Plot_t, alpha_d, "alphad");
    SimuPlot.plot_xy(Plot_t, omega_d, "omegad");
    SimuPlot.plot_xy(Plot_t, theta_d, "thetad");
    SimuPlot.plot_xy(Plot_t, zeta_d, "zetad");
    SimuPlot.plot_xy(Plot_t, id_d, "idd");
    SimuPlot.plot_xy(Plot_t, iq_d, "iqd");
    SimuPlot.plot_xy(Plot_t, did_d, "didd");
    SimuPlot.plot_xy(Plot_t, diq_d, "diqd");
    SimuPlot.plot_xy(Plot_t, vd_d, "vdd");
    SimuPlot.plot_xy(Plot_t, vq_d, "vqd");
  }
  else{
    for(i = 0; i < 20; i++){
      if(TagNamesToPlot[i] == "betad"){
	SimuPlot.plot_xy(Plot_t, beta_d, "betad");
      }
      else if(TagNamesToPlot[i] == "alphad"){
	SimuPlot.plot_xy(Plot_t, alpha_d, "alphad");
      }
      else if(TagNamesToPlot[i] == "omegad"){
	SimuPlot.plot_xy(Plot_t, omega_d, "omegad");
      }
      else if(TagNamesToPlot[i] == "thetad"){
	SimuPlot.plot_xy(Plot_t, theta_d, "thetad");
      }
      else if(TagNamesToPlot[i] == "zetad"){
	SimuPlot.plot_xy(Plot_t, zeta_d, "zetad");
      }
      else if(TagNamesToPlot[i] == "idd"){
	SimuPlot.plot_xy(Plot_t, id_d, "idd");
      }
      else if(TagNamesToPlot[i] == "iqd"){
	SimuPlot.plot_xy(Plot_t, iq_d, "iqd");
      }
      else if(TagNamesToPlot[i] == "didd"){
	SimuPlot.plot_xy(Plot_t, did_d, "didd");
      }
      else if(TagNamesToPlot[i] == "diqd"){
	SimuPlot.plot_xy(Plot_t, diq_d, "diqd");
      }
      else if(TagNamesToPlot[i] == "vdd"){
	SimuPlot.plot_xy(Plot_t, vd_d, "vdd");
      }
      else if(TagNamesToPlot[i] == "vqd"){
	SimuPlot.plot_xy(Plot_t, vq_d, "vqd");
      }
    }
  }


}

void RefGen::CtrlRValueUpdate(void)
{
  CtrlObjItem * pCurCtrlItem;

  //Update Rvalues
  pCurCtrlItem = pCtrlObjRValList;

  ((VDqCmd *) pCurCtrlItem->pCtrlObject)->vdd = vdd;
  pCurCtrlItem = pCurCtrlItem->pNextCtrlItem;
  ((VDqCmd *) pCurCtrlItem->pCtrlObject)->vqd = vqd;

  //!!!!!!!!!!!!!!!
  //
  //   Here is where we write the following R-values to "FSFCtrl" below
  //
  //   vdd, vqd, idd, iqd, omegad, thetad, zetad
  //
  //
  //
  //!!!!!!!!!!




}





double RefGen::sgn(double omegad)
{
  //code needs to be written here...
  return 0;
}

double RefGen::impulse(double sgn_omegad)
{

  //code needs to be written here...

  return 0;
}





// ---------------------------------------------------------------




// *****************************************************************


  


// **** SimuObject ************************************************




SimuObject Simulation;

SimuObject::SimuObject(void)
{
  OdeObjItem * pCurOdeItem;
  SrcObjItem * pCurSrcItem;
  CtrlObjItem * pCurCtrlItem;
  CtrlObjGroup * pCurCtrlGroup; 
  int i;


  SimuTime = 1.0;        
  
  MinimumPlotTime = 0;
  MaximumPlotTime = 1;



  ExceptionTime = .05;

  //For this example the setting of "RelTol" is important. If it is set to large
  //the system will become unstable. 
  RelTol =  .0000000001;
  //Setting "AbsTol" too small will make a system with a decaying oscillation 
  //take too long to finish.
  AbsTol =  .0000000000001; 
  //typical error correction setting as per "RungeKutta_java.htm" (never set higher then "1.0")
  Safety = .98;
  h_start = .000000001; 

  h = h_start;

  //set to a value other then "0" to clamp maximum "h";
  h_max = .0000002;

  //set to store and plot "h" parameter.
  Do_h_Plot = 1;
  
  TimeQuantum = h;
  CtrlTimeQuantum = QUANTUM_PERIOD;

  //set tp force CTRL update on first ODE update.
  CtrlTimeAccumulator = 0;

  SrcPeriodQuantum = QUANTUM_PERIOD;
  SrcPeriodAccumulator = 0;
 

  //build the SRC equation list
  pSrcEquationList = new SrcObjItem;
  pCurSrcItem = pSrcEquationList;
  i = 0;
  while(SrcObjectList[i]){
    pCurSrcItem->pSrcObject = SrcObjectList[i];
    i++;
    if(!SrcObjectList[i])
      break;
    pCurSrcItem->pNextSrcItem = new SrcObjItem;
    pCurSrcItem = pCurSrcItem->pNextSrcItem;


  }

  //build the ODE equation list.
  pOdeEquationList = new OdeObjItem;
  pCurOdeItem = pOdeEquationList;
  i = 0;
  while(1){
    pCurOdeItem->pOdeObject = OdeObjectList[i];
    i++;
    if(!OdeObjectList[i])
      break;
    pCurOdeItem->pNextOdeItem = new OdeObjItem;
    pCurOdeItem = pCurOdeItem->pNextOdeItem;
  }

  //build the CTRL equation lists.

  //(NOTE: As of 6/12/08, "pTranslationList" and "pTrajectoryList" CTRL's have been 
  //       deprecated and replaced with a "group" structure.)

  pCtrlGroupList = new CtrlObjGroup;
  pCurCtrlGroup = pCtrlGroupList;

  pCurCtrlGroup->pCtrlEquationList = new CtrlObjItem;
  pCurCtrlItem = pCurCtrlGroup->pCtrlEquationList;
  //set tp force CTRL update on first ODE update.
  pCurCtrlGroup->QuantumCount = 1;
  pCurCtrlGroup->QuantumNum = CtrlObjectQuantum[0];

  i = 0;
  while(1){
    pCurCtrlItem->pCtrlObject = CtrlObjectList[i];   
    i++;
    if(!CtrlObjectList[i])                 
      break;

    if(CtrlObjectQuantum[i] == CtrlObjectQuantum[i-1]){
      pCurCtrlItem->pNextCtrlItem = new CtrlObjItem;
      pCurCtrlItem = pCurCtrlItem->pNextCtrlItem;
    }
    else{
      //create a new group...
      pCtrlGroupList->pNextCtrlGroup = new CtrlObjGroup;
      pCurCtrlGroup = pCtrlGroupList->pNextCtrlGroup;

      pCurCtrlGroup->pCtrlEquationList = new CtrlObjItem;
      pCurCtrlItem = pCurCtrlGroup->pCtrlEquationList;
      //set tp force CTRL update on first ODE update.
      pCurCtrlGroup->QuantumCount = 1;
      pCurCtrlGroup->QuantumNum = CtrlObjectQuantum[i];  
    }
  }



 

}


SimuObject::~SimuObject(void)
{

  //(ideally we should delete all make allocation make in the constructor, here)

}



// ************************************************************





bool ExecuteSimulation(void)
{

   

  Simulation.OdeSimuType = ODE_SIMU_56;

  while(Simulation.t < Simulation.SimuTime){               

    if(!Simulation.DoOneInteration())
      return FALSE;
    
  }
  if(Simulation.GotException){
    cout << Simulation.ExceptionMessageBuffer.str().c_str();
  }

  return TRUE;
}

void PlotResults(string TagNamesToPlot[], double ScaleFactors[], double MinPlotTimes[], double MaxPlotTimes[], 
		 double PlotTimeSteps[], double PlotTimeOffset)
{
  Simulation.PlotSimuResults(TagNamesToPlot, ScaleFactors, MinPlotTimes, MaxPlotTimes, PlotTimeSteps, PlotTimeOffset);


}
