|------------------------------------------------------------------------------
|
|  Peter Richter (prichter@princeton.edu)
|  Princeton Plasma Physics Laboratory
|  August 2000
!
!  Updated Mar02, Rob Andre PPPL: For Impurity Reaction Rates
|
|  documentation.txt - Documentation for PREACT module.
|
|------------------------------------------------------------------------------


 Contents:	I.    Abstract/Introduction
                II.   Installation
		III.  Usage
		IV.   Error Handling
                V.    Programming Interface
                VI.   Available Data
                VII.  Simple Examples
                VIII. Known Problems
                IX.   References

See README for instructions on installing the module.

-------------------------------------------------------------------------------
 I. ABSTRACT/Introduction
-------------------------------------------------------------------------------

The PREACT module performs lookups and interpolation of tables of the rate
(weighted product of cross-section and velocity "sigma*v") of various charge
exchange, impact ionization, and fusion reactions.  It has independent 
interfaces for use in both C++ and Fortran-77 codes.  The C++ interface is 
fully object-oriented, and the Fortran-77 interface provides a layer above
this C++ interface so that PREACT may be embedded in legacy Fortran-77 
transport codes.  The module generates data tables with real*8 precision,
and for convenience supports both a real and a real*8 programming interface.
The interface is "vector oriented", returning a list of reaction rate 
coefficients given a list of input parameters appropriate to the
type of data sought; taking advantage of the vector feature can significantly
benefit applications performance.

PREACT is now used for all atomic and nuclear rate data in TRANSP.
Installing PREACT and exploiting its vector capabilities resulted in
a 10-15% speed-up of TRANSP's serial Monte Carlo fast ion calculation.

Available reaction table groups are:

CX -- (neutralizing) charge exchange between light neutrals and
      light fully stripped ions (H,He,Li) (Li data is not complete)

II -- impact ionization + non-neutralizing charge exchange ionization
      of light neutrals by light ions (H,He,Li) (Li data is not complete)

FS -- various fusion reactions involving D,T,He3

EI -- electron impact ionization and H+,e- recombination

SV -- stopping on fully stripped light impurities (C+6,O+8, scaled by Z
      for other impurities)

A partial list of tables:

                        CX      II      FS      EI      SV

[sigma*v](Erel/A)       x       x                       x
[sigma*v](Erel)                         x
<sigma*v>(Te)                                   x
<sigma*v>(Eb/Ab,Ti/Ai)  x       x
<sigma*v>(Eb,Ti)                        x
<<sigma*v>>(Ti)                         x

[sigma*v] indicates a mono-energetic interaction;
<sigma*v> indicates an average over a Maxwellian;
<<sigma*v>> indicates a bimaxwellian convolution (i.e. thermonuclear
          rates)

all energies and temperatures are given in KeV or KeV/AMU; output
rate coefficients are in m**3/sec.

Also available:

  CX -- tables giving expectation values for energy and normalized velocity
        (relative to incident beam) for beam-target interactions

  FS -- gyro-averaged sigma*v table, useful for fast ion - fast ion fusion
        rate calculations in the presence of a magnetic field


Author:  Peter Richter (prichter@princeton.edu)
Contact: TRANSP Support (transp_support@pppl.gov)

Update RGA (1/2002):
Rates for impurity ionization, recombination and radiation have been added to
the preact C++ and fpreact fortran interface.  The interface is similar to the
other reaction cross sections except for the following aspects:
  1) The rates are returned for all of the charge states of an atomic
     species so the vector interfaces return results in a two dimensional
     array.
  2) The electron density is an input along with the electron temperature
     with the resulting rates in the form <sigma*v*ne> in units of (sec-1)
     for ionization and recombination or (joules/sec) for radiation.
  3) The f77 layer exposes only a small fraction of the underlying C++ code.
  4) The initial source of impurity rate data has been taken from the ADPAK
     module which is now a dependency of preact.  ADPAK is Russell Hulse's
     Atomic Data package extracted from the MIST code.  Other sources are 
     expected to follow.
  5) The structure of the code is separate from the other reaction code and
     data table architecture.

In addition, there is a routine for calculating the coronal equilibrium
using the ionization and recombination rate results.

-------------------------------------------------------------------------------
 II. INSTALLATION
-------------------------------------------------------------------------------

See README for instructions on building, testing and installing the module.


-------------------------------------------------------------------------------
 III. USAGE
-------------------------------------------------------------------------------

The environment variable PREACTDIR must be set to be the full pathname of the
directory where the Plasma Reaction Tables are stored.

A "high level" fortran interface, fpreact, exists and should be used in
preference to direct preact calls in most cases, when calling preact from
fortran code.

From C++ code, the user interfaces with the PREACT module via the six 
C++ classes

 --  CXReaction (for charge exchange reactions)
 --  IIReaction (for ion impact ionization reactions)
 --  FSReaction (for fusion reactions)
 --  EIReaction (for electron impact ionization and recombination 
                 reactions (vs. Te only))
 --  SVReaction (for impurity stopping cross section tables (vs. Erel only))
 --  ImpReaction (for impurity ionization, recombination and radiation)

The header files for these classes are located in the directory
include/preact, and the file preact/testpreact.cpp shows how the
classes are used in a client program.  When compiling a client program that
uses the PREACT module, the user must link his code with the PREACT libraries
(libpreact.a, libsigsub.a, libaladdinsub.a, libadpak.a,
libcppsub.a, libcomput.a and libportlib.a) and the Fortran run-time 
libraries (e.g. libfor.a, -lUfor, and -lFutil on a DEC Alpha).  Note that, 
as always, the order in which the libraries are given is important.  Thus, 
the compile command for a C++ client program 'client.cpp' that uses the 
PREACT module would look like

  % g++ -I$PREFIX/include -o client client.cpp \
        -L$PREFIX/lib/ -lpreact -lsigsub -laladdinsub \
        -ladpak -lcppsub -lcomput -lportlib /usr/lib/libfor.a -lUfor -lFutil

on a DEC Alpha (PREFIX points to the NTCC software root directory).

Although preact itself contains a fortran interface, this has been extended
for convenience in the library "fpreact.a".  "fpreact" uses an f90 static
module to store (and hide from the user) the integer "handles" needed by 
fortran to reference the underlying c++ objects.  The test program
"fpreact_test.f90" demonstrates use of both the real and real*8 
interfaces.  The f90 interface module "fpreact_calls" can be used to
have the compiler select the right fpreact routine depending on the
precision of calling arguments.  For the impurity rate data, the f77 and
f90 interfaces use the atomic number of the impurity element to reference
the underlying c++ object instead of using an integer handle as is used 
by the other reactions in fpreact.

In order to run a fortran client program on an Alpha, one would first type
something like

  % f90 -c client.for

to create object files for each of the client program source files, and would
then type something like

  % f90 -I$PREFIX/include -o client client.o \
         -L$PREFIX/lib -lfpreact  -lpreact -lsigsub -laladdinsub \
         -ladpak -lcppsub -lcomput -lportlib \
         -lstdc++

to build the client program (note the trailing reference to the c++ runtime
library may take different forms on different systems -- also not for gcc you
might need to include libgcc.a).

To view the current parameters for a particular reaction's tables, type the
command:

  % preact_list

The 'preact_list' program will prompt the user for the reaction and then show
the parameters for the given reaction's tables.  To change the parameters for a
particular table (which will require recomputing the table unless one with
those same parameters already exists), type:

  % preact_change

The 'preact_change' program will prompt the user for the necessary information
and then change the table parameters for the appropriate reaction.
To remove all existing computed tables from the database (thus re-initializing
the database), type:

  % preactinit

These are the only commands that the user need be concerned with.  (The
'preact_init' program in the directory $PREFIX/bin is not to be called
explicitly by the user; it is run by 'gmake install' and 'preactinit'
script.)

-------------------------------------------------------------------------------
 IV.  Error handling
-------------------------------------------------------------------------------

The main type of error handled by the preact/fpreact software is an 
out-of-range request for table interpolation.  The default error
handling is:  warn and use low end table value for out-of-range low;
write message, set status code and exit for out-of-range high.  The 
error handling "policy" is user controllable, with the following
policies available and indepently controllable on each dimension of
each table (from fpreact/hatom_mod.f90):

  !  "policy options" for range errors on table lookups.
  !  for each initialization a "policy" must be set for two
  !  conditions:  out-of-range low, and out-of-range high
  !  -- can also modify independently for each dimension of each table...

  integer, parameter :: r_ignore=0,r_warn=1,r_halt=2
  integer, parameter :: r_ignore_clear=3,r_warn_clear=4

  !
  ! These policies have effect when an energy or temperature argument
  ! is given beyond the range of the table data:
  ! 
  !  r_ignore means:  ignore range error; use nearest table value
  !  r_warn means:  use nearest table value, but issue a warning message
  !  r_halt means:  issue a warning message and exit
  !  r_ignore_clear means:  set result to zero *silently*
  !  r_warn_clear means:  set result to zero with warning message
  !
  !  actual policies:
  !    default:  ignore if out-of-range low
  !              halt with message if out-of-range high

The fortran interface fpreact sets "reasonable" error handling policies;
the code for this is in the private module fpreact/hatom_mod.f90.

The C++ interface allows either the default policy or a single policy
for all table dimensions to be defined at object instantiation time;
policy for individual dimensions can then be modified by subsequent
public "policy" method invocations.

-------------------------------------------------------------------------------
 V.  Programming Interfaces (C++ and Fortran)
-------------------------------------------------------------------------------

The C++ interface for the PREACT module consists of the following publiclly
accessible methods:


  ***** CXReaction class methods: ************************************

