//-----------------------------------------------------------------------------
//
//  Peter Richter (prichter@princeton.edu)
//  Princeton Plasma Physics Laboratory
//  August 2000
//
//  eireaction.cpp - Implementation of sigma*v(Te) data
//    recombination; electron impact ionization
//
//-----------------------------------------------------------------------------
 
#include "preact/eireaction.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <math.h>
#include "preact/fortran.h"
#include "preact/global.h"
#include "preact/table.h"
 
using namespace std ;

#define L 180
 
//-----------------------------------------------------------------------------
 
EIReaction :: EIReaction(char tag[], int errlo, int errhi) : sigvTe_data()
{
  init_aladdin();
 
  this->errlo = errlo;
  this->errhi = errhi;
 
  if (!strcmp(tag, "recombine")) {
    code = 0;
    Zplas = 1;
    setTableParameters((char *)"ei/recomb/");
  }
  else if (!strcmp(tag, "i:e->H0")) {
    code = 1;
    Zplas = 1;
    setTableParameters((char *)"ei/eionzh/");
  }
  else if (!strcmp(tag, "i:e->He0")) {
    code = 2;
    Zplas = 2;
    setTableParameters((char *)"ei/eionhe/");
  }
  else if (!strcmp(tag, "i:e->Li0")) {
    code = 3;
    Zplas = 3;
    setTableParameters((char *)"ei/eionli/");
  }
}
 
//-----------------------------------------------------------------------------
 
EIReaction :: ~EIReaction()
{
  if (sigvTe_data.vector != NULL) {
    delete[] sigvTe_data.vector;
    delete[] sigvTe_data.domain;
  }
}
 
//-----------------------------------------------------------------------------
 
fp_64 EIReaction :: sigmav(fp_64 Te)
{
  fp_64 sigmav;
  sigmav = F77NAME(elec_sigv)(Te, code);
  return sigmav;
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: g_tablefile(char table[], char file[])
{
  // gen the table filename
  switch (code) {
  case 0: maptable((char *)"ei/recomb/", table, file); break;
  case 1: maptable((char *)"ei/eionzh/", table, file); break;
  case 2: maptable((char *)"ei/eionhe/", table, file); break;
  case 3: maptable((char *)"ei/eionli/", table, file); break;
  }
}
//-----------------------------------------------------------------------------
 
void EIReaction :: range_error_exit(char table[])
{
  char tablename[L];
  g_tablefile(table, tablename);
  cerr << " error interpolating data from table: " << endl;
  cerr << "    " << tablename << endl;
  F77NAME(bad_exit)();
}
//-----------------------------------------------------------------------------
 
void EIReaction :: range_error_warn(char table[])
{
  char tablename[L];
  g_tablefile(table, tablename);
  cerr << " interpolation range warning from table: " << endl;
  cerr << "    " << tablename << endl;
}
//-----------------------------------------------------------------------------
 
void EIReaction :: sigvTe_sigmaTimesV(fp_64 Te[], fp_64 f[], int n)
{
  // read table into memory if not done yet...
  if (sigvTe_data.vector == NULL) {
    char filename[L];
    fstream datafile;
 
    g_tablefile((char *)"sigvTe", filename);
    datafile.open(filename, ios :: in);
 
    // compute table if not done yet...
    if ( !datafile )
      compute1DTable(sigvTe_data, filename);
    else
      datafile.close();
 
    // now read table into memory...
    read1DTable(sigvTe_data, filename);
  }
 
  // interpolate from data and return sigma*v...
  interp1DTable((char *)"sigvTe", sigvTe_data, Te, (char *)"Electron Temperature", f, n);
}
 
//-----------------------------------------------------------------------------
 
range EIReaction :: sigvTe_TRange() const
{
  return sigvTe_data.endpoints;
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: sigvTe_TPolicy(int errlo, int errhi)
{
  sigvTe_data.modify(errlo, errhi);
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: setTableParameters(char dir[])
{
  fp_64 p1[8];
  int n = strlen(dir);
  char table[L];
 
  strcpy(table, dir);
  strcpy(table + n, "sigvTe");
  getparam(table, p1);
 
  sigvTe_data.set(p1, errlo, errhi);
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: computeAxis(fp_64 axis[], int npts, range endpts,
			       int spac)
{
  if (spac == LOG) {
    fp_64 t = log(endpts.maximum / endpts.minimum);
    for (int i = 0; i < npts - 1; i++)
      axis[i] = endpts.minimum * exp(fp_64(i) * t / fp_64(npts - 1));
    axis[npts - 1] = endpts.maximum;
  }
  else /* spac == LIN */ {
    fp_64 t = endpts.maximum - endpts.minimum;
    for (int i = 0; i < npts - 1; i++)
      axis[i] = endpts.minimum + fp_64(i) * t / fp_64(npts - 1);
    axis[npts - 1] = endpts.maximum;
  }
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: compute1DTable(grid_1D& g, char file[])
{
  ofstream f(file);
  if ( !f ) {
    cerr << "preact: output file open failure: " << file << endl;
    F77NAME(bad_exit)();
  }
  f.precision(15);
  fp_64 sigmav;
  fp_64 *axis = new fp_64[g.npoints];
  computeAxis(axis, g.npoints, g.endpoints, g.spacing);
  cout << "[...preact:  computing: " << file << " ]" << endl;
  for (int i = 0; i < g.npoints; i++) {
    sigmav = F77NAME(elec_sigv)(axis[i], code);
    f << sigmav << '\n';
  }
  delete[] axis;
  f.close();
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: read1DTable(grid_1D& g, char file[])
{
  ifstream f(file);
  g.vector = new fp_64[g.npoints];
  g.domain = new fp_64[g.npoints];
  for (int i = 0; i < g.npoints; i++) {
    f >> g.vector[i];
  }
  computeAxis(g.domain, g.npoints, g.endpoints, g.spacing);
  f.close();
}
 
//-----------------------------------------------------------------------------
 
void EIReaction :: interp1DTable(char table[], grid_1D& g,
				 fp_64 x[], char xdim[],
				 fp_64 f[], int n)
{
  int iwarn;
  F77NAME(flin1_z)(x, f, n, g.vector, g.endpoints.minimum,
		   g.endpoints.maximum, g.ln, g.npoints, iwarn);
 
  if (iwarn) {
    int halt = FALSE, warn = FALSE;
    table_errchk(x, f, n, xdim, g.endpoints, warn, halt);
    if (halt == TRUE)
      range_error_exit(table);
    if (warn == TRUE)
      range_error_warn(table);
  }
}
 
//-----------------------------------------------------------------------------
