%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\chapter{C++ Source for the CFD Client Application}\label{ch:appendixCFD}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\section{Sample input file for PUMA}
\label{ch:pumainput}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\begin{scriptsize}
\begin{verbatim}
Gamma      R         rhoRef    Vref      muRef
1.4        287.04    1.3813    320.46    1.831e-5
rho_inf     u_inf      v_inf      w_inf      p_inf         fsMult    xyzMult
1.3813      58.1152    0.0        0.0        101325.0      1.0       1.0
mu_inf   T_Suth  PrLam   PrTurb
1.831e-5 110.0   0.72    0.9
numIts      maxMinutes      wrRestart      wrResid      relResid      absResid
150         50000           5a             1            1.0e-6        1.0e-16
CFLconst      CFLslope
26            15
localStepping  spatial_order    inviscid_flux     integ_scheme    limiter
1              2                "roe"             "ssor"          "none"
innerIters    innerTol      omega     stages    K        commScheme
50            1.0e-8        1.0       2         5.0e+2   "delta q"
gridName                  restartFrom      restartTo        residName
"grids/apache.sg.gps"     ""               "apache.rst"     "apache.rsd"
implicitBCs    viscousModel      artDiss      VIS-2   VIS-4   M_CR
1              "inviscid"        0            1.00    1.0     0.85
Num_surfaces
7
surface BC_type rho u v w p
1       8
2       5
3       5
4       5
5       5
6       5
7       5
\end{verbatim}
\end{scriptsize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\section{Additions to PUMA (Server-side)}
\label{ch:puma.cc}
\begin{scriptsize}
\begin{verbatim}
/***************************************************************************/
#include "puma.h"
#include "global.h"
#include "dataservermpi.h"
#include "steering.h"
/***************************************************************************/
// Global variables for Computational Steering
int Ncells, Nghost, Nrecv;
int numCPUs, iter = 0, numIters = 0;
int Ntotal = 0;
double CFL, CFLconst, CFLslope;
double(*q)[5];
double GV_freestream[5];
char GV_fluxscheme[20];
char GV_intscheme[20];
char GV_gridfile[100], GV_inpfile[100], GV_residfile[100];
int NglobalCells = 0;
int NglobalFaces = 0;
double GV_logResid = 0.0;
double GV_MFlops = 0.0;
double GV_MFlopsPerProc = 0.0;
double GV_time_per_iter = 200.0;
int GV_querymode = 0;
NumericalFlux fscheme;
IntMethod tscheme;
double GV_min[12];
double GV_max[12];
double GV_mach, GV_temperature;
int GV_getrstflag = 0;
double *GV_rst = NULL;
int GV_num_rst = 0;
Surface isoContTri;
Surface surfaceTri;
double(*GV_isoContTri)[3][12] = NULL;
double(*GV_surfaceTri)[3][12] = NULL;
int GV_num_surfTri = 0;
int GV_num_isoContTri = 0;
int GV_isovar = -1;
int GV_restartflag = 0;
double GV_isovalue;
/***************************************************************************/
REGISTER_DATA_BLOCK()
{
  REGISTER_VARIABLE("flopcount", "ro", dFlops);
  REGISTER_VARIABLE("querymode", "rw", GV_querymode);
  REGISTER_VARIABLE("restart", "rw", GV_restartflag);
  REGISTER_VARIABLE("iter", "ro", iter);
  REGISTER_VARIABLE("numIters", "rw", numIters);
  REGISTER_VARIABLE("simTime", "ro", simTime);
  REGISTER_VARIABLE("rho", "rw", GV_freestream[0]);
  REGISTER_VARIABLE("u", "rw", GV_freestream[1]);
  REGISTER_VARIABLE("v", "rw", GV_freestream[2]);
  REGISTER_VARIABLE("w", "rw", GV_freestream[3]);
  REGISTER_VARIABLE("P", "rw", GV_freestream[4]);
  REGISTER_VARIABLE("M", "ro", GV_mach);
  REGISTER_VARIABLE("T", "ro", GV_temperature);
  REGISTER_1D_ARRAY("int_scheme", "rw", GV_intscheme);
  REGISTER_1D_ARRAY("flux_scheme", "rw", GV_fluxscheme);
  REGISTER_VARIABLE("CFLconst", "rw", CFLconst);
  REGISTER_VARIABLE("CFLslope", "rw", CFLslope);
  REGISTER_VARIABLE("CFL", "ro", CFL);
  REGISTER_VARIABLE("logResid", "ro", GV_logResid);
  REGISTER_VARIABLE("Ncells", "ro", NglobalCells);
  REGISTER_VARIABLE("Nlocalcells", "ro", Ncells);
  REGISTER_VARIABLE("Nlocalghost", "ro", Nghost);
  REGISTER_VARIABLE("Nlocalrecv", "ro", Nrecv);
  REGISTER_VARIABLE("Nfaces", "ro", NglobalFaces);
  REGISTER_1D_ARRAY("inpfile", "ro", GV_inpfile);
  REGISTER_1D_ARRAY("gridfile", "ro", GV_gridfile);
  REGISTER_1D_ARRAY("residfile", "ro", GV_residfile);
  REGISTER_VARIABLE("MFlops", "ro", GV_MFlops);
  REGISTER_VARIABLE("MFlopsPerProc", "ro", GV_MFlopsPerProc);
  REGISTER_VARIABLE("TimePerIter", "ro", GV_time_per_iter);
  REGISTER_VARIABLE("isoVar", "rw", GV_isovar);
  REGISTER_VARIABLE("isoValue", "rw", GV_isovalue);
  REGISTER_VARIABLE("min_rho", "ro", GV_min[0]);
  REGISTER_VARIABLE("max_rho", "ro", GV_max[0]);
  REGISTER_VARIABLE("min_u", "ro", GV_min[1]);
  REGISTER_VARIABLE("max_u", "ro", GV_max[1]);
  REGISTER_VARIABLE("min_v", "ro", GV_min[2]);
  REGISTER_VARIABLE("max_v", "ro", GV_max[2]);
  REGISTER_VARIABLE("min_w", "ro", GV_min[3]);
  REGISTER_VARIABLE("max_w", "ro", GV_max[3]);
  REGISTER_VARIABLE("min_Cp", "ro", GV_min[4]);
  REGISTER_VARIABLE("max_Cp", "ro", GV_max[4]);
  REGISTER_VARIABLE("min_M", "ro", GV_min[5]);
  REGISTER_VARIABLE("max_M", "ro", GV_max[5]);
  REGISTER_VARIABLE("min_T", "ro", GV_min[6]);
  REGISTER_VARIABLE("max_T", "ro", GV_max[6]);
  REGISTER_VARIABLE("min_P", "ro", GV_min[7]);
  REGISTER_VARIABLE("max_P", "ro", GV_max[7]);
  REGISTER_VARIABLE("min_Entropy", "ro", GV_min[8]);
  REGISTER_VARIABLE("max_Entropy", "ro", GV_max[8]);
  REGISTER_VARIABLE("min_X", "ro", GV_min[9]);
  REGISTER_VARIABLE("max_X", "ro", GV_max[9]);
  REGISTER_VARIABLE("min_Y", "ro", GV_min[10]);
  REGISTER_VARIABLE("max_Y", "ro", GV_max[10]);
  REGISTER_VARIABLE("min_Z", "ro", GV_min[11]);
  REGISTER_VARIABLE("max_Z", "ro", GV_max[11]);
  REGISTER_VARIABLE("getrstflag", "rw", GV_getrstflag);
  REGISTER_DYNAMIC_1D_ARRAY("q", "ro", q, Ncells);
  REGISTER_DYNAMIC_1D_ARRAY("isoCont", "ro", GV_isoContTri, GV_num_isoContTri);
  REGISTER_DYNAMIC_1D_ARRAY("SurfTri", "ro", GV_surfaceTri, GV_num_surfTri);
  REGISTER_DYNAMIC_1D_ARRAY("rstdata", "ro", GV_rst, GV_num_rst);
  REGISTER_STRUCTURE("isoContSurf", "ro", isoContTri);
  REGISTER_STRUCTURE("SurfTriSurf", "ro", surfaceTri);
}
/***************************************************************************/
void
UpdateCallback(char *key)
{
  myprintf("UpdateCallback: Keyword \"%s\" modified!!\n", key);
}
/***************************************************************************/
void
UpdateIntScheme()
{
  myprintf("UpdateIntScheme() called!\n");
  tscheme = getIntScheme(GV_intscheme);
}
/***************************************************************************/
void
UpdateFluxScheme()
{
  myprintf("UpdateFluxScheme() called!\n");
  fscheme = getFScheme(GV_fluxscheme);
}
/***************************************************************************/
\end{verbatim}
\end{scriptsize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\section{Graphical User Interface (Client-side)}
\label{ch:PumaClientWindow.cc}
\begin{scriptsize}
\begin{verbatim}
//**************************************************************************
#include "PumaClientWindow.h"
//**************************************************************************
PumaClientWindow::PumaClientWindow(int w, int h, const char *l,
                            const char *serverDefault,
                            int portDefault, const char *layoutFile):
ClientWindow(w, h, l, serverDefault, portDefault, 95)
{
  window->user_data(this);
  window->end();

  int width;
  int pos_h = 25;
  int pos_w = 5;
  int start_h = 35;
  int height = 25;
  int gap = 5;

  width = 110;
  variable = new variableChoice(pos_w, start_h, width, pos_h, this);
  pos_w += width + gap;
  variable->down_box(FL_BORDER_BOX);
  for(int i = 0; i < NumVars(); i++)
    variable->add(GetIsoVarName(i), 0,(Fl_Callback *) variableUpdate);
  variable->value(GetIsoVarID("M"));
  window->add(variable);

  width = 240;
  value = new Fl_Value_Slider(pos_w, start_h, width, pos_h);
  pos_w += width + gap;
  value->type(5);
  window->add(value);

  width = 70;
  getIt = new Fl_Button(pos_w, start_h, width, pos_h, "Get It!");
  pos_w += width + gap;
  getIt->callback((Fl_Callback *) getItClick);
  window->add(getIt);

  width = 140;
  queryMode = new Fl_Button(pos_w, start_h, width, pos_h, "Query Mode: OFF");
  pos_w += width + gap;
  queryMode->callback((Fl_Callback *) queryModeClick);
  window->add(queryMode);

  width = 80;
  getGrid = new Fl_Button(pos_w, start_h, width, pos_h, "Get Grid");
  pos_w += width + gap;
  getGrid->callback((Fl_Callback *) getGridClick);
  window->add(getGrid);

  start_h += height + gap;
  pos_w = 5;

  width = 200;
  pos_w += 70;
  layoutInp = new Fl_Input(pos_w, start_h, width, pos_h, "Layout file:");
  pos_w += width + gap;
  layoutInp->value(layoutFile);
  window->add(layoutInp);

  width = 80;
  getTecIso = new Fl_Button(pos_w, start_h, width, pos_h, "Contour");
  pos_w += width + gap;
  getTecIso->callback((Fl_Callback *) getTecIsoClick);
  window->add(getTecIso);

  width = 80;
  getTecSurf = new Fl_Button(pos_w, start_h, width, pos_h, "Surface");
  pos_w += width + gap;
  getTecSurf->callback((Fl_Callback *) getTecSurfClick);
  window->add(getTecSurf);

  width = 80;
  getTecGrid = new Fl_Button(pos_w, start_h, width, pos_h, "Grid");
  pos_w += width + gap;
  getTecGrid->callback((Fl_Callback *) getTecGridClick);
  window->add(getTecGrid);

  ConnectAction(false);

  Fl::add_idle((void(*)(void *)) IdleCalls, this);
}

//**************************************************************************
PumaClientWindow::~PumaClientWindow()
{
  delete variable;
  delete value;
  delete getIt;
  delete queryMode;
  delete getGrid;
  delete layoutInp;
  delete getTecIso;
  delete getTecSurf;
  delete getTecGrid;
}
//**************************************************************************
void PumaClientWindow::getItClick_i(Fl_Button * o, void *v)
{
  getIsoContour(variable->value(), value->round(value->value()));
  RenderIsoSurface(iso);
}
//**************************************************************************
void PumaClientWindow::getTecIsoClick_i(Fl_Button * o, void *v)
{
  char datafile[] = "contour.dat";
  getIsoContour(variable->value(), value->round(value->value()));
  WriteTrianglesToFile(iso, datafile);
  char cmd[200];
  sprintf(cmd, "tecplot %s %s &", layoutInp->value(), datafile);
  system(cmd);
}
//**************************************************************************
void PumaClientWindow::getTecSurfClick_i(Fl_Button * o, void *v)
{
  getSurfaceGrid();
  char datafile[] = "surface.dat";
//WriteTrianglesToFile(surface, datafile);
  char cmd[200];
  sprintf(cmd, "tecplot %s %s &", layoutInp->value(), datafile);
  system(cmd);
}
//**************************************************************************
void PumaClientWindow::getTecGridClick_i(Fl_Button * o, void *v)
{
  char datafile[] = "grid.dat";
  get3DTecplotFile(datafile);
  char cmd[200];
  sprintf(cmd, "tecplot %s %s &", layoutInp->value(), datafile);
  system(cmd);
}
//**************************************************************************
void PumaClientWindow::queryModeClick_i(Fl_Button * o, void *v)
{
  if (strcmp(queryMode->label(), "Query Mode: OFF") == 0)
    {
      SetQueryMode(true);
      queryMode->label("Query Mode: ON");
    }
  else
    {
      SetQueryMode(false);
      queryMode->label("Query Mode: OFF");
    }
}
//**************************************************************************
void PumaClientWindow::variableUpdate_i(Fl_Button * o, void *v)
{
  double minv = getMin(variable->value());
  double maxv = getMax(variable->value());
  value->minimum(minv);
  value->maximum(maxv);
  value->value(0.5 *(minv + maxv));
  clientTable->take_focus();
  variable->set_changed();
}
//**************************************************************************
void PumaClientWindow::getGridClick_i(Fl_Button * o, void *v)
{
  get3DTecplotFile("tecgrid.out");
}
//**************************************************************************
void PumaClientWindow::ConnectAction(bool connected)
{
  if (connected)
    {
      variable->activate();
      value->activate();
      getIt->activate();
      queryMode->activate();
      getGrid->activate();
      layoutInp->activate();
      getTecIso->activate();
      getTecSurf->activate();
      getTecGrid->activate();
      PumaClient::Connect(clientTable->GetClient());
      variableUpdate_i(NULL, NULL);
      if (QueryMode())
      queryMode->label("Query Mode: ON");
      else
      queryMode->label("Query Mode: OFF");
    }
  else
    {
      variable->deactivate();
      value->deactivate();
      getIt->deactivate();
      queryMode->deactivate();
      getGrid->deactivate();
      layoutInp->deactivate();
      getTecIso->deactivate();
      getTecSurf->deactivate();
      getTecGrid->deactivate();
      PumaClient::Disconnect();
    }
}
//**************************************************************************
void PumaClientWindow::Idle2()
{
  // enter critical section ++++++++++++++++++++++++++++++++++++++++++
  if (!PreventRefreshSem.isBusy())
    {
      if (clientTable->GetClient())
      {
        clientTable->update();
        if (QueryMode())
          queryMode->label("Query Mode: ON");
        else
          queryMode->label("Query Mode: OFF");
      }
    }
  // exit critical section -------------------------------------------
}
//**************************************************************************
int variableChoice::handle(int event)
{
  switch(event)
    {
    case FL_PUSH:
      if (window)
      window->PreventRefreshSem.Wait();
      Fl_Choice::handle(event);
      break;
    case FL_LEAVE:
      if (window)
      window->PreventRefreshSem.Post();
      break;
    }
}
//**************************************************************************
void PumaClientWindow::automate(char *var, int iter, const char *server, int port)
{
  cout << "-------------------" << endl << flush;
  cout << "Starting Automation" << endl;
  cout << "-------------------" << endl << flush;
  Connect((char *) server, port);
  int isoVar = GetIsoVarID(var);
  double minv = getMin(isoVar);
  double maxv = getMax(isoVar);
  cout << "Range for \"" << var << "\" = {" << minv << "," << maxv << "}" <<
    endl << flush;
  double dv =(maxv - minv) * 1.0 /(iter - 1);
  for(int i = 0; i < iter; i++)
    getIsoContour(isoVar, minv + dv * i);
  Disconnect();
  cout << "-----------------" << endl << flush;
  cout << "Ending Automation" << endl;
  cout << "-----------------" << endl << flush;
}
//**************************************************************************
\end{verbatim}
\end{scriptsize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