#include "grid_1d.h"
#include "grid_2d.h"

class CXReaction {

public:    // constructor, destructor...
           CXReaction(char tag[], int errlo = WARN, int errhi = HALT);
           ~CXReaction();

           // sigma, vrel as functions of Erel...
           fp_64 sigma(fp_64 Erel);
           fp_64 vrel(fp_64 Erel);

           // sigma*v for beam to cold (T=0) target...
           void coldTarget_sigmaTimesV(fp_64 E[], fp_64 f[], int n);
           void coldTarget_sigmaTimesV_32(fp_32 E[], fp_32 f[], int n);
           range coldTarget_ERange() const;
           void coldTarget_EPolicy(int errlo, int errhi);

           // <sigma*v> for beam to warm (T>0) target...
           void warmTarget_sigmaTimesV(fp_64 E[], fp_64 T[], fp_64 f[],
                                       int n);
           void warmTarget_sigmaTimesV_32(fp_32 E[], fp_32 T[], fp_32 f[],
                                       int n);
           range warmTarget_ERange() const;
           range warmTarget_TRange() const;
           void warmTarget_EPolicy(int errlo, int errhi);
           void warmTarget_TPolicy(int errlo, int errhi);

           // <E/A> of target reagent...
           void energyAvg_perAMU(fp_64 E[], fp_64 T[], fp_64 f[], int n);
           void energyAvg_perAMU_32(fp_32 E[], fp_32 T[], fp_32 f[], int n);
           range energyAvg_perAMU_ERange() const;
           range energyAvg_perAMU_TRange() const;
           void energyAvg_perAMU_EPolicy(int errlo, int errhi);
           void energyAvg_perAMU_TPolicy(int errlo, int errhi);

           // <Vb dot Vtarg / |Vb|*|Vth|>...
           void average_vDotNorm(fp_64 E[], fp_64 T[], fp_64 f[], int n);
           void average_vDotNorm_32(fp_32 E[], fp_32 T[], fp_32 f[], int n);
           range average_vDotNorm_ERange() const;
           range average_vDotNorm_TRange() const;
           void average_vDotNorm_EPolicy(int errlo, int errhi);
           void average_vDotNorm_TPolicy(int errlo, int errhi);

           ...}

  ***** IIReaction class methods: ************************************

#include "grid_1d.h"
#include "grid_2d.h"

class IIReaction {

public:    // constructor, destructor...
           IIReaction(char tag[], int errlo = WARN, int errhi = HALT);
           ~IIReaction();

           // sigma, vrel as functions of Erel...
           fp_64 sigma(fp_64 Erel);
           fp_64 vrel(fp_64 Erel);

           // sigma*v for beam to cold (T=0) target...
           void coldTarget_sigmaTimesV(fp_64 E[], fp_64 f[], int n);
           void coldTarget_sigmaTimesV_32(fp_32 E[], fp_32 f[], int n);
           range coldTarget_ERange() const;
           void coldTarget_EPolicy(int errlo, int errhi);

           // <sigma*v> for beam to warm (T>0) target...
           void warmTarget_sigmaTimesV(fp_64 E[], fp_64 T[], fp_64 f[], 
                                       int n);
           void warmTarget_sigmaTimesV_32(fp_32 E[], fp_32 T[], fp_32 f[], 
                                       int n);
           range warmTarget_ERange() const;
           range warmTarget_TRange() const;
           void warmTarget_EPolicy(int errlo, int errhi);
           void warmTarget_TPolicy(int errlo, int errhi);

           ...}


  ***** FSReaction class methods: ************************************

#include "grid_1d.h"
#include "grid_2d.h"

class FSReaction {

public:    // constructor, destructor...
           FSReaction(char tag[], int errlo = WARN, int errhi = HALT);
           ~FSReaction();

           // sigma, vrel as functions of Erel...
           fp_64 sigma(fp_64 Erel);
           fp_64 vrel(fp_64 Erel);

           // sigma*v for beam to cold (T=0) target...
           void coldTarget_sigmaTimesV(fp_64 E[], fp_64 f[], int n);
           void coldTarget_sigmaTimesV_32(fp_32 E[], fp_32 f[], int n);
           range coldTarget_ERange() const;
           void coldTarget_EPolicy(int errlo, int errhi);

           // <sigma*v> for beam to warm (T>0) target...
           void warmTarget_sigmaTimesV(fp_64 E[], fp_64 T[], fp_64 f[],
                                       int n);
           void warmTarget_sigmaTimesV_32(fp_32 E[], fp_32 T[], fp_32 f[],
                                       int n);
           range warmTarget_ERange() const;
           range warmTarget_TRange() const;
           void warmTarget_EPolicy(int errlo, int errhi);
           void warmTarget_TPolicy(int errlo, int errhi);

           // <<sigma*v>> thermonuclear...
           void thermonuclear_sigmaTimesV(fp_64 T[], fp_64 f[], int n);
           void thermonuclear_sigmaTimesV_32(fp_32 T[], fp_32 f[], int n);
           range thermonuclear_TRange() const;
           void thermonuclear_TPolicy(int errlo, int errhi);

           // <sigma*v> gyro average...
           void gyroAvg_sigmaTimesV(fp_64 E[], fp_64 Var[], fp_64 f[],
                                    int n);
           void gyroAvg_sigmaTimesV_32(fp_32 E[], fp_32 Var[], fp_32 f[],
                                    int n);
           range gyroAvg_ERange() const;
           range gyroAvg_VarRange() const;
           void gyroAvg_EPolicy(int errlo, int errhi);
           void gyroAvg_VPolicy(int errlo, int errhi);

           ...}

  ***** EIReaction class methods: ************************************

#include "grid_1d.h"
#include "grid_2d.h"

class EIReaction {

public:    // constructor, destructor...
           EIReaction(char tag[], int errlo = WARN, int errhi = HALT);
           ~EIReaction();

           // sigma, vrel as functions of Erel...
           fp_64 sigmav(fp_64 Te);

           // sigma*v for beam to cold (T=0) target...
           void sigvTe_sigmaTimesV(fp_64 Te[], fp_64 f[], int n);
           void sigvTe_sigmaTimesV_32(fp_32 Te[], fp_32 f[], int n);
           range sigvTe_TRange() const;
           void sigvTe_TPolicy(int errlo, int errhi);

           ...}

  ***** SVReaction class methods: ************************************

#include "grid_1d.h"
#include "grid_2d.h"

class SVReaction {

public:    // constructor, destructor...
           SVReaction(char tag[], int errlo = WARN, int errhi = HALT);
           ~SVReaction();

           // sigma, vrel as functions of Erel...
           fp_64 sigmav(fp_64 Erel);

           // sigma*v for beam to cold (T=0) target...
           void coldTarget_sigmaTimesV(fp_64 E[], fp_64 f[], int n);
           void coldTarget_sigmaTimesV_32(fp_32 E[], fp_32 f[], int n);
           range coldTarget_ERange() const;
           void coldTarget_EPolicy(int errlo, int errhi);

           ...}

  
  ***** ImpReaction class methods: ************************************
Two classes are relavent for impurity reactions.  A React class defines
a single quantity (ionization, recombination or radiation).  Impurity
rates are returned by operating on the React objects.  An ImpReaction
class holds the four Reacts needed to describe the rates of a single
impurity species (ionization, recombination, radiation (with or without
bremsstrahlung), bremsstrahlung radiation).  Also relevant is the fwrap 
template class which provides access to memory like a multidimensional 
fortran array and is typedefed to the names ap_32 and ap_64 depending 
on the precision of the result.

Two static methods exist in ImpReaction to support the calculation of
the coronal equilibrium and the radiation for a coronal equilibrium.
These are template functions which will select the precision according
to the type of the rate arguments.

//
// ------------------------ ImpReaction -----------------------
// Encapsulates the reactions associated with impurity rates
// Currently includes:
//    - electron collisional ionization rate (sec-1)
//    - recombination rate due to radiative and dielectronic
//      recombination (sec-1)
//    - radiation in (joules/sec) due to collisional excitation
//      and recombination and optionally brem...(default is no brem...)
//    - brem... radiation only in (joules/sec) 
//
// For all three rates:
//    arguments:  0-> Te (keV)  electron temperature
//                1-> Ne (m-3)  electron density
//
//    result:     rank 1 with shape [Z+1]
//                [i]-> rate for charge state i,  i=0...Z
//
// Note: If brem... is set to be included in radiation rad() React, then
//       trying to call brem() will throw an exception.  This is only to
//       prevent double counting of brem... in total radiation.
//
// example:
//    ImpReaction r(6) ;          // build carbon
//    ap_32 xarg(2), result(7) ;
//    xarg(0) = 10. ;             // Te in keV
//    xarg(1) = 1.e19 ;           // Ne in m-3
//    r.ioniz()(xarg,result) ;    // fill result array
//
class ImpReaction {
public:
  //
  // ---  constructor ---
  // The option value is used to select the objects used to implement
  // the impurity rates.
  //
  enum option {ADPAK_DIRECT=0} ;

  ImpReaction(int nucz, option r=ADPAK_DIRECT) ;
  ~ImpReaction() ;

  // --- reaction data ---
  int    nucz() const ;  // atomic number of this element
  string name() const ;  // name of this reaction

  string info() const ;  // informative

  //
  // -- modify the out of range policy for all three Reacts  --
  // Only the policy is modifiable here because the minimum and maximum
  // should be intrinsic to the implementation method.  The clear_minimum
  // and clear_maximum values are set to the default of 0.0 by these calls.  
  // Changing the policy could result in rebuilding an internally cached table.
  //   i=0 -> Te
  //    =1 -> Ne
  void r_set_min_policy(size_t i, Range::policy pmin) ;  // set policy for axis Range i
  void r_set_max_policy(size_t i, Range::policy pmax) ;

