#ifndef IMPREACT_ADPAK_H
#define IMPREACT_ADPAK_H

#include "preact/react.h"
#include "preact/impreaction.h"

//
// -------------------- adset_param -------------------
//
// collection of parameters used in adpak's adp_reset routine.
//
class adset_param {
public:
  adset_param() : kladen(1), kladtip(1), kleci(2), kldrmlt(1) { } ; // preferred defaults
  
  void adp_reset_param(int knucz) const ;  // call ADPAK's adp_reset() using the supplied data

  // --- data ---
  int kladen ;      // switch for energy level calculation
                    //  -1 -> do not change from default
                    //   0 -> use H. MAYER SHIELDING CONSTANTS
                    //   1 -> use R. MORE REVISED SHIELDING CONSTANTS
  int kladtip ;     // switch to use tabulated ionization potentials
                    //  -1 -> do not change from default
                    //   0 -> do not use tabulated data
                    //   1 -> use tabulated data
  int kleci ;       // switch for selecting formula to use for electron collisional ionization rate
                    //  -1 -> do not change from default
                    //   1 -> USE XSNQ DERIVED IONIZATION RATE CALCULATION
                    //   2 -> USE BELFAST GROUP LIGHT ELEMENT RATE FITS
                    //   3 -> USE YOUNGER'S RATES FOR AVAILABLE ELEMENTS AND SHELLS
                    //        XSNQ RATES OTHERWISE ON A CHARGE STATE-BY-CHARGE STATE BASIS
  int kldrmlt ;     // setup DIELECTRONIC RECOMBINATION RATE COEFFICIENT ARRAYS CDNN,CDNM
                    //  -1 -> do not change from default
                    //   0 -> USE CDNN, CDNM ARRAYS AS GIVEN
                    //   1 -> CDNN, CDNM ARRAYS SET TO 1.0
                    //   2 -> USE Y. HAHN FACTORS TO SETUP CDNN, CDNM
} ;

//
// -------------------- ImpReactADPAK ----------------------
// base class for interfacing to ADPAK routines -- handles common
// setup, ranges, ... used in ionization, recombination and radiation
// derived classes.  There are no public routines available for building
// an ImpReactADPAK by itself since it is abstract.
//
class ImpReactADPAK : public aReact {
public:
  virtual ~ImpReactADPAK() ;

  int         nucz()   const { return inucz ; } ;
  adset_param params() const { return adpak_data ; } ;

  //
  // --- adpak setup ---
  // each reaction can have it's own set of adpak switches which
  // are modified with these routines.  The arguments must be >0
  // so that the adpak state is uniquely specified.
  //
  void set_laden(int i)  ;  // see documunetation in adset_param
  void set_ladtip(int i) ;
  void set_leci(int i)   ;
  void set_ldrmlt(int i) ;

  // --- static ---
  static ImpReactADPAK* cast(const React& r) ;  // return the ImpReactADPAK pointer or 0

protected:
  ImpReactADPAK(int knucz, string name, size_t num, Shape fshape) ;

  // --- virtuals ---
  virtual void call(const ap_64& x, ap_64& f, Range::range_error& rerr) ;

  virtual void vcall2(const ap_64& x, const ap_64& y, ap_64& f, Range::range_error& rerr) ;

  virtual void adpak_func(const fp_64& x, const fp_64& y, fp_64* f) const = 0 ;

  virtual state current() const ; // return an appropriate state object

  virtual string dprint() const ; // descriptive output string of derived class specifics

private:
  // --- data ---
  int         inucz ;             // nuclear Z -- atomic number
  adset_param adpak_data ;        // switches controling configuration of adpak
} ;

//
// -------------------- ImpReactADPAK_Ioniz ----------------------
// Returns the ADPAK ionization rate (sec-1) of an element for each
// charge state species due to electron collisions
// given the electron temperature Te (keV) and electron density Ne (m-3).  
// The result is an array with size Z+1 where Z is the nuclear charge 
// of the element.
//
//    f = ImpReactADPAK_Ioniz::(6) ;  // carbon
//    Shape a(2) ;                    // hold arguments
//    a[0] = 10. ;                    // Te
//    a[1] = 1.e19 ;                  // Ne
//    ap_32 r(7) ;                    // hold result
//    f(a,r) ;                        // calculate ionization
//        r(i) -> ionization rate from charge state i to i+1 
//
class ImpReactADPAK_Ioniz : public ImpReactADPAK {
public:
  virtual ~ImpReactADPAK_Ioniz() ;

  // --------- static ---------
  static React                create(int knucz) ;     // public constructor of ImpReactADPAK_Ionizs
  static ImpReactADPAK_Ioniz* cast(const React& r) ;  // return the ImpReactADPAK_Ioniz pointer or 0

protected:
  ImpReactADPAK_Ioniz(int knucz, string name, size_t num, Shape fshape) ;

  // --- virtuals ---
  virtual void adpak_func(const fp_64& x, const fp_64& y, fp_64* f) const ;

