
 
  


#include "SimuCmds.hpp"

#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <math.h>

#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <vector>
#include <stdexcept>

#include "gnuplot_i.hpp"

using namespace std;




int ImageType; 


extern int n_max;

extern double ***ex, ***ey, ***ez;  
extern double ***hx, ***hy, ***hz;
extern int nx, ny, nz;
unsigned int x_slice_low;
unsigned int x_slice_high;
unsigned int y_slice_low;
unsigned int y_slice_high;
unsigned int z_slice_low;
unsigned int z_slice_high;
bool plot_e_field;
bool plot_h_field;
unsigned int GenerateXFieldSliceAtIntrationNum;

          

bool ExecuteSimulation(void);
void PlotResults(string [], double [], double [], double [], double [], double);

volatile SIMU_CMD SimuCmd;
int ProgressCount;

extern void Init_ToyFDTDbezhig(void);
extern void DoInteration(void);

// **** FEM version of original FDTD algorythm ****************************************************************************************************

extern void Init_ToyFDTDbezhig_FEM(void);
extern void DoInteration_FEM(void);

	//Test only (Can only be used if DEMO_MATRIX_INVERSE is defined in ToyFDTDbezhig.cc)
extern void demo_matrix_inverse(void);
extern void mat_demo(void);
// ********************************************************************************************************************************************************


string TagNamesToPlot[20];
double ScaleFactors[20];
double MinPlotTimes[20];
double MaxPlotTimes[20];
double PlotTimeSteps[20];
double PlotTimeOffset;

void CtrlCHandler(int signal)
{

      SimuCmd = SIMU_CMD_Exit;

}



int main(int argc, char *argv[])
{
  string TagName;
  double ScaleFactor;
  double MinPlotTime;
  double MaxPlotTime;
  double PlotTimeStep;
  int i;

  // **** FEM version of original FDTD algorythm ***************************

  	  //Define only to evaluate validity of this code...
 //#define DEMO_MATRIX_INVERSE
  #ifdef DEMO_MATRIX_INVERSE
    demo_matrix_inverse();
    return 0;

  #endif
    //Define only to evaluate validity of this code..
//#define DEMO_MATRIX_MULTIPLY
#ifdef DEMO_MATRIX_MULTIPLY
    	//Produces an Identity matrix result in a 4x3 matrix.
    mat_demo();
    return 0;

#endif

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











  signal(SIGINT, CtrlCHandler);


  
  //All "App_<xxxx>.hpp" use these functions.
  //!!!!!!!! THIS "COMPARE" MAKES NO SENCE,... NEVER TRUE,... FIX LATER !!!!!!!!!)
  if(ExecuteSimulation() == SIMU_CMD_Exit){
    return 0;
  }

 

}

void CheckPlotState(void)
{
  while(1){
    if((SimuCmd == SIMU_CMD_BreakLoop) || (SimuCmd == SIMU_CMD_Exit)){
      break;
    }
    pause();
   }
}

bool QuickCheckPlotState(void)
{
  return((SimuCmd == SIMU_CMD_BreakLoop) || (SimuCmd == SIMU_CMD_Exit));
 }


bool CheckSimuState(double CurTime, double SimuTime)
{
  int  CurProgressCount;
  if((SimuCmd == SIMU_CMD_BreakLoop) || (SimuCmd == SIMU_CMD_Exit)){
    cout << "\n\nSimulation stopped...\n\n\n";
    cout << "\t   Current Time - " << CurTime << "\n";
    cout << "\tSimulation Time - " << SimuTime << "\n\n\n";
    return FALSE;
  }
  else{
    CurProgressCount = (int) (100.0 * CurTime / SimuTime);
    if(CurProgressCount > ProgressCount){
      while(CurProgressCount > ProgressCount){
	printf("%3d percent executed...\n", CurProgressCount);
	ProgressCount++;
      }
      
    }
    return TRUE;
  }
}