  // --- Reacts ---
  React ioniz()  ;  // Ionization    (sec-1)
  React recom()  ;  // Recombination (sec-1)
  React rad()    ;  // Radiation     (joules/sec)
  React brem()   ;  // Brem          (joules/sec)

  // --- static ---
  static string table_name(int knucz) ; // return name in the form  "Helium (He)"

  //
  // ----- static coronal equilibrium -----
  // These functions can operate in either single evaluation or vector
  // form depending on the rank of the input arrays
  //
  // coronal: calculates the coronal equilibrium given the ionization
  //          and recombination rate
  //          single mode,
  //             ioniz[Z+1] -> input -- rank 1 array of ionization rate over
  //                           charge states 0...Z
  //             recom[Z+1] -> input -- rank 1 array of recombination rate over
  //                           charge states
  //             coron[Z+1] -> output -- rank 1 array of fraction of particles in 
  //                           each charge state.  This is normalized
  //                           to a sum of 1.
  //          vector mode,
  //             ioniz[Z+1,N] -- input  -- same but rank 2 for N different sets of data
  //             recom[Z+1,N] -- input
  //             coron[Z+1,N] -- output
  //
  // coronal_rad: returns the total radiation in (joules/sec) based on the
  //              supplied coronal_equilibrium and radiation rate
  //          single mode,
  //             coron[Z+1] -> input -- rank 1 array of fraction of particles in 
  //                           each charge state as returned by coronal(), need not
  //                           be normalized to a sum of 1.
  //             rad[Z+1]   -> input -- rank 1 array of radiation rate in (joules/sec)
  //             total[]    -> output -- rank 0 array of total radiation in (joules/sec)
  //
  //          vector mode,
  //             coron[Z+1,N] -- input  -- same but rank 2 for N different sets of data
  //             rad[Z+1,N]   -- input  -- same but rank 2 for N different sets of data
  //             total[N]     -- output -- same but rank 1 for N different sets of data
  //
  template<typename FP> static void coronal(const fwrap<FP>& ioniz, const fwrap<FP>& recom, fwrap<FP>& coron) ;
  template<typename FP> static void coronal_rad(const fwrap<FP>& coron, const fwrap<FP>& rad, fwrap<FP>& total) ;
} ;

//
// ---------------------------- React ------------------------
// Describes a single function in a reaction.  This object has
// reference semantics so copying it will refer to the same 
// underlying reaction (aReact).  The function it describes has a fixed
// number of arguments, nargs(), and can return an array as
// a result of its invocation.
//
class React {
public:
  // --- object stuff ---
  React(aReact* q) ;   
  React(const React& q) ;
  React& operator=(const React& q) ;
  ~React() ;

  // --- arguments ---
  size_t nargs()       const  ;  // number of arguments of function

  fp_64  min(size_t i) const  ;   // return the minimum of this argument range  0<=i<nargs()
  fp_64  max(size_t i) const ;    // return the maximum of this argument range  0<=i<nargs()

  const Range& range(size_t i) const ;  // non-modifiable Range object

  // --- result ---
  size_t frank()    const ;    // rank  of result for one function evaluation
  Shape  fshape()   const ;    // shape of result for one function evaluation

  bool   isscalar() const  ; // true if result is scalar(rank=1, size(0)=1)

  //
  // set min/max policy for Range argument i -- do not ignore clear_scale.
  // It should be set to the relative size of the clear_value or is not changed if <=0.
  // This is important for comparing the state of the Range object.  The same clear_scale 
  // is used for both the min and max policy.  The defaults are (IGNORE, clear_value=0., clear_scale=1.).
  //
  void set_min_policy(size_t i, Range::policy pmin, fp_64 clear_value=0., fp_64 clear_scale=-1.) ;
  void set_max_policy(size_t i, Range::policy pmax, fp_64 clear_value=0., fp_64 clear_scale=-1.) ;

  // --- calling ---
  // evaluate the function once -- xargs is a 1d array containing all the arguments
  // so xargs.size(0)==nargs() is required.  The result is stored in f so f must
  // have the shape fshape().  The return logical is true if a WARN range error
  // occurred during evaluation.
  //
  bool operator()(const ap_64& xargs, ap_64& f) ; 
  bool operator()(const ap_32& xargs, ap_32& f) ;

  //
  // vector calls -- use vector1() if nargs()==1, vector2() if nargs()==2 ...
  //
  // Each argument (x,y,...) must be a 1 dimensional array with logical
  // length equal to the number of function evaluations.  The result is put
  // in the array fv which must have rank fv.rank()=frank+1.  The shape
  // of fv = (fshape()[0], fshape()[1], ..., fshape()[frank-1], x.size(0))
  // In other words, fv has the shape of the function result plus an extra
  // dimension which is the size of the number of function evaluations = x.size(0).
  // This is the way that you would make this call in fortran except the
  // logical and physical size of the arrays are built into the ap_64,ap_32 objects.
  //
  // A logical true is returned if a WARN range error occurred.
  //
  // skip_arg_check=true will skip checking the ranks and shapes of the arguments.
  //
  bool vector1(const ap_64& x, ap_64& fv, bool skip_arg_check=false) ;
  bool vector1(const ap_32& x, ap_32& fv, bool skip_arg_check=false) ;

  bool vector2(const ap_64& x, const ap_64& y, ap_64& fv, bool skip_arg_check=false) ;
  bool vector2(const ap_32& x, const ap_32& y, ap_32& fv, bool skip_arg_check=false) ;
} ;

  ***** FORTRAN ************************************

The recommended fortran (f77 compatible) interface is described in the
fortran-90 interface module "fpreact/fpreact_calls.f90" which is copied
below.  The "handles" for managing the underlying c++ objects are hidden
by default, but can be retrieved in case the user needs to access the 
underlying preact f77 interface.  The most likely reason for doing this
would be to access the energy range of a table.

Another possibly useful fpreact public fortran-90 module is
"fpreact/fpreact_parameters.f90" which defines parameters that can
be useful in fpreact calls.  These parameters can be used to specify
(for example) whether a beam-target table lookup routine is to assume
a neutral beam striking an ion target, or, an ion beam striking a 
neutral target.  "fpreact_parameters" is included in "fpreact_calls".

A detailed example of the usage of usage of fpreact_calls is in the
test program "fpreact_test.f90".

The preact fortran-77 interface is defined in several header files,
not reproduced here, all in the preact source directory:  f77cx.h, 
f77ii.h, f77fs.h, f77ei.h, f77sv.h, f77imp.h.