  virtual state current() const ; // return an appropriate state object

  virtual string dprint() const ; // descriptive output string of derived class specifics
} ;

//
// -------------------- ImpReactADPAK_Recom ----------------------
// Returns the ADPAK recombination rate (sec-1) of an element for each
// charge state species due to electron collisions
// given the electron temperature Te (keV) and electron density Ne (m-3).  
// The result is an array with size Z+1 where Z is the nuclear charge 
// of the element.
//
//    f = ImpReactADPAK_Recom::(6) ;  // carbon
//    Shape a(2) ;                    // hold arguments
//    a[0] = 10. ;                    // Te
//    a[1] = 1.e19 ;                  // Ne
//    ap_32 r(7) ;                    // hold result
//    f(a,r) ;                        // calculate recombination rate
//        r(i) -> recombination rate from charge state i to i-1 
//
class ImpReactADPAK_Recom : public ImpReactADPAK {
public:
  virtual ~ImpReactADPAK_Recom() ;

  // --------- static ---------
  static React                create(int knucz) ;     // public constructor of ImpReactADPAK_Recoms
  static ImpReactADPAK_Recom* cast(const React& r) ;  // return the ImpReactADPAK_Recom pointer or 0

protected:
  ImpReactADPAK_Recom(int knucz, string name, size_t num, Shape fshape) ;

  // --- virtuals ---
  virtual void adpak_func(const fp_64& x, const fp_64& y, fp_64* f) const ;

  virtual state current() const ; // return an appropriate state object

  virtual string dprint() const ; // descriptive output string of derived class specifics
} ;

//
// -------------------- ImpReactADPAK_Brem ----------------------
// Returns the ADPAK radiation rate (joules/sec) of an element for each
// charge state species due to brem... radiation
// given the electron temperature Te (keV) and electron density Ne (m-3).  
// The result is an array with size Z+1 where Z is the nuclear charge 
// of the element.
//
//    f = ImpReactADPAK_Brem::(6) ;   // carbon
//    Shape a(2) ;                    // hold arguments
//    a[0] = 10. ;                    // Te
//    a[1] = 1.e19 ;                  // Ne
//    ap_32 r(7) ;                    // hold result
//    f(a,r) ;                        // calculate recombination rate
//        r(i) -> recombination rate from charge state i to i-1 
//
class ImpReactADPAK_Brem : public ImpReactADPAK {
public:
  virtual ~ImpReactADPAK_Brem() ;

  // --------- static ---------
  static React               create(int knucz) ;     // public constructor of ImpReactADPAK_Brems
  static ImpReactADPAK_Brem* cast(const React& r) ;  // return the ImpReactADPAK_Brem pointer or 0

protected:
  ImpReactADPAK_Brem(int knucz, string name, size_t num, Shape fshape) ;

  // --- virtuals ---
  virtual void adpak_func(const fp_64& x, const fp_64& y, fp_64* f) const ;

  virtual state current() const ; // return an appropriate state object

  virtual string dprint() const ; // descriptive output string of derived class specifics
} ;

//
// -------------------- ImpReactADPAK_Rad ----------------------
// Return the ADPAK radiation rate (joules/sec) of an element for each
// charge state species due to electron collisional excitation, radiative
// recombination and dielectronic recombination
// given the electron temperature Te (keV) and electron density Ne (m-3).  
// The result is an array with size Z+1 where Z is the nuclear charge 
// of the element.
//
//    f = ImpReactADPAK_Rad:(6) ;     // carbon
//    Shape a(2) ;                    // hold arguments
//    a[0] = 10. ;                    // Te
//    a[1] = 1.e19 ;                  // Ne
//    ap_32 r(7) ;                    // hold result
//    f(a,r) ;                        // calculate radiation rate
//        r(i) -> radiation rate for charge state i
//
// The bremsstrahlung radiation can optionally be included in the radiation
// rate -- the default is no brem...
//
class ImpReactADPAK_Rad : public ImpReactADPAK, public ImpReact_Rad {
public:
  virtual ~ImpReactADPAK_Rad() ;

  virtual bool brem() const ;     // true if including brem... in radiation results

  virtual void set_brem(bool b) ; // set true to include brem... in radiation power

  // --------- static ---------
  static React              create(int knucz) ;     // public constructor of ImpReactADPAK_Rads
  static ImpReactADPAK_Rad* cast(const React& r) ;  // return the ImpReactADPAK_Rad pointer or 0

protected:
  ImpReactADPAK_Rad(int knucz, string name, size_t num, Shape fshape) ;

  // --- virtuals ---
  virtual void adpak_func(const fp_64& x, const fp_64& y, fp_64* f) const ;

  virtual state current() const ; // return an appropriate state object

  virtual string dprint() const ; // descriptive output string of derived class specifics

private:
  // --- data ---
  int i_brem ;                    // nonzero to include brem... in radiation
} ;

#endif