bool ExecuteSimulation(void)
{
  Gnuplot SimuPlot;

  SimuPlot.reset_plot();

   //Un-comment to use FEM simulation.
#define SIMULATE_USING_FEM

#ifdef SIMULATE_USING_FEM
  Init_ToyFDTDbezhig_FEM();
#else
  Init_ToyFDTDbezhig();
#endif

  while(1){

#ifdef SIMULATE_USING_FEM
	  DoInteration_FEM();
#else
    DoInteration();
#endif

#ifdef SIMULATE_USING_FEM
     x_slice_low = 1;
     x_slice_high = n_max - 1;
     y_slice_low = 1;
     y_slice_high = n_max - 1;
     z_slice_low = 1;
     z_slice_high = n_max - 1;
     plot_e_field = TRUE;
     plot_h_field = TRUE;


#else
    x_slice_low = 1; 
    x_slice_high = nx - 1;
    y_slice_low = 1;
    y_slice_high = ny - 1;
    z_slice_low = 1;
    z_slice_high = nz - 1;
    plot_e_field = TRUE;
    plot_h_field = TRUE;

#endif


// ***** Analysis of "curl" on center section of simulatin run*********************************
//
//Conditions: #define SIMULATE_Y_CONDUCTING_ELEMENT_TEST_CONTINUOUS
//                    (we should be at the DC portion of J" at this point.)
//
//
//
//

   GenerateXFieldSliceAtIntrationNum =25;

    // In Octave issue the following after this interation is executed.
    //
    //
    //octave:8> load Octave_U_V_data_file 
    //octave:9> [X Y] = meshgrid(1:32, 1:32);
    //octave:10> [curlz, cav] = curl(X, Y, U, V);
    //octave:11> mesh(X, Y, curlz)
    //octave:12> mesh(X, Y, cav)
    //octave:13> 


   // Comments: We see the distinctive "z" direction to the impressed "J" current.
   //           However, there is still indication wave propagating in the X/Y direction.
   //           We have to be careful of reflections on either side of the dipole. (I do not think
   //           this is the issue here. 
   //
   //        (Be careful of changing code in his program. Most of the parameters that generated this simulation 
   //         are hard coded!!!)
   //
   //
   //    Saved plots:
   //                   ./CURL_PLOTS/curlz.png,...cav.png,  simulation_run.png
   
 
 // **********************************************************************

#ifdef SIMULATE_USING_FEM


   SimuPlot.plot_vectors(n_max, n_max, n_max, (const double ***) ex, (const double ***) ey, (const double ***) ez,
			  (const double ***) hx, (const double ***) hy, (const double ***) hz,
			  (const unsigned int) x_slice_low, (const unsigned int ) x_slice_high,
			  (const unsigned int) y_slice_low, (const unsigned int ) y_slice_high,
			  (const unsigned int) z_slice_low, (const unsigned int ) z_slice_high,
		     (const bool) plot_e_field, (const bool) plot_h_field,
		     (const unsigned int) GenerateXFieldSliceAtIntrationNum );

#else

       SimuPlot.plot_vectors(nx, ny, nz, (const double ***) ex, (const double ***) ey, (const double ***) ez, 
    			  (const double ***) hx, (const double ***) hy, (const double ***) hz,
    			  (const unsigned int) x_slice_low, (const unsigned int ) x_slice_high, 
    			  (const unsigned int) y_slice_low, (const unsigned int ) y_slice_high,      
    			  (const unsigned int) z_slice_low, (const unsigned int ) z_slice_high, 
			     (const bool) plot_e_field, (const bool) plot_h_field,
			     (const unsigned int) GenerateXFieldSliceAtIntrationNum );

#endif

       if(SimuCmd == SIMU_CMD_Exit)
           break;


      }


  return SIMU_CMD_Exit;
}


void PlotResults(string [], double [], double [], double [], double [], double)
{
  Gnuplot SimuPlot;

  SimuPlot.reset_plot();


}