The Fortran-77 interface for the PREACT module consists of the following
routines:
module fpreact_parameters

  !  these are standard values for arguments of `hatom_btsigv'

  !  "irtype" -- reaction table selection
  integer, parameter :: fpreact_CX = 1    ! <sigma*v>cx
  integer, parameter :: fpreact_II = 2    ! <sigma*v>ii
  integer, parameter :: fpreact_EAV = 3   ! <Eav>cx
  integer, parameter :: fpreact_FD = 4    ! <vb.vtarg>/|vb*vth|

  !  "beamchrg" -- whether beam is neutral and target is ionized, or
  !                vice versa

  integer, parameter :: fpreact_NEUTRAL_BEAM = 1
  integer, parameter :: fpreact_ION_BEAM = 2

  !  common Z's of elements...

  integer, parameter :: fpreact_Z_H = 1
  integer, parameter :: fpreact_Z_He = 2
  integer, parameter :: fpreact_Z_Li = 3
  integer, parameter :: fpreact_Z_C = 6
  integer, parameter :: fpreact_Z_O = 8

end module fpreact_parameters

module fpreact_calls

  !  Atomic and Nuclear rate coefficients (<sigma*v>'s).

  !  All routines are vectorized, i.e. input list of interaction energies
  !  and receive back list of reaction rate coefficients.

  !  All energies & temperatures in KeV.
  !  All rate coefficients <sigma*v> in m**3/sec.

  !  In atomic physics tables, energies and temperatures are normalized
  !  per AMU.  Thus in a (H+,D+) 1 KeV thermal plasma, the D+ has a
  !  normalized temperature of 0.5 KeV/AMU and the H+ a normalized 
  !  temperature of 1.0 KeV/AMU.  All isotopes of H undergo the same
  !  atomic physics reactions, but, since the relative velocity of 
  !  the charges is what is important for determining reaction rates,
  !  the per AMU normalization must be applied to all temperature and
  !  energy arguments.

  !  In nuclear physics tables, of course isotopes are not 
  !  interchangeable, and the real (i.e. not normalized per AMU)
  !  temperatures and energies are used.

  !  Actual reaction rate between populations of densities n1 & n2 (m**-3)
  !  is n1*n2*<sigma*v> (reactions/m**3/sec).

  !  All routines are front ends for `preact' -- a module which computes
  !  reaction rate coefficient tables once and stores these as files;
  !  once a table is computed, it is not recomputed, but simply read in
  !  for interpolation.

  !  Computation and storage of table file happens once per installation,
  !  read of table file happens once per code run,
  !  interpolations happen 1000000s of times and are very fast.

  !  For information on table energy/temperature range limits and
  !  for policies on out-of-range interpolation requests:  see the
  !  comments in the module fpreact/hatom_mod.f90 ... the fpreact 
  !  interface does not allow for modification of out-of-range 
  !  error handling policy; if this is required, use `preact'
  !  directly:
  !    (a) use the appropriate fpreact subroutine to fetch the 
  !        reaction handle;
  !    (b) call the appropriate preact subroutine, with reaction
  !        handle argument, to get information on energy range
  !        limits, set out-of-range error handling policy, etc.

  !  the fpreact sources containing the handle subroutines are:
  !    fusn_handles.f90   zstop_handles.f90 
  !    sigvte_handle.f90  hatom_handle.f90
  !

  !------------------ parameters:  these can be used as calling arguments
  !                                in hatom_btsigv and similar routines...
 
  use fpreact_parameters

  !------------------ Atomic Physics:  neutral stopping rate coefficients
  !
  !  caution:  cross-section data for Li neutrals is incomplete
  !
  !  neutral stopping by impurity (charge exchange + ionization)
  !  neutral stopping by electron impact ionization
  !  caution:  cross-section data for Li neutrals is incomplete
  !
  !  neutral stopping by impurity (charge exchange + ionization)
  !  neutral stopping by electron impact ionization

  interface zstop_sigv

     ! neutral stopping by fully stripped light impurities
     !  data for H and He neutral atoms
     !                 Li neutral atoms (data based on H cross sections!)
     !  data for C+6 and O+8
     !    if Z < 6, scale the Carbon rate coeff. down by Z/6
     !    if Z > 8, scale the Oxygen rate coeff. up by Z/8
     !    if 6 < Z < 8, linearly interpolate between the Carbon and
     !                  Oxygen coefficients
     !
     !  Erel/A (eova) = 0.5*mp*vrel**2, mp = proton mass, expressed in KeV
     !  rate coefficient sigma*v (sigv) returned in m**3/sec

     subroutine zstop_sigv(izneut,izimp,eova,n,sigv)
       implicit NONE

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       integer, intent(in) :: izimp   ! Z of impurity, .ge.3
       integer, intent(in) :: n       ! vector size
       real*8, intent(in) :: eova(n)  ! Erel/A vector, KeV
       real*8, intent(out) :: sigv(n) ! rate coefficient sigma*v, m**3/sec

     end subroutine zstop_sigv

     subroutine zstop_sigv_r4(izneut,izimp,eova,n,sigv)
       implicit NONE

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       integer, intent(in) :: izimp   ! Z of impurity, .ge.3
       integer, intent(in) :: n       ! vector size
       real, intent(in) :: eova(n)    ! Erel/A vector, KeV
       real, intent(out) :: sigv(n)   ! rate coefficient sigma*v, m**3/sec

     end subroutine zstop_sigv_r4

     subroutine zstop_sigvz(izneut,zimp,eova,n,sigv)
       implicit NONE

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       real*8, intent(in) :: zimp     ! Z of impurity, .ge.3
       integer, intent(in) :: n       ! vector size
       real*8, intent(in) :: eova(n)  ! Erel/A vector, KeV
       real*8, intent(out) :: sigv(n) ! rate coefficient sigma*v, m**3/sec

     end subroutine zstop_sigvz

     subroutine zstop_sigvz_r4(izneut,zimp,eova,n,sigv)
       implicit NONE

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       real, intent(in) :: zimp       ! Z of impurity, .ge.3
       integer, intent(in) :: n       ! vector size
       real, intent(in) :: eova(n)    ! Erel/A vector, KeV
       real, intent(out) :: sigv(n)   ! rate coefficient sigma*v, m**3/sec

     end subroutine zstop_sigvz_r4

  end interface

  interface sigvte_ioniz

     ! ionization of neutrals by electron impact
     ! rate coefficients <sigma*v> averaged over Maxwellian electron
     ! distribution characterized by temperature Te (KeV).
     !
     ! neutral atoms:  H or He or Li
     !                 (but H cross section data is used for Li)

     subroutine sigvte_ioniz(izneut,te,n,sigv)

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       integer, intent(in) :: n       ! vector size
       real*8, intent(in) :: te(n)    ! Te, electron temperature, KeV
       real*8, intent(out) :: sigv(n) ! rate coefficient sigma*v, m**3/sec

     end subroutine sigvte_ioniz

     subroutine sigvte_ioniz_r4(izneut,te,n,sigv)

       integer, intent(in) :: izneut  ! Z of neutral atom (1,2 or 3)
       integer, intent(in) :: n       ! vector size
       real, intent(in) :: te(n)      ! Te, electron temperature, KeV
       real, intent(out) :: sigv(n)   ! rate coefficient sigma*v, m**3/sec

     end subroutine sigvte_ioniz_r4

  end interface

  !------------------ Atomic Physics: impact ionization & charge exchange
  !
  !  interactions of light neutral atoms {H0,He0,Li0} with fully stripped
  !  light ions {H+,He++,Li+++} (caution: Li cross section data not complete)
  !
  !  note: in these routines, "charge exchange" means "neutralizing
  !  charge exchange", that is, the term refers only to reactions
  !  which have a neutral atom product; ion-ion charge exchange reactions
  !  are not considered, and, neutral-ion charge exchage reactions which
  !  do not fully neutralize the ion are considered ionization events.
  !
  !  This is the right logic for the intended application:  neutral beam
  !  stopping or neutral gas transport in hot tokamak core plasmas;
  !  partially ionized light ions are assumed to be magnetically confined
  !  and quickly fully stripped by subsequent charged particle collisions.
  !
  !  Thus:  (He0,H+) -> (He+,H0) counts as charge exchange
  !         (He++,H0) -> (He+,H+) counts as ionization
  !         the rate coefficent for ionization of H0 by He++ includes
  !         the latter reaction in a sum.
  !
  !  Usually, the beam-target tables are used, because the usual physical
  !  situation under consideration is a single neutral atom ("beam") with
  !  energy per nuclean Eb/Ab KeV/AMU, entering a maxwellian ion population
  !  ("target") with temperature per nucleon Ti/Ai KeV/AMU.  However, 
  !  non-maxwellian-averaged "cold target" or "colliding beam" sigma*v
  !  is also available.  But sometimes, the viewpoint is of a single ion
  !  entering a neutral population that is treated as if it were Maxwellian
  !  although in tokamak plasmas this would only be a rough approximation.
  !
  !     use hatom_btsigv for information on beam-target impact ionization
  !         and neutralizing charge exchange reactions:
  !             <sigma*v>   m**3/sec (Maxwellian avg <sigma*v>(Eb/Ab,Ti/Ai))
  !                         can be charge exchange (CX) or 
  !                         impact ionization (II).
  !
  !             <Eav>       charge exchange: average energy sampled from
  !                         Maxwellian, KeV, <Eav> vs. (Eb/Ab,Ti/Ai)
  !                         (can use to refine estimate of cx power
  !                          exchanged between ion and neutral populations)
  !
  !             <fd> = <vb.vtarg>/(|vb|*vth) vs. (Eb/Ab,Ti/Ai) 
  !                         (vth = sqrt(Ti/Ai)*conversion to units of v's)
  !                         for neutralizing charge exchange reaction:
  !                         normalized average velocity (relative to
  !                         incident beam) sampled from target Maxwellian.
  !                         (can use to refine estimate of cx momentum
  !                          exchanged between ion and neutral populations)
  !
  !     use hatom_btsigv argument "irtype" to select the desired output
  !     use hatom_btsigv argument "beamchrg" to indicate
  !       (neutral beam, ion target distribution) ..or..
  !       (ion beam, neutral target distribution)
  !
  !     use hatom_sigv for raw sigma*v as a function of Erel/A

  interface hatom_btsigv

     subroutine hatom_btsigv(irtype,beamchrg,eabeam,tatarg,n,izbeam,iztarg, &
          btsigv, istat )

       implicit NONE

       integer, intent(in) :: irtype    ! reaction/output type code:
                                        ! use: CX=1, II=2, EAV=3, FD=4

       integer, intent(in) :: beamchrg  ! beam type:
                                        ! use: NEUTRAL=1, ION=2

       integer, intent(in) :: n         ! **vector size**
       real*8, intent(in) :: eabeam(n)  ! E/A, KeV/nucleon, of beam
       real*8, intent(in) :: tatarg(n)  ! T/A, KeV/nucleon, of target

       integer, intent(in)  :: izbeam   ! Z of beam species (1 2 or 3)
       integer, intent(in)  :: iztarg   ! Z of target species (1 2 or 3)

       !  **result**

       real*8, intent(out) :: btsigv(n) ! <sigma*v>, m**3/sec  **vector**
                                        ! or <Eav>, KeV
                                        ! or <fd>, dimensionless

       integer, intent(out) :: istat    ! completion code; 0 = normal

       !  istat = 1:  beamchrg argument invalid
       !  istat = 2:  irtype argument invalid
       !  istat = 3:  izbeam or iztarg invalid

     end subroutine hatom_btsigv

     subroutine hatom_btsigv_r4(irtype,beamchrg,eabeam,tatarg,n,izbeam,iztarg,&
          btsigv, istat )

       implicit NONE

       integer, intent(in) :: irtype    ! reaction/output type code:
                                        ! use: CX=1, II=2, EAV=3, FD=4

       integer, intent(in) :: beamchrg  ! beam type:
                                        ! use: NEUTRAL=1, ION=2

       integer, intent(in) :: n         ! **vector size**
       real, intent(in) :: eabeam(n)    ! E/A, KeV/nucleon, of beam
       real, intent(in) :: tatarg(n)    ! T/A, KeV/nucleon, of target

       integer, intent(in)  :: izbeam   ! Z of beam species (1 2 or 3)
       integer, intent(in)  :: iztarg   ! Z of target species (1 2 or 3)

       !  **result**

       real, intent(out) :: btsigv(n)   ! <sigma*v>, m**3/sec  **vector**
                                        ! or <Eav>, KeV
                                        ! or <fd>, dimensionless

       integer, intent(out) :: istat    ! completion code; 0 = normal

       !  istat = 1:  beamchrg argument invalid
       !  istat = 2:  irtype argument invalid
       !  istat = 3:  izbeam or iztarg invalid

     end subroutine hatom_btsigv_r4

  end interface

  interface hatom_sigv

     subroutine hatom_sigv(irtype,Eova,n,izneut,izchrg, sigv, istat)

       implicit NONE

       integer, intent(in) :: irtype    ! reaction type code:
                                        ! use: CX=1, II=2

       integer, intent(in) :: n         ! **vector size**
       real*8, intent(in) :: EovA(n)    ! Erel/A, KeV/nucleon, of collision

       integer, intent(in)  :: izneut   ! Z of neutral species (1 2 or 3)
       integer, intent(in)  :: izchrg   ! Z of ion species (1 2 or 3)

       !  **result**

       real*8, intent(out) :: sigv(n)   ! sigma*v result(s), m**3/sec

       integer, intent(out) :: istat    ! completion code; 0 = normal

       !  istat = 2:  irtype argument invalid
       !  istat = 3:  izneut or izchrg invalid

     end subroutine hatom_sigv

     subroutine hatom_sigv_r4(irtype,Eova,n,izneut,izchrg, sigv, istat)

       implicit NONE

       integer, intent(in) :: irtype    ! reaction type code:
                                        ! use: CX=1, II=2

       integer, intent(in) :: n         ! **vector size**
       real, intent(in) :: EovA(n)      ! Erel/A, KeV/nucleon, of collision

       integer, intent(in)  :: izneut   ! Z of neutral species (1 2 or 3)
       integer, intent(in)  :: izchrg   ! Z of ion species (1 2 or 3)

       !  **result**

       real, intent(out) :: sigv(n)     ! sigma*v result(s), m**3/sec

       integer, intent(out) :: istat    ! completion code; 0 = normal

       !  istat = 2:  irtype argument invalid
       !  istat = 3:  izneut or izchrg invalid

     end subroutine hatom_sigv_r4

  end interface

  !------------------ Atomic Physics: (H+,e-) -> H0 recombination

  interface sigvte_reco

     subroutine sigvte_reco(te,n,sigv)

       !  e-,H+ --> H0
       !  recombination <sigma*v>(Te)
       !  via table lookup

       integer, intent(in) :: n     ! vector size
       real*8, intent(in) :: te(n)  ! electron temperature(s)  KeV

       real*8, intent(out) :: sigv(n) ! <sigma*v> value(s) returned  m**3/sec

     end subroutine sigvte_reco

     subroutine sigvte_reco_r4(te,n,sigv)

       !  e-,H+ --> H0
       !  recombination <sigma*v>(Te)
       !  via table lookup

       integer, intent(in) :: n     ! vector size
       real, intent(in) :: te(n)    ! electron temperature(s)  KeV

       real, intent(out) :: sigv(n) ! <sigma*v> value(s) returned  m**3/sec

     end subroutine sigvte_reco_r4

  end interface

  !================================================
  !  Fusion reactions
  !    --thermonuclear rate coefficients (vs. Temperature)
  !
  !    --beam-target rate coefficients (vs. beam energy, target Temperature)
  !
  !    --beam-beam rate coefficients (vs. beam energy, gyro-variation 
  !                                      fraction in target frame)
  !
  !    --beam-coldTarget rate coefficients (vs. beam energy, T=0)
  !
  !  reaction designations:
  !
  !  DDp  -- DD fusion --> p,T
  !  DDn  -- DD fusion --> n,He3
  !
  !  TT   -- TT fusion --> 2n,He4
  !
  !  DT   -- DT fusion:  D beam, T target
  !  TD   -- TD fusion:  T beam, D target
  !
  !  D3   -- D-He3 fusion:  D beam, He3 target
  !  3D   -- He3-D fusion:  He3 beam, D target
  !
  !  T3   -- T-He3 fusion:  D beam, T target
  !  3T   -- He3-T fusion:  T beam, T target
  !
  !  caution:  while DT & TD calls are interchangeable when evaluating
  !  thermonuclear rate coefficients, for all other calls the energy is
  !  taken in the reference frame of the target specie, which means the
  !  same energy value will yield a different result depending on which
  !  is the beam specie, and which is the target; this is an issue for
  !  all asymmetric reactions.
  !  
  !------------------ Nuclear Physics:  thermonuclear fusion tables
  !
  !  <<sigma*v>> as a function of ion temperature
  !  a single temperature is assumed to characterize both reagents
  !
  !  there is a separate routine for each fusion reaction
  !  in what follows:
  !

  interface fusn_thermo_DDp

     subroutine fusn_thermo_DDp(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DDp

     subroutine fusn_thermo_DDp_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DDp_r4

  end interface

  interface fusn_thermo_DDn

     subroutine fusn_thermo_DDn(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DDn

     subroutine fusn_thermo_DDn_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DDn_r4

  end interface

  interface fusn_thermo_DT

     subroutine fusn_thermo_DT(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DT

     subroutine fusn_thermo_DT_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_DT_r4

  end interface

  interface fusn_thermo_TD

     subroutine fusn_thermo_TD(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_TD

     subroutine fusn_thermo_TD_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_TD_r4

  end interface

  interface fusn_thermo_TT

     subroutine fusn_thermo_TT(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_TT

     subroutine fusn_thermo_TT_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_TT_r4

  end interface

  interface fusn_thermo_D3

     subroutine fusn_thermo_D3(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_D3

     subroutine fusn_thermo_D3_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_D3_r4

  end interface

  interface fusn_thermo_3D

     subroutine fusn_thermo_3D(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_3D

     subroutine fusn_thermo_3D_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_3D_r4

  end interface

  interface fusn_thermo_T3

     subroutine fusn_thermo_T3(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_T3

     subroutine fusn_thermo_T3_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_T3_r4

  end interface

  interface fusn_thermo_3T

     subroutine fusn_thermo_3T(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: tplasma(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_3T

     subroutine fusn_thermo_3T_r4(tplasma,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: tplasma(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <<sigma*v>> value(s)

     end subroutine fusn_thermo_3T_r4

  end interface

  !------------------ Nuclear Physics:  beam-target fusion tables
  !
  !  the beam energy is in the rest frame of the maxwellian target
  !  the target temperature characterizes the maxwellian
  !
  !  reagent designations:  D = Deuterium T = Tritium 3 = Helium-3
  !  first symbol = beam specie, 2nd symbol = target specie
  !

  interface fusn_btsigv_DDp

     subroutine fusn_btsigv_DDp(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DDp

     subroutine fusn_btsigv_DDp_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DDp_r4

  end interface

  interface fusn_btsigv_DDn

     subroutine fusn_btsigv_DDn(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DDn

     subroutine fusn_btsigv_DDn_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DDn_r4

  end interface

  interface fusn_btsigv_DT

     subroutine fusn_btsigv_DT(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DT

     subroutine fusn_btsigv_DT_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_DT_r4

  end interface

  interface fusn_btsigv_TD

     subroutine fusn_btsigv_TD(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_TD

     subroutine fusn_btsigv_TD_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_TD_r4

  end interface

  interface fusn_btsigv_TT

     subroutine fusn_btsigv_TT(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_TT

     subroutine fusn_btsigv_TT_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_TT_r4

  end interface

  interface fusn_btsigv_D3

     subroutine fusn_btsigv_D3(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_D3

     subroutine fusn_btsigv_D3_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_D3_r4

  end interface

  interface fusn_btsigv_3D

     subroutine fusn_btsigv_3D(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_3D

     subroutine fusn_btsigv_3D_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_3D_r4

  end interface

  interface fusn_btsigv_T3

     subroutine fusn_btsigv_T3(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_T3

     subroutine fusn_btsigv_T3_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_T3_r4

  end interface

  interface fusn_btsigv_3T

     subroutine fusn_btsigv_3T(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(in) :: ttarget(n)   ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_3T

     subroutine fusn_btsigv_3T_r4(ebeam,ttarget,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(in) :: ttarget(n)   ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_btsigv_3T_r4

  end interface

  !------------------ Nuclear Physics:  beam-beam fusion tables
  !
  !  These routines do table lookup in gyro-averaged fusion <sigma*v>
  !  tables.  These tables are useful for computing beam-beam or 
  !  general fast-ion-fast-ion fusion, where two fast ion distribution
  !  functions are being convolved.  The distribution functions have
  !  the form f(vperp,vpll) where vpll is in the direction of the local
  !  B field; the fast ions are gyrating around the field line (i.e. the
  !  direction of vperp gyrates).
  !
  !  The average beam energy is with respect to the reference frame 
  !  of the gyrating target; fvar species the fractional beam energy 
  !  variation in the target frame.  (For more details see the comments
  !  in fpreact/fusn_bbsigv.f90)
  !
  !  reagent designations:  D = Deuterium T = Tritium 3 = Helium-3
  !  first symbol = beam specie, 2nd symbol = target specie
  !

  interface fusn_bbsigv_DDp

     subroutine fusn_bbsigv_DDp(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DDp

     subroutine fusn_bbsigv_DDp_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DDp_r4

  end interface

  interface fusn_bbsigv_DDn

     subroutine fusn_bbsigv_DDn(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DDn

     subroutine fusn_bbsigv_DDn_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DDn_r4

  end interface

  interface fusn_bbsigv_DT

     subroutine fusn_bbsigv_DT(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DT

     subroutine fusn_bbsigv_DT_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_DT_r4

  end interface

  interface fusn_bbsigv_TD

     subroutine fusn_bbsigv_TD(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_TD

     subroutine fusn_bbsigv_TD_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_TD_r4

  end interface

  interface fusn_bbsigv_TT

     subroutine fusn_bbsigv_TT(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_TT

     subroutine fusn_bbsigv_TT_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_TT_r4

  end interface

  interface fusn_bbsigv_D3

     subroutine fusn_bbsigv_D3(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_D3

     subroutine fusn_bbsigv_D3_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_D3_r4

  end interface

  interface fusn_bbsigv_3D

     subroutine fusn_bbsigv_3D(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_3D

     subroutine fusn_bbsigv_3D_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_3D_r4

  end interface

  interface fusn_bbsigv_T3

     subroutine fusn_bbsigv_T3(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_T3

     subroutine fusn_bbsigv_T3_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_T3_r4

  end interface

  interface fusn_bbsigv_3T

     subroutine fusn_bbsigv_3T(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: eav(n)       ! beam energy(s)
       real*8, intent(in) :: fvar(n)      ! temperature(s)
       real*8, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_3T

     subroutine fusn_bbsigv_3T_r4(eav,fvar,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: eav(n)       ! beam energy(s)
       real, intent(in) :: fvar(n)      ! temperature(s)
       real, intent(out) :: answer(n)   ! <sigma*v> value(s)

     end subroutine fusn_bbsigv_3T_r4

  end interface

  !------------------ Nuclear Physics:  cold-target fusion tables
  !
  !  the beam energy is in the rest frame of the cold stationary
  !  target (zero temperature target).
  !
  !  reagent designations:  D = Deuterium T = Tritium 3 = Helium-3
  !  first symbol = beam specie, 2nd symbol = target specie
  !

  interface fusn_coldtarget_DDp

     subroutine fusn_coldtarget_DDp(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DDp

     subroutine fusn_coldtarget_DDp_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DDp_r4

  end interface

  interface fusn_coldtarget_DDn

     subroutine fusn_coldtarget_DDn(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DDn

     subroutine fusn_coldtarget_DDn_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DDn_r4

  end interface

  interface fusn_coldtarget_DT

     subroutine fusn_coldtarget_DT(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DT

     subroutine fusn_coldtarget_DT_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_DT_r4

  end interface

  interface fusn_coldtarget_TD

     subroutine fusn_coldtarget_TD(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_TD

     subroutine fusn_coldtarget_TD_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_TD_r4

  end interface

  interface fusn_coldtarget_TT

     subroutine fusn_coldtarget_TT(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_TT

     subroutine fusn_coldtarget_TT_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_TT_r4

  end interface

  interface fusn_coldtarget_D3

     subroutine fusn_coldtarget_D3(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_D3

     subroutine fusn_coldtarget_D3_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_D3_r4

  end interface

  interface fusn_coldtarget_3D

     subroutine fusn_coldtarget_3D(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_3D

     subroutine fusn_coldtarget_3D_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_3D_r4

  end interface

  interface fusn_coldtarget_T3

     subroutine fusn_coldtarget_T3(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_T3

     subroutine fusn_coldtarget_T3_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_T3_r4

  end interface

  interface fusn_coldtarget_3T

     subroutine fusn_coldtarget_3T(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real*8, intent(in) :: ebeam(n)     ! beam energy(s)
       real*8, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_3T

     subroutine fusn_coldtarget_3T_r4(ebeam,answer,n)

       implicit NONE

       integer, intent(in) :: n           ! vector size
       real, intent(in) :: ebeam(n)     ! beam energy(s)
       real, intent(out) :: answer(n)   ! sigma*v value(s)

     end subroutine fusn_coldtarget_3T_r4

  end interface

  !------------------ Atomic Physics:  impurity ionization, recombination and radiation
  !
  ! The cross sections in this section are in the form <sigma*v*ne>(te,ne) and have
  ! the units
  !       ionization    -> sec-1
  !       recombination -> sec-1
  !       radiation     -> joules/sec
  !
  !       ne = electron density in m-3
  !       te = electron temperature in keV
  !
  ! ionization(n):
  !   This is the rate of ionization of an atom of nuclear charge Z 
  !   due to electron collisions from the charge state +(n-1) to +n  
  !   where  n=1...Z+1.  ionization(Z+1)=0
  !
  ! recombination(n):
  !   This is the rate of recombination of an atom of nuclear charge Z 
  !   due to radiative and dielectronic recombination from the charge 
  !   state +(n-1) to +(n-2)  where  n=1...Z+1.  recombinaton(1)=0
  !
  ! radiation(n):
  !   This is the rate of radiation of an atom of nuclear charge Z
  !   due to electron collisional excitation and optionally bremsstrahlung
  !   in the charge state +(n-1).  Default is no bremsstrahlung.
  !
  ! bremsstrahlung(n):
  !   If bremsstrahlung is NOT included in the radiation(n), it can be called
  !   separately.  If bremsstrahlung IS included in radiation(n), an attempt to
  !   call imptable_brem() or imptable_brem_policy() will cause an exception.
  !
  ! coronal equilibrium:
  ! In addition, a routine is provided to calculate the coronal equilibrium based
  ! on the ionization and recombination rate data.  There is also a simple routine
  ! to return the radiation in (joules/sec) when provided with coronal equilibrium
  ! and radiation rate data.
  !
  interface
     ! -- interface --
     ! Each element from Z=1 to Z=99 can have one C++ Impreaction object
     ! associated with it for calculating the impurity rates.  The C++ object
     ! is constructed on first use of the object using standard defaults
     ! in the construction process.  The defaults can be modified with these
     ! subroutines:
     !
     subroutine imptable_def_option(iopt)
       integer, intent(in) :: iopt    ! option chooses the source of the impurity data
                                      ! 0 -> ADPAK without buffering
     end subroutine imptable_def_option

     subroutine imptable_def_brem(ibrem)
       integer, intent(in) :: ibrem   ! 0 -> do NOT include bremsstrahlung in radiation
                                      !      radiation = line radiation only (Default)
                                      ! 1 -> include bremsstrahlung in radiation
                                      !      radiation = line+bremsstrahlung radiation
     end subroutine imptable_def_brem

     !
     ! ... or the object can be built or rebuilt with defaults
     ! supplied in the arguments to this subroutine,
     !
     subroutine imptable_build(nucz, iopt, ibrem)
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iopt    ! option for choosing source of data
       integer, intent(in) :: ibrem   ! option for including or not bremsstrahlung
     end subroutine imptable_build

     !
     ! this subroutine writes out a full description of the
     ! underlying ImpReaction C++ object to the terminal for
     ! infomational or debugging purposes
     !
     subroutine imptable_print(nucz)
       integer, intent(in) :: nucz    ! atomic number Z of element
     end subroutine imptable_print
     
     !
     ! the ionization, recombination and radiation calculations each
     ! have range policies which can be modified separately or
     ! as a group
     !
     subroutine imptable_ioniz_policy(nucz, iaxis, pmin, pmax)
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iaxis   ! 0 -> Te, electron temperature
                                      ! 1 -> Ne, electron density
       integer, intent(in) :: pmin    ! policy to apply when minimum range exceeded
       integer, intent(in) :: pmax    ! policy to apply when maximum range exceeded
     end subroutine imptable_ioniz_policy

     subroutine imptable_recom_policy(nucz, iaxis, pmin, pmax)
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iaxis   ! 0 -> Te, electron temperature
                                      ! 1 -> Ne, electron density
       integer, intent(in) :: pmin    ! policy to apply when minimum range exceeded
       integer, intent(in) :: pmax    ! policy to apply when maximum range exceeded
     end subroutine imptable_recom_policy

     subroutine imptable_rad_policy(nucz, iaxis, pmin, pmax)
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iaxis   ! 0 -> Te, electron temperature
                                      ! 1 -> Ne, electron density
       integer, intent(in) :: pmin    ! policy to apply when minimum range exceeded
       integer, intent(in) :: pmax    ! policy to apply when maximum range exceeded
     end subroutine imptable_rad_policy

     subroutine imptable_brem_policy(nucz, iaxis, pmin, pmax)
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iaxis   ! 0 -> Te, electron temperature
                                      ! 1 -> Ne, electron density
       integer, intent(in) :: pmin    ! policy to apply when minimum range exceeded
       integer, intent(in) :: pmax    ! policy to apply when maximum range exceeded
     end subroutine imptable_brem_policy

     subroutine imptable_policy(nucz, iaxis, pmin, pmax)
       ! -- apply to ionization, recombination and radiation --
       integer, intent(in) :: nucz    ! atomic number Z of element
       integer, intent(in) :: iaxis   ! 0 -> Te, electron temperature
                                      ! 1 -> Ne, electron density
       integer, intent(in) :: pmin    ! policy to apply when minimum range exceeded
       integer, intent(in) :: pmax    ! policy to apply when maximum range exceeded
     end subroutine imptable_policy
  end interface

  !
  ! the impurity rates are computed using the following vector based routines where
  !
  ! input:
  !   nucz    -> nuclear charge Z of element
  !   nvec    -> number of evaluations of the rates
  !   te(nmax)-> array containing electron temperature in keV  nvec<=nmax
  !   ne(nmax)-> array containing electron density in m-3      nvec<=nmax
  !   mmax    -> size of first dimension of result array       (nucz+1)<=mmax -- checked
  ! output:
  !   result(mmax,nvec) -> contains the rate coefficients in the form
  !                        result(i,j) = rate for charge state (i-1) for te(j),ne(j)
  interface imptable_ioniz
     ! -- compute ionization rate --
     subroutine imptable_ioniz_r4(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: te(nvec)          ! electron temperature in keV
       real,    intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real,    intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_ioniz_r4

     subroutine imptable_ioniz_r8(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: te(nvec)          ! electron temperature in keV
       real*8,  intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real*8,  intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_ioniz_r8
  end interface

  interface imptable_recom
     ! -- compute recombination rate --
     subroutine imptable_recom_r4(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: te(nvec)          ! electron temperature in keV
       real,    intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real,    intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_recom_r4

     subroutine imptable_recom_r8(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: te(nvec)          ! electron temperature in keV
       real*8,  intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real*8,  intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_recom_r8
  end interface

  interface imptable_rad
     ! -- compute radiation rate --
     subroutine imptable_rad_r4(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: te(nvec)          ! electron temperature in keV
       real,    intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real,    intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_rad_r4

     subroutine imptable_rad_r8(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: te(nvec)          ! electron temperature in keV
       real*8,  intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real*8,  intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_rad_r8
  end interface

  interface imptable_brem
     ! -- compute radiation rate --
     subroutine imptable_brem_r4(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: te(nvec)          ! electron temperature in keV
       real,    intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real,    intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_brem_r4

     subroutine imptable_brem_r8(nucz, nvec, te, ne, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: te(nvec)          ! electron temperature in keV
       real*8,  intent(in)  :: ne(nvec)          ! electron density in m-3
       integer, intent(in)  :: mmax              ! dimensioning for result
       real*8,  intent(out) :: result(mmax,nvec) ! resulting rate as (charge_state+1, Te/Ne index)
     end subroutine imptable_brem_r8
  end interface
  !
  ! ---- coronal equilibrium ---
  ! the rate arrays used as input to the coronal equilibrium functions have the 
  ! same format as the rates returned in the previous functions
  !
  !   nucz    -> nuclear charge Z of element
  !   nvec    -> number of evaluations of the rates
  !   ioniz(mmax,nvec)-> array containing ionization rate (sec-1)
  !   recom(mmax,nvec)-> array containing recombination rate (sec-1)
  !   rad(mmax,nvec)  -> array containing radiation rate (joules/sec)
  !   mmax    -> size of first dimension of arrays       (nucz+1)<=mmax -- checked
  ! input/output:
  !   coron(mmax,nvec) -> contains the coronal equilibrium normalized for a sum of 1
  !                       coron(i,j) = fraction of particles in charge state (i-1) for 
  !                                     rates ioniz(*,j),recom(*,j)
  ! output:
  !   result(nvec) -> contains the total radiation associated with the coronal equilibrium
  !                   coron(mmax,nvec) and radiation rate rad(mmax,nvec) in (joules/sec)
  !                   for the nvec sets of charge state data.
  !
  interface coronal
     ! -- coronal equilibrium --
     subroutine impreaction_coronal_r4(nucz, nvec, ioniz, recom, mmax, coron)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: ioniz(mmax,nvec)  ! ionization rate as (charge_state+1, Te/Ne index)
       real,    intent(in)  :: recom(mmax,nvec)  ! recombination rate as (charge_state+1, Te/Ne index)
       integer, intent(in)  :: mmax              ! dimensioning for arrays
       real,    intent(out) :: coron(mmax,nvec)  ! coronal equilibrium as a fraction of the particles
                                                 ! in each charge state normalized for a sum of 1 
                                                 ! (charge_state+1, Te/Ne index)
     end subroutine impreaction_coronal_r4
       
     subroutine impreaction_coronal_r8(nucz, nvec, ioniz, recom, mmax, coron)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: ioniz(mmax,nvec)  ! ionization rate as (charge_state+1, Te/Ne index)
       real*8,  intent(in)  :: recom(mmax,nvec)  ! recombination rate as (charge_state+1, Te/Ne index)
       integer, intent(in)  :: mmax              ! dimensioning for arrays
       real*8,  intent(out) :: coron(mmax,nvec)  ! coronal equilibrium as a fraction of the particles
                                                 ! in each charge state normalized for a sum of 1 
                                                 ! (charge_state+1, Te/Ne index)
     end subroutine impreaction_coronal_r8
  end interface

  interface coronal_rad
     ! -- coronal equilibrium radiation --
     subroutine impreaction_coronal_rad_r4(nucz, nvec, coron, rad, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real,    intent(in)  :: coron(mmax,nvec)  ! coronal equilibrium as (charge_state+1, Te/Ne index)
       real,    intent(in)  :: rad(mmax,nvec)    ! radiation rate as (charge_state+1, Te/Ne index)
       integer, intent(in)  :: mmax              ! dimensioning for arrays
       real,    intent(out) :: result(nvec)      ! total radiation in (joules/sec) for each Te/Ne index
     end subroutine impreaction_coronal_rad_r4

     subroutine impreaction_coronal_rad_r8(nucz, nvec, coron, rad, mmax, result)
       integer, intent(in)  :: nucz              ! atomic number Z of element
       integer, intent(in)  :: nvec              ! number of rate evaluations
       real*8,  intent(in)  :: coron(mmax,nvec)  ! coronal equilibrium as (charge_state+1, Te/Ne index)
       real*8,  intent(in)  :: rad(mmax,nvec)    ! radiation rate as (charge_state+1, Te/Ne index)
       integer, intent(in)  :: mmax              ! dimensioning for arrays
       real*8,  intent(out) :: result(nvec)      ! total radiation in (joules/sec) for each Te/Ne index
     end subroutine impreaction_coronal_rad_r8
  end interface
end module fpreact_calls

------------------------------------------------------------------
 VI.  Available data
------------------------------------------------------------------

The PREACT system currently supports these atomic reactions
(note, Lithium data is incomplete; current state of Lithium data
is summarized in fpreact/hatom_mod.f90).

      -----------------------------------------------------------------
      reaction tag     reaction type             description
      -----------------------------------------------------------------
CX:   H->H(cx)         charge exchange           hydrogen-hydrogen
      H+->He0x         charge exchange           H+, helium neutral
      He++>Hex         charge exchange           helium-helium
      H+->Li0x         charge exchange           H+, lithium
      He++>Lix         charge exchange           helium-lithium
      Li+++>Lx         charge exchange           lithium-lithium

II:   H->H(ii)         (impact) ionization       hydrogen-hydrogen
      H+->He0i         (impact) ionization       H+, helium neutral
      He++>H0i         ionization (by ii,cx)     He++, hydrogen neutral
      He++>Hei         (impact) ionization       helium-helium
      H+->Li0i         (impact) ionization       H+, lithium
      He++>Lii         ionization (by ii,cx)     helium-lithium
      Li+++->H         (impact) ionization       lithium-hydrogen
      Li+++>He         (impact) ionization       lithium-helium
      Li+++>Li         (impact) ionization       lithium-lithium

EI:   recombine        electron <sigma*v>        e-,H+ -> H0 + photon
      i:e->H0          election impact ioniz.    e-,H0 -> H+ & 2e-
      i:e->He0         election impact ioniz.    e-,He0 -> He+ & 2e-
      i:e->Li0         election impact ioniz.    e-,Li0 -> Li+ & 2e-

SV:   C+6->H           ionization (by ii,cx)     H stopping rate on C+6
      C+6->He          ionization (by ii,cx)     He stopping rate on C+6
      C+6->Li          ionization (by ii,cx)     Li stopping rate on C+6
      O+8->H           ionization (by ii,cx)     H stopping rate on O+8
      O+8->He          ionization (by ii,cx)     He stopping rate on O+8
      O+8->Li          ionization (by ii,cx)     Li stopping rate on O+8

      -----------------------------------------------------------------

as well as the following nuclear reactions:

      -----------------------------------------------------------------
      reaction tag     reaction type             description
      -----------------------------------------------------------------
FS:   D->D(n)          fusion                    DD neutron branch
      D->D(p)          fusion                    DD proton branch
      D->T             fusion                    D beam on T target
      T->D             fusion                    T beam on D target
      D->He3           fusion                    D beam on He3 target
      He3->D           fusion                    He3 beam on D target
      T->T             fusion                    T on T
      T->He3           fusion                    T beam on He3 target
      He3->T           fusion                    He3 beam on T target
      -----------------------------------------------------------------

and Impurity ionization, recombination and radiation rates:

      -----------------------------------------------------------------
      Nuclear Z        Data Source               description
      -----------------------------------------------------------------
      1-57, 61-99      ADPAK_DIRECT              unbuffered data from ADPAK
                                                 module.  Z=58,59,60 has some
                                                 problems with neutral radiation
                                                 numerics so they are forbidden.



Quantities are measured in the following units:

     ------------------------------------------------------------------
     quantity                                unit
     ------------------------------------------------------------------
     cross section (sigma)                    m^2
     relative velocity (vrel)                 m/s
     reaction rate (sigma*v)                  m^3/s
     energy (E), temperature (T)              keV (per AMU)
     impurity ionization rate (simga*v*ne)    1/s
     impurity recombination rate (simga*v*ne) 1/s
     impurity radiation rate (simga*v*ne)     joule/s
     ------------------------------------------------------------------

------------------------------------------------------------------
 VII.  Simple Examples
------------------------------------------------------------------

By linking the PREACT library 'libpreact.a' to your C++ code, you can create a
reaction 'object' using the syntax:

  XXReaction identifier("tag");

where 'XX' is either CX (for charge exchange), II (for ionization) or FS (for
fusion), and 'tag' is one of the reaction tags listed in the tables above.  
You may then evaluate cross sections, relative velocities, reaction rates, and
various other characteristics of the reaction using the public methods
provided in the header files cxreaction.h, iireaction.h, and fsreaction.h (in
the directory include/preact).  For example, to evaluate the <sigma*v> 
(beam to warm target) average of the reaction H->H(cx) at the points (E, T) =
(10 keV, 11 keV), (12 keV, 13 keV), and (14 keV, 15 keV), one would write:

  CXReaction hcx("H->H(cx)");                  // initialization
  const int n = 3;                             // # of points
  fp_64 E[] = { 10, 12, 14 };                  // E-coordinates
  fp_64 T[] = { 11, 13, 15 };                  // T-coordinates
  fp_64 f[n];                                  // output array
  hcx.warmTarget_sigmaTimesV(E, T, f, n);      // evaluate (fill 'f')

The reaction class constructors have 2 optional arguments in addition to the
mandatory 'tag' argument: 'errlo' and 'errhi'.  These determine how the
interpolation routines will handle out-of-range input coordinates (default
settings are marked with an asterisk):

     ------------------------------------------------------------------
     'errlo' value     out-of-range low result
     ------------------------------------------------------------------
     IGNORE            minimum domain value used, warning supressed
     WARN (*)          minimum domain value used, warning issued
     HALT              error, program halted
     ------------------------------------------------------------------

     ------------------------------------------------------------------
     'errhi' value     out-of-range high result
     ------------------------------------------------------------------
     IGNORE            maximum domain value used, warning supressed
     WARN              maximum domain value used, warning issued
     HALT (*)          error, program halted
     ------------------------------------------------------------------

Note: if you use the preact f77 interface directly, the 'ierrlo' and 
'ierrhi' arguments of the cx_init, ii_init, and fs_init F77 routines 
*must* be passed (i.e. they are not optional like 'errlo' and 'errhi'
are in the C++ constructor).  However, it is recommended to use fpreact
instead; fpreact hides these details from the user.

An example of fortran preact coding follows:

  integer, parameter :: iwarn=1,ihalt=2
  integer icd, ihcx, icode, cx_init                ! declarations

  icd = icode('H->H(cx)')                          ! get icode for reaction
  ihcx = cx_init(icd, iwarn, ihalt)                ! init reaction, get handle
  call cx_warmtarget_sigmatimesv(ihcx, E, T, f, n) ! evaluate (fill array 'f')

A more detailed working example can be seen in the initialization subroutine
contained in the private module fpreact/hatom_mod.f90.

A maximum of 100 calls are allowed to each of the three initialization routines
cx_init, ii_init, and fs_init.

Methods are provided in the C++ and F77 interfaces for returning the range of
each dimension in the interpolation tables, so that the client program may
ensure that all coordinates are within the legal range before they are passed
to an interpolation method.  Alternatively, the preact/fpreact error handling
policy can be allowed to execute.

Impurity Rates
--------------
The C++ code for the impurity rates is setup slightly differently then the other 
reactions in preact.  The fwrap template class, which is instantiated to ap_32
and ap_64 for single and double precision array data, is used extensively to 
pass multidimensional data through the inpurity rate reaction interfaces.
As an example of using this interface,

    ImpReaction r(6) ;          // build carbon reaction
    ap_32 xarg(2), result(7) ;  // construct single precision arrays to hold
                                // one set of Te,Ne arguments and a rate result
    xarg(0) = 10. ;             // Te in keV
    xarg(1) = 1.e19 ;           // Ne in m-3
    r.ioniz()(xarg,result) ;    // fill result array with ionization rate data
    cout << result << endl ;    // write out result array
    cout << result(3) << endl ; // ionization rate for charge state +3
    cout << r << endl ;         // LOTS of info about this reaction object

alternatively, you could use a predefined table of ImpReaction objects for
extracting rate data,

    ap_32 xarg(2), result(7) ;  // same as before
    xarg(0) = 10. ;             // Te in keV
    xarg(1) = 1.e19 ;           // Ne in m-3
    ImpReactionTable::Element(6)->ioniz()(xarg,result) ;
    cout << result << endl ;    // write out result array
    
There are also vector and double precision interfaces for each reaction.

The default is to NOT include bremsstrahlung radiation with the radiation
rate.  It is available as a separate React.  If you prefer including
bremsstrahlung with the ImpReaction::rad() reaction,

    ImpReaction r(6) ;          // build carbon reaction
    ImpReact_Rad::cast(r.rad())->set_brem(true) ;  // yes, we want bremsstrahlung

or if your using the table objects,

    ImpReactionTable::build(6, ImpReaction::ADPAK_DIRECT, true) ;

which also specifies the source of impurity rate data as coming from
ADPAK without any buffering (only choice for now).

To get the coronal equilibrium,

     ap_32 rioniz(7), rrecom(7), rcoron(7) ;
     r.ioniz()(xarg, rioniz) ;
     r.recom()(xarg, rrecom) ;
     ImpReaction::coronal(rioniz, rrecom, rcoron) ;
     cout << rcoron << endl ;

The React objects are picky about the sizes of the arguments and resulting
ap_32, ap_64 arrays.  The ap_32, ap_64 arrays have a fixed physical
size in each dimension but the logical size can be changed as follows,
     
     ap_32 rbrem(100) ;    // too large for carbon
     rbrem.set_size(0,7) ; // set dimension 0 to size 7
     r.brem(rbrem) ;       // ok now


For further examples of how to use the PREACT module, see
	- testpreact.cpp   -- a C++ source file
	- testf77layer.f   -- a Fortran-77 source file  
        - fpreact_test.f90 -- a Fortran-90 driver using the fpreact
                              programming interface.
        - f77imp.cpp       -- contains a preact_impurity_test() subroutine
                              demonstrating the C++ ImpReaction and 
                              ImpReactionTable classes

all are available via the web home page:
http://w3.pppl.gov/NTCC/PREACT/

-------------------------------------------------------------------------------
 VIII. KNOWN PROBLEMS
-------------------------------------------------------------------------------

The Li rate database is incomplete, as detailed in fpreact/hatom_mod.f90.

The impurity radiation rates give NANs for elements 58-60 so these elements
are not available.

If a problem arises that is not addressed in the documentation, send an email
to TRANSP Support (transp_support@pppl.gov).

Last documentation update:  dmccune -- 3 July 2001

-------------------------------------------------------------------------------
 IX. References
-------------------------------------------------------------------------------

These are the sources of cross section data used to form preact's 
sigma*v tables.

Cross-sections (atomic physics)
===============================

C.F. Barnett, H.T. Hunter, M.I. Kirkpatrick, I. Alvarez, C. Cisneros,
R.A. Phaneuf, Atomic Data for Fusion, Vol. 1, Collisions of H, He, and Li
Atoms and Ions with Atoms and Molecules, ORNL-6086/V1 (July 1990).

R.A. Phaneuf, R.K. Janev, M.S. Pindzola, Atomic Data for Fusion, Vol. 5,
Collisions of Carbon and Oxygen Ions with Electrons, H, H2, and He, 
ORNL-6090/V5 (5th volume of ORNL-6086) (Feb. 1987).

R.K. Janev, W.D. Langer, K. Evans Jr., D.E. Post, Jr., Elementary Processes
in Hydrogen-Helium Plasmas, Springer-Verlag, 1987

Cross-sections (nuclear fusion)
===============================

H-S. Bosch, Review of Data and Formulas for Fusion Cross-sections, 
IPP I/252 (Sept 1990).

ADPAK references
================
C     A selection of references from the ADPAK module
C
C     1) POST ET AL., PPPL-1352 (CORRECTED)
C     2) LOKKE AND GRASBERGER, LLL REPORT UCRL-52276 (CORRECTED)
C     3) H. MAYER, 'METHODS OF OPACITY CALCULATIONS', LOS ALAMOS
C        SCIENTIFIC  LABORATORY LA-647 (1947).
C     4) XSNQ LISTING
C     5) R. MORE 'ATOMIC PHYSICS IN INERTIAL CONFINEMENT FUSION -
C        PART I' LLL REPORT UCRL-84991 (1981) (TO APPEAR
C        IN 'APPLIED ATOMIC COLLISION PHYSICS', VOLUME II,
C        ACADEMIC PRESS)
C     6) GRASBERGER, XSNQ - TOKAMAK MEMORANDUM #4, 7/29/76
C     7) GRASBERGER, XSNQ - TOKAMAK MEMORANDUM #10, 1/5/77
C     8) LOKKE & GRASBERGER, 'XSNQ-U A NON-LTE EMISSION AND
C        ABSORPTION COEFFICIENT SUBROUTINE', LLL REPORT UCRL-52276
C     9) MERTS ET AL., 'THE CALCULATED POWER OUTPUT FROM
C        A THIN IRON-SEEDED PLASMA', LOS ALAMOS REPORT LA-6220-MS
C    10) POST, JENSEN, TARTER, GRASBERGER, LOKKE, 'STEADY STATE
C        RADIATIVE COOLING RATES FOR LOW-DENSITY HIGH-TEMPERATURE
C        PLASMAS', PPPL-1352 (SUB. TO N.F.) (WITH CORRECTIONS)
C    11) SEATON, 'RADIATIVE RECOMBINATION OF HYDROGENIC IONS',
C        MNRAS:119,81 (1959)
C    12) COX AND TUCKER, 'IONIZATION EQUILIBRIUM AND RADIATIVE
C        COOLING OF A LOW-DENSITY PLASMA', AP.J.:157,1157 (1969)
C    13) GRASBERGER, XSNQ - TOKAMAK MEMORANDUM #1, 2/11/76
