#!/bin/bash
function usage ()
{
   cat<<EOF
 autoxc - script to autogenerate Fortran code for Electron Density Functionals
          and their derivatives using Maxima

 Usage:

    $0 [-o <source-file>] <functional>.max

 The Autoxc script takes a file specifying an electron density functional 
 and invokes Maxima [1] to generate expressions for the functional itself
 and its partial derivatives up to 3rd order. Subsequently Maxima transforms
 the expressions into Fortran code. 

 The script is based on the idea published by Strange et al. [2]. However,
 the dfauto script they published requires Maple [3] which is inconvenient
 for free software projects because of the commercial licensing. Hence
 this is a complete re-implementation of the approach.

 As a little extra the file containing the functional may define two 
 special strings:
 - reference : the literature reference of the functional (default
               "unpublished")
 - doi       : the DOI of the paper (default "unpublished")
 These variables are used to add the reference and DOI to the Doxygen
 documentation of the generated source code.

 The file containing the functional may specify three different expression:
 - f : a correlation functional term
 - g : an exchange functional term
 - G : a limiting expression for the limit rho_s -> 0
 These expressions should be specified as
 - f(zeta,rho_a,rho_b,rho,sigma_aa,sigma_ab,sigma_bb,sigma,tau_a,tau_b,tau)
 - g(rho_s,sigma_ss,tau_s)
 - G(rho_s,sigma_ss,tau_s,tau_u)
 where "s" refers to one spin-channel and then "u" refers to the other one,
 i.e. if "u" refers to the alpha spin-channel then "u" refers to the beta
 one and vice versa.
 The script will substitute
 - rho   = rho_a + rho_b
 - zeta  = (rho_a - rho_b) / rho
 - sigma = sigma_aa + 2 * sigma_ab + sigma_bb
 - tau   = tau_a + tau_b
 Given this information the total functional is defined as:

   When rho_a and rho_b > 0.0d0

     - K = sum(s=(a,b),g(rho_s,sigma_ss,tau_s))
         + f(zeta,rho_a,rho_b,rho,sigma_aa,sigma_ab,sigma_bb,sigma,
             tau_a,tau_b,tau)

   when rho_a > 0.0d0 and rho_b = 0.0d0 and G defined

     - K = g(rho_a,sigma_aa,tau_a)
         + G(rho_a,sigma_aa,tau_a,tau_b)
 
   when rho_a = 0.0d0 and rho_b > 0.0d0 and G defined

     - K = g(rho_b,sigma_bb,tau_b)
         + G(rho_b,sigma_bb,tau_b,tau_a)

 References
 ==========
 
 [1] "Maxima, a Computer Algebra System", Version 5.27.0,
     http://maxima.sourceforge.net/

 [2] R. Strange, F.R. Manby, P.J. Knowles,
     "Automatic code generation in density functional theory",
     Comp. Phys. Commun. 136 (2001) 310,
     DOI: 10.1016/S0010-4655(01)00148-5

 [3] M.B. Monagan, K.O. Geddes, K.M. Heal, G. Labahn, S.M. Vorkoetter,
     J. McCarron, P. DeMarco,
     "Maple 10 Programming Guide",
     Maplesoft, Waterloo ON, Canada, 2005.

$Id$
EOF
}
# Note on the mathematics
# -----------------------
#
# In the expressions for G only the densities and gradients for one
# spin channel are used, but the kinetic energy density for both
# appears.
#
# These expressions are correct because when the density goes to 
# zero so do the gradients of the density, therefore rho_s equals zero
# implies that sigma_ss and sigma_st are also zero.
#
# The proof follows simply from the fact that the density is a non-negative
# expression and hence zero density corresponds to a minimum. At the minimum
# the gradient is zero also.
#
# A similar argument cannot be constructed for the kinetic energy density or
# the Laplacian of the density (which we currently do not use).
#
# Variables in this script
# ------------------------
#
# The revision of autoxc
#
version="$Id$"
version=($version)
revision="${version[1]}, revision ${version[2]} ${version[3]}"
#
revision_rewrap=`./bin/rewrap.py --version`
revision_subr=`./bin/call_subroutine.py --version`
#
# The input file containing the DFT functional specification as a
# Maxima expression
#
inputfile=""
#
# The output file where the source code is written to
#
outputfile=""
#
# The name of the density functional
#
functional_name=""
#
# The intermediate density functional representation file that tells Maxima to
# be relatively quiet
#
f_quiet=""
#
# In the Maxima definitions we will use:
# - f : the correlation part of the functional
# - g : the exchange part of the functional
# - G : the limit of the correlation functional when one of the alpha or beta
#       densities goes to 0 (this expression has an exchange like form)
#
# From the above definitions we will derive:
# - excess      : Is there a special definition for when there is an excess of
#                 alpha- or beta-electron density, i.e. is there a definition
#                 of G?
# - rho_deriv   : Is the functional density dependent?
# - sigma_deriv : Is the functional density gradient dependent?
# - tau_deriv   : Is the functional kinetic energy density dependent?
#
excess=false
rho_deriv=false
sigma_deriv=false
tau_deriv=false
#
# Establish the script path and locations of utilities
# ----------------------------------------------------
#
if [ -f "$0" ] ; then
   # The first item on the command line is an actual file so this script must
   # have been specified including the path.
   script_path="`dirname \"$0\"`"
else
   # The first item on the command line is not a file so this script must have
   # been found in PATH.
   script_path="`which \"$0\"`"
   script_path="`dirname \"$path\"`"
fi
#
# Check the command line
# ----------------------
#
# Are there a reasonable number of arguments?
#
if [ $# -lt 1 ] ; then
  usage
  exit 1
elif [ $# -gt 3 ] ; then
  usage
  exit 1
fi
#
# Go through argument list and pick up the outputfile (optional)
# and the inputfile (required)
#
while getopts "o:" arg ; do
    case $arg in
    o)  outputfile="$OPTARG" ;;
    esac
done
shift $((OPTIND - 1))
inputfile="$1"
#
# If no outputfile was specified generate the outputfile from the inputfile
# by replacing the .max extension with .F
#
if [ "x$outputfile" == "x" ] ; then
  outputfile=`echo "$inputfile" | sed 's/\.max/.F/'`
fi
#
# Work out a sensible name for the functional:
# - Start with the filename without extension
# - Replace "-" and "+" with "_"
# - Maybe do other things but we will see what creative ideas people come up
#   with
functional_name=${inputfile%.max}
functional_name=`basename $functional_name`
functional_name=`echo "$functional_name" | sed -e 's/^nwxc_//' -e 's/-/_/' -e 's/+/_/'`
#
# Normally Maxima will print everything it is doing. This behavior can be 
# suppressed by terminating the lines with $-signs instead of ;-signs.
# Hence create an intermediate Maxima specification of the functional that
# suppresses all the printing.
#
f_quiet=${TMPDIR:-/tmp}/fnc_intermediate.$$
sed -e 's/ *$//' -e 's/;$/$/' $inputfile > $f_quiet
#
# What version of Maxima are we using?
#
maxima_version=`maxima --version`
#
# Work out what LISP interpreter Maxima is using
#
f_maxima=${TMPDIR:-/tmp}/fnc_maxima.$$
echo > $f_maxima
lisp_version=`maxima -b $f_maxima | grep -i lisp | sed -e 's/using Lisp //'`
#
# Write Maxima code to analyze the functional given
#
# Analyze the functional definition we have been given. We want to know whether
# f, g, and/or G are present. The presence of G requires additional source
# code to be generated for when one of the alpha or beta density is 0.
#
f_maxima=${TMPDIR:-/tmp}/fnc_maxima.$$
f_dependency=${TMPDIR:-/tmp}/fnc_dependency.$$.out
f_dependency_sh=${TMPDIR:-/tmp}/fnc_dependency.$$.sh
cat <<EOF > $f_maxima
reference: "unpublished"$
doi: "unpublished"$
f(zeta,rho_a,rho_b,rho,sigma_aa,sigma_ab,sigma_bb,sigma,tau_a,tau_b,tau):=0$
g(rho_s,sigma_ss,tau_s):=0$
G(rho_s,sigma_ss,tau_s,tau_u):=0$
functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b):=0$
gradef(nwxcm_heaviside(x),0)$
EOF
cat $f_quiet >> $f_maxima
cat <<EOF >> $f_maxima
functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b):=  
    f((rho_a-rho_b)/(rho_a+rho_b),rho_a,rho_b,rho_a+rho_b,        
      sigma_aa,sigma_ab,sigma_bb,sigma_aa+2*sigma_ab+sigma_bb,    
      tau_a,tau_b,tau_a+tau_b)                                    
  + g(rho_a,sigma_aa,tau_a)       + g(rho_b,sigma_bb,tau_b)             
  + G(rho_a,sigma_aa,tau_a,tau_b) + G(rho_b,sigma_bb,tau_b,tau_a)$
rho_deriv:is (diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                              tau_a,tau_b),rho_a)#0 or
              diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                              tau_a,tau_b),rho_b)#0)$
sigma_deriv:is (diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                                tau_a,tau_b),sigma_aa)#0 or
                diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                                tau_a,tau_b),sigma_ab)#0 or  
                diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                                tau_a,tau_b),sigma_bb)#0)$
tau_deriv:is (diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                              tau_a,tau_b),tau_a)#0 or
              diff(functional(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,
                              tau_a,tau_b),tau_b)#0)$
sums : 0$
if (f((rho_a-rho_b)/(rho_a+rho_b),rho_a,rho_b,rho_a+rho_b,        
      sigma_aa,sigma_ab,sigma_bb,sigma_aa+2*sigma_ab+sigma_bb,    
      tau_a,tau_b,tau_a+tau_b)#0) then
  sums : sums + 1$
if (g(rho_a,sigma_aa,tau_a)#0) then
  sums : sums + 1$
if (G(rho_a,sigma_aa,tau_a,tau_b)#0) then
  sums : sums + 1$
excess: is (G(rho_a,sigma_aa,tau_a,tau_b)#0)$

/* Set line length to something huge to avoid strings getting wrapped */
linel: 20000$
with_stdout("$f_dependency",        
   print("sums=",sums),      
   print("excess=",excess),      
   print("rho_deriv=",rho_deriv),      
   print("sigma_deriv=",sigma_deriv),  
   print("tau_deriv=",tau_deriv),
   print("reference=\"",reference,"\""),
   print("doi=\"",doi,"\""))$
/* printfile("$f_dependency")$ */
EOF
maxima -b $f_maxima
sed -e "s/ //" $f_dependency > $f_dependency_sh
source $f_dependency_sh
if [ $sums -eq 0 ] ; then
    echo "No functional definition in $inputfile"
    echo "Bombing"
    exit 10
fi
#
# Now we know:
#
# - whether the functional depends on the density
# - whether the functional depends on the gradient of the density
# - whether the functional depends on the kinetic energy density
# - whether the functional has a special limiting case for densities tending
#   to zero
#
# So, now we do the real thing:
#
# - Initialize all the expressions f, g, and G
# - Pick up the functional specification
# - Work out the derivative expressions
# - Generate the Fortran (currently compiler support many more continuation
#   lines, hopefully it is enough...)
# 
cat <<EOF > $f_maxima
f(zeta,rho_a,rho_b,rho,sigma_aa,sigma_ab,sigma_bb,sigma,tau_a,tau_b,tau):=0$
g(rho_s,sigma_ss,tau_s):=0$
G(rho_s,sigma_ss,tau_s,tau_u):=0$
/* Func is the functional for the regular case: f(a,b) + g(a) + g(b).
   I.e. both spin channels have non-zero density. */
func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b):=0$
/* Funcs is the functional for one spin channel assuming that the density
   in the other spin channel vanishes: g(s) + G(s). */
funcs(rho_s,sigma_ss,tau_s,tau_u):=0$
gradef(nwxcm_heaviside(x),0)$
EOF
cat $f_quiet >> $f_maxima
cat <<EOF >> $f_maxima
excess:$excess\$
rho_deriv:$rho_deriv\$
sigma_deriv:$sigma_deriv\$
tau_deriv:$tau_deriv\$
EOF
cat <<EOF >> $f_maxima
func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b):=
   wght*(f((rho_a-rho_b)/(rho_a+rho_b),rho_a,rho_b,rho_a+rho_b,
           sigma_aa,sigma_ab,sigma_bb,sigma_aa+2*sigma_ab+sigma_bb,
           tau_a,tau_b,tau_a+tau_b)
       + g(rho_a,sigma_aa,tau_a) + g(rho_b,sigma_bb,tau_b))$
if excess then
   funcs(rho_s,sigma_ss,tau_s,tau_u):=
      wght*(g(rho_s,sigma_ss,tau_s) + G(rho_s,sigma_ss,tau_s,tau_u))
else
   funcs(rho_s,sigma_ss,tau_s,tau_u):=
      wght*(g(rho_s,sigma_ss,tau_s)
          + f(1,rho_s,0,rho_s,sigma_ss,0,0,sigma_ss,tau_s,tau_u,tau_s+tau_u))$

/* debugmode(true) $ */

/* When generating the actual code the optimization function will be used
   to create compact code. At that stage Maxima will generate sub-expressions
   and assign the results to some variables. To ensure that the result is 
   valid Fortran we have to reset the optimprefix as otherwise the variable
   names will start with "%". Here, I have chosen "t" as short hand for
   "temporary".
*/

optimprefix: t$

/* Increase the indentation to generate properly indented code */

fortindent: 6$

/* Set line length to something huge to avoid strings getting wrapped */

linel: 20000$

/* The usual psychosis:
   Running fortran(%pi) produces "%pi" instead of a number or something else a
   Fortran compiler would recognize. Getting Maxima to produce actual Fortran
   with "fortran" we need to tell it to evaluate everything numerically. So we
   need to create a function for that.
 */

Fortran(expr):= fortran(ev(expr,numer))$

/* Generate and print optimized Fortran to:
   1. Keep the subroutine sizes in check
   2. Keep the compiler from complaining about too many continuation lines
   3. Get code that performs reasonably well (hopefully)
*/

Fortran_block(l,e) := block( [ml: l, me : e, n : 0],
  for n:1 thru length(me) do
    Fortran(ml[n] = ml[n] + me[n])
  )$

/* The optimize(e) function produces different results depending on whether
   it could optimize the expressions in e or not. 

   If the optimization failed to achieve anything then optimize(e) will 
   simply return e. I.e. if e is 

              4/3          4/3               1/3              1/3       c3 wght     c3 wght  c4 wght        c4 wght
     [(c1 rhob    + c1 rhoa   ) wght, c2 rhoa    wght, c2 rhob    wght, -------, 0, -------, -------, 0, 0, -------] 
                                                                            2/3         2/3      5/3            5/3
                                                                        rhoa        rhob     rhoa           rhob

   optimize(e) will simply throw the same thing back. However if the
   optimization was successful optimize(e) will return a nested list. I.e.
   optimize(e) will return something like

                          c3 wght       c4 wght          4/3              1/3
     block([t1, t2], t1 : -------, t2 : -------, [c1 rhoa    wght, c2 rhoa    wght, t1, t1, t2, t2]) 
                              2/3           5/3
                          rhoa          rhoa

   where t1 and t2 are the expressions broken out, and the embedded list 
   contains the optimized expressions.

   The Fortran_opt routine needs to be aware of these different kinds of
   results and adapt accordingly. Below op(rest(args(le))[1])=":" is true if we
   have the second kind of result, otherwise we pass the result from
   optimize(e) directly to Fortran_block.
*/

Fortran_opt(l,e) := block( [ll: l, le: optimize(e)],
  if atom(rest(args(le))[1]) then
    Fortran_block(ll,le)
  else if op(rest(args(le))[1])=":" then
    for p in rest(args(le)) do
      if atom(p) then print("Pos1: What the heck?: ",p)
      else if op(p)=":" then Fortran(apply("=",args(p)))
      else if listp(p) then Fortran_block(ll,p)
      else print("Pos2: What the heck?: ",p)
  else Fortran_block(ll,le)
  )$

/* Generate and print optimized TeX to:
   1. Get some readable expressions (i.e. not 10 screens wide)
*/

TeX_block(l,e) := block( [ml: l, me : e, n : 0],
  for n:1 thru length(me) do
    print(sconcat("C>   ",tex1(ml[n])," &=& ",tex1(me[n]),"\\\\\\\\\\\\\\\\"))
  )$

TeX_opt(l,e) := block( [ll: l, le: optimize(e)],
  if atom(rest(args(le))[1]) then
    TeX_block(ll,le)
  else if op(rest(args(le))[1])=":" then
    for p in rest(args(le)) do
      if atom(p) then print("Pos1: What the heck?: ",p)
      else if op(p)=":" then
        print(sconcat("C>   ",tex1(args(p)[1])," &=& ",tex1(args(p)[2]),"\\\\\\\\\\\\\\\\"))
      else if listp(p) then TeX_block(ll,p)
      else print("Pos2: What the heck?: ",p)
  else TeX_block(ll,le)
  )$

/* eliminateAt

In this application for the closed density functional derivatives we will
have entities of the form at(diff(densfunc(rhoa,rhob),rhoa,1),rhob=rhoa).
The "at" function interferes with the expression optimizer eventually leading
to Fortran code that cannot easily be transformed into valid Fortran that
calls the right subroutines. 

The important pieces of information in the offending entity are:
1. densfunc
   - the name of the subroutine we need to call eventually
2. the number of arguments to densfunc
   - specifies the type of functional (LDA, GGA, or meta-GGA) and hence the
     parameter list for the subroutine call
3. the further arguments of diff
   - specifies the order of differentiation and the parameters with respect to
     which the functional is differentiated, and by extension the variables
     returned from the subroutine call that hold the relevant data.
   - beware though that the cross derivative
     diff(lda(rhoa,rhob)*gga(rhoa,rhob,gammaaa,gammaab,gammabb),rhoa,rhob)
     leads to terms involving diff(lda(rhoa,rhob),rhob) which is not computed
     in the closed shell lda implementation, instead diff(lda(rhoa,rhob),rhoa)
     is calculated and has the same value. Hence additional translations are
     needed to ensure we pick the right results from the subroutines we
     invoke.
Hence we can replace the entity given above by diff(densfunc(rhoa,rhoa),rhoa,1)
without losing the three crucial bits of information but at the same time
eliminating the troublesome "at" function.

The eliminateAt function executes this substitution and returns the resulting
expression.
*/
eliminateAt(expression) :=
  block( [ops,args,result,arg],
         if atom(expression)
           then expression
           else
              ( ops:  op(expression),
                args: args(expression),
                if piece=nounify('at)
                then processAt(first(args))
                else
                   (
                     result: [],
                     for arg in args do (
                        result: endcons(eliminateAt(arg),result)
                     ),
                     apply(ops,result)
                   )
              )
       )$

/* processAt

This function take diff(densfunc(rhoa,rhob),rhoa,1) and substitutes 
rhoa for rhob, gammaaa for gammaab and gammabb, and taua for taub in the
argument list of densfunc. It returns the modified diff expression of the 
form diff(densfunc(rhoa,rhoa),rhoa,1).
*/
processAt(expression) :=
   block( [ops,args,result,arg],
          if atom(expression)
            then error("The contents of at() should not be an atom")
            else
               ( ops:  op(expression),
                 args: args(expression),
                 if piece#nounify('derivative)
                 then error("Only diff() is supposed to appear in at() at this point")
                 else
                    (
                      result: [],
                      arg: first(args),
                      result: endcons(processFunc(arg),result),
                      args: rest(args),
                      args: canonicalArgs(args),
                      for arg in args do (
                         result: endcons(arg,result)
                      ),
                      apply(ops,result)
                    )
               )
        )$

/* canonicalArgs

This function takes the argument list of the diff-construct (i.e. for
diff(densfunc(rhoa,rhob),rhoa,1,rhob,2) it takes [rhoa,1,rhob,2]) and,
if needed, replaces it with the derivative that the closed shell codes
calculate (i.e. [rhoa,2,rhob,1] in the previous example).
The implementation of this function is mind-bogglingly dumb. I just go 
through all possible cases and check whether the list of arguments matches
one. If so I return the canonical list of arguments for that case.
*/
canonicalArgs(args) :=
   block( [],
          if (args = [rhob,1]) then
             return([rhoa,1])
          elseif (args = [gammabb,1]) then
             return([gammaaa,1])
          elseif (args = [taub,1]) then
             return([taua,1])
          elseif (args = [rhob,1,taua,1]) then
             return([rhoa,1,taub,1])
          elseif (args = [rhob,1,taub,1]) then
             return([rhoa,1,taua,1])
          elseif (args = [rhob,1,gammaaa,1]) then
             return([rhoa,1,gammabb,1])
          elseif (args = [rhob,1,gammaab,1]) then
             return([rhoa,1,gammaab,1])
          elseif (args = [gammaab,1,gammabb,1]) then
             return([gammaaa,1,gammaab,1])
          elseif (args = [gammabb,2]) then
             return([gammaaa,2])
          elseif (args = [gammaab,1,taub,1]) then
             return([gammaab,1,taua,1])
          elseif (args = [gammabb,1,taua,1]) then
             return([gammaaa,1,taub,1])
          elseif (args = [gammabb,1,taub,1]) then
             return([gammaaa,1,taua,1])
          elseif (args = [taub,2]) then
             return([taua,2])
          else
             return(args)
        )$

/* processFunc

This function takes an expression of the form densfunc(rhoa,rhob) and applies
the relevant substitutions to the argument list and returns the expression of
the densfunc(rhoa,rhoa) form.
*/
processFunc(expression) :=
   block( [ops,args,arg,result],
          ops: op(expression),
          args: args(expression),
          result: [],
          for arg in args do (
             arg: subst(rhoa,rhob,arg),
             arg: subst(gammaaa,gammaab,arg),
             arg: subst(gammaaa,gammabb,arg),
             arg: subst(taua,taub,arg),
             result: endcons(arg,result)
          ),
          apply(ops,result)
        )$

/* Ideally we want reasonably compact expressions so we extend diff to try and
   generate those.
*/

Diff(x,y):=combine(diff(x,y))$

/* 1st order derivatives */
/* Alpha and Beta spin channel */

df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_a)$
df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$
df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df1gab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df1gbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df1ta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df1tb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(func(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* One spin channel */

dfs1rs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(funcs(rho_s,sigma_ss,tau_s,tau_u),rho_s)$
dfs1gss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(funcs(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs1ts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(funcs(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs1tu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(funcs(rho_s,sigma_ss,tau_s,tau_u),tau_u)$

/* 2nd order derivatives */
/* Alpha and Beta spin channel */
/* Rho Rho */

df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_a)$
df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$
df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$

/* Rho Sigma */
df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df2ragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df2ragbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df2rbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df2rbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$

/* Rho Tau */

df2rata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2ratb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ra(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df2rbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2rbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1rb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Sigma Sigma */

df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df2gaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df2gaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df2gabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df2gabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df2gbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$

/* Sigma Tau */

df2gaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2gaatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df2gabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2gabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df2gbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2gbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1gbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Tau Tau */

df2tata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df2tatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1ta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df2tbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df1tb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* 2nd order derivatives */
/* One spin channel */

dfs2rsrs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1rs(rho_s,sigma_ss,tau_s,tau_u),rho_s)$
dfs2rsgss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1rs(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs2rsts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1rs(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs2rstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1rs(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs2gssgss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1gss(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs2gssts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1gss(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs2gsstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1gss(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs2tsts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1ts(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs2tstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1ts(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs2tutu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs1tu(rho_s,sigma_ss,tau_s,tau_u),tau_u)$

/* 3rd order derivatives */
/* Alpha and Beta spin channel */
/* Rho Rho Rho */

df3rarara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_a)$
df3rararb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$
df3rarbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$
df3rbrbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),rho_b)$

/* Rho Rho Sigma */

df3raragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3raragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3raragbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3rarbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3rarbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3rarbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3rbrbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3rbrbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3rbrbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$

/* Rho Rho Tau */

df3rarata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3raratb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rara(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rarbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rarbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rarb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbrbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rbrbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbrb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Rho Sigma Sigma */

df3ragaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3ragaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3ragaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3ragabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3ragabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3ragbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$

df3rbgaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3rbgaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3rbgaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3rbgabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3rbgabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3rbgbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$


/* Rho Sigma Tau */

df3ragaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3ragaatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3ragabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3ragabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3ragbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3ragbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ragbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbgaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rbgaatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbgabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rbgabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbgbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rbgbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Rho Tau Tau */

df3ratata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3ratatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3ratbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2ratb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbtata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3rbtatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3rbtbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2rbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Sigma Sigma Sigma */

df3gaagaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_aa)$
df3gaagaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3gaagaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3gaagabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3gaagabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3gaagbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3gabgabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_ab)$
df3gabgabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3gabgbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$
df3gbbgbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),sigma_bb)$

/* Sigma Sigma Tau */

df3gaagaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gaagaatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagaa(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gaagabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gaagabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gaagbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gaagbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaagbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gabgabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gabgabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgab(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gabgbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gabgbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gbbgbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gbbgbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbgbb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Sigma Tau Tau */

df3gaatata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gaatatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gaatbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gaatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gabtata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gabtatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gabtbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gabtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gbbtata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3gbbtatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbta(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3gbbtbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2gbbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* Tau Tau Tau */

df3tatata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2tata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_a)$
df3tatatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2tata(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3tatbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2tatb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$
df3tbtbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b)
:=Diff(df2tbtb(rho_a,rho_b,sigma_aa,sigma_ab,sigma_bb,tau_a,tau_b),tau_b)$

/* 3rd order derivatives */
/* One spin channel */

dfs3rsrsrs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsrs(rho_s,sigma_ss,tau_s,tau_u),rho_s)$
dfs3rsrsgss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsrs(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs3rsrsts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsrs(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3rsrstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsrs(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3rsgssgss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsgss(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs3rsgssts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsgss(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3rsgsstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsgss(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3rststs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsts(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3rststu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rsts(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3rstutu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2rstu(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3gssgssgss(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gssgss(rho_s,sigma_ss,tau_s,tau_u),sigma_ss)$
dfs3gssgssts(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gssgss(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3gssgsstu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gssgss(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3gsststs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gssts(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3gsststu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gssts(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3gsstutu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2gsstu(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3tststs(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2tsts(rho_s,sigma_ss,tau_s,tau_u),tau_s)$
dfs3tststu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2tsts(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3tstutu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2tstu(rho_s,sigma_ss,tau_s,tau_u),tau_u)$
dfs3tututu(rho_s,sigma_ss,tau_s,tau_u)
:=Diff(dfs2tutu(rho_s,sigma_ss,tau_s,tau_u),tau_u)$

texput(zeta,"\\\\zeta")$
texput(rhoa,"\\\\rho_\\\\alpha")$
texput(rhob,"\\\\rho_\\\\beta")$
texput(rho,"\\\\rho")$
texput(sigmaaa,"\\\\sigma_{\\\\alpha\\\\alpha}")$
texput(sigmaab,"\\\\sigma_{\\\\alpha\\\\beta}")$
texput(sigmabb,"\\\\sigma_{\\\\beta\\\\beta}")$
texput(sigma,"\\\\sigma")$
texput(taua,"\\\\tau_\\\\alpha")$
texput(taub,"\\\\tau_\\\\beta")$
texput(tau,"\\\\tau")$
texput(rhos,"\\\\rho_s")$
texput(sigmass,"\\\\sigma_{ss}")$
texput(taus,"\\\\tau_s")$
texput(tauu,"\\\\tau_{\\\\bar s}")$
tl : [f, g, G] $
te : [f(zeta,rhoa,rhob,rho,sigmaaa,sigmaab,sigmabb,sigma,taua,taub,tau),
      g(rhos,sigmass,taus),
      G(rhos,sigmass,taus,tauu)] $

/* Lists of first order quantities */

/* Unrestricted open-shell */

ul0 : [ fnc(iq) ] $
ul1r: [ Amat(iq,D1_RA),  Amat(iq,D1_RB) ] $
ul1g: [ Cmat(iq,D1_GAA), Cmat(iq,D1_GAB), Cmat(iq,D1_GBB) ] $
ul1t: [ Mmat(iq,D1_TA),  Mmat(iq,D1_TB) ] $

ue0 : [ func(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $
ue1r: [ df1ra(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df1rb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $
ue1g: [ df1gaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df1gab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df1gbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $
ue1t: [ df1ta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df1tb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $

/* Unrestricted open-shell, alpha density only (beta density equals zero) */

ula0 : [ fnc(iq) ] $
ula1r: [ Amat(iq,D1_RA)  ] $
ula1g: [ Cmat(iq,D1_GAA) ] $
ula1t: [ Mmat(iq,D1_TA),  Mmat(iq,D1_TB) ] $

uea0 : [ funcs(rhoa,gammaaa,taua,taub) ] $
uea1r: [ dfs1rs(rhoa,gammaaa,taua,taub) ] $
uea1g: [ dfs1gss(rhoa,gammaaa,taua,taub) ] $
uea1t: [ dfs1ts(rhoa,gammaaa,taua,taub),
         dfs1tu(rhoa,gammaaa,taua,taub) ] $

/* Unrestricted open-shell, beta density only (alpha density equals zero) */

ulb0 : [ fnc(iq) ] $
ulb1r: [ Amat(iq,D1_RB)  ] $
ulb1g: [ Cmat(iq,D1_GBB) ] $
ulb1t: [ Mmat(iq,D1_TB),  Mmat(iq,D1_TA) ] $

ueb0 : [ funcs(rhob,gammabb,taub,taua) ] $
ueb1r: [ dfs1rs(rhob,gammabb,taub,taua) ] $
ueb1g: [ dfs1gss(rhob,gammabb,taub,taua) ] $
ueb1t: [ dfs1ts(rhob,gammabb,taub,taua),
         dfs1tu(rhob,gammabb,taub,taua) ] $

/* Closed-shell */

cl0 : [ fnc(iq) ] $
cl1r: [ Amat(iq,D1_RA) ] $
cl1g: [ Cmat(iq,D1_GAA), Cmat(iq,D1_GAB) ] $
cl1t: [ Mmat(iq,D1_TA) ] $

ce0 : [ func(rhoa,rhoa,gammaaa,gammaaa,gammaaa,taua,taua) ] $
ce1r: [ eliminateAt(at(df1ra(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $
ce1g: [ eliminateAt(at(df1gaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df1gab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $
ce1t: [ eliminateAt(at(df1ta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $

/* Lists of second order quantities */

/* Unrestricted open-shell */

ul2r: [ Amat2(iq,D2_RA_RA),   Amat2(iq,D2_RA_RB),   Amat2(iq,D2_RB_RB) ] $
ul2g: [ Cmat2(iq,D2_RA_GAA),  Cmat2(iq,D2_RA_GAB),  Cmat2(iq,D2_RA_GBB),
        Cmat2(iq,D2_RB_GAA),  Cmat2(iq,D2_RB_GAB),  Cmat2(iq,D2_RB_GBB),
        Cmat2(iq,D2_GAA_GAA), Cmat2(iq,D2_GAA_GAB), Cmat2(iq,D2_GAA_GBB),
        Cmat2(iq,D2_GAB_GAB), Cmat2(iq,D2_GAB_GBB), Cmat2(iq,D2_GBB_GBB) ] $
ul2t: [ Mmat2(iq,D2_RA_TA),   Mmat2(iq,D2_RA_TB),
        Mmat2(iq,D2_RB_TA),   Mmat2(iq,D2_RB_TB),
        Mmat2(iq,D2_GAA_TA),  Mmat2(iq,D2_GAA_TB),
        Mmat2(iq,D2_GAB_TA),  Mmat2(iq,D2_GAB_TB),
        Mmat2(iq,D2_GBB_TA),  Mmat2(iq,D2_GBB_TB),
        Mmat2(iq,D2_TA_TA),   Mmat2(iq,D2_TA_TB),   Mmat2(iq,D2_TB_TB) ] $

ue2r: [ df2rara(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rarb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbrb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $
ue2g: [ df2ragaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2ragab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2ragbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbgaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $
ue2t: [ df2rata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2ratb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2rbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df2gaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df2gabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df2gbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2gbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df2tata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2tatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df2tbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $

/* Unrestricted open-shell, alpha density only (beta density equals zero) */

ula2r: [ Amat2(iq,D2_RA_RA)  ] $
ula2g: [ Cmat2(iq,D2_RA_GAA), Cmat2(iq,D2_GAA_GAA) ] $
ula2t: [ Mmat2(iq,D2_RA_TA),  Mmat2(iq,D2_RA_TB),
         Mmat2(iq,D2_GAA_TA), Mmat2(iq,D2_GAA_TB),
         Mmat2(iq,D2_TA_TA),  Mmat2(iq,D2_TA_TB),
         Mmat2(iq,D2_TB_TB)   ] $

uea2r: [ dfs2rsrs(rhoa,gammaaa,taua,taub) ] $
uea2g: [ dfs2rsgss(rhoa,gammaaa,taua,taub),
         dfs2gssgss(rhoa,gammaaa,taua,taub) ] $
uea2t: [ dfs2rsts(rhoa,gammaaa,taua,taub),
         dfs2rstu(rhoa,gammaaa,taua,taub),
         dfs2gssts(rhoa,gammaaa,taua,taub),
         dfs2gsstu(rhoa,gammaaa,taua,taub),
         dfs2tsts(rhoa,gammaaa,taua,taub),
         dfs2tstu(rhoa,gammaaa,taua,taub),
         dfs2tutu(rhoa,gammaaa,taua,taub)   ] $

/* Unrestricted open-shell, beta density only (alpha density equals zero) */

ulb2r: [ Amat2(iq,D2_RB_RB)  ] $
ulb2g: [ Cmat2(iq,D2_RB_GBB), Cmat2(iq,D2_GBB_GBB) ] $
ulb2t: [ Mmat2(iq,D2_RB_TA),  Mmat2(iq,D2_RB_TB),
         Mmat2(iq,D2_GBB_TA), Mmat2(iq,D2_GBB_TB),
         Mmat2(iq,D2_TA_TA),  Mmat2(iq,D2_TA_TB),
         Mmat2(iq,D2_TB_TB)   ] $

ueb2r: [ dfs2rsrs(rhob,gammabb,taub,taua) ] $
ueb2g: [ dfs2rsgss(rhob,gammabb,taub,taua),
         dfs2gssgss(rhob,gammabb,taub,taua) ] $
ueb2t: [ dfs2rstu(rhob,gammabb,taub,taua),
         dfs2rsts(rhob,gammabb,taub,taua),
         dfs2gsstu(rhob,gammabb,taub,taua),
         dfs2gssts(rhob,gammabb,taub,taua),
         dfs2tutu(rhob,gammabb,taub,taua),
         dfs2tstu(rhob,gammabb,taub,taua),
         dfs2tsts(rhob,gammabb,taub,taua)   ] $

/* Closed-shell */

cl2r: [ Amat2(iq,D2_RA_RA),   Amat2(iq,D2_RA_RB) ] $
cl2g: [ Cmat2(iq,D2_RA_GAA),  Cmat2(iq,D2_RA_GAB),  Cmat2(iq,D2_RA_GBB),
        Cmat2(iq,D2_GAA_GAA), Cmat2(iq,D2_GAA_GAB), Cmat2(iq,D2_GAA_GBB),
        Cmat2(iq,D2_GAB_GAB) ] $
cl2t: [ Mmat2(iq,D2_RA_TA),   Mmat2(iq,D2_RA_TB),
        Mmat2(iq,D2_GAA_TA),  Mmat2(iq,D2_GAA_TB),
        Mmat2(iq,D2_GAB_TA),
        Mmat2(iq,D2_TA_TA),   Mmat2(iq,D2_TA_TB) ] $

ce2r: [ eliminateAt(at(df2rara(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2rarb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $
ce2g: [ eliminateAt(at(df2ragaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2ragab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2ragbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $
ce2t: [ eliminateAt(at(df2rata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2ratb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2gabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2tata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df2tatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $

/* Lists of third order quantities */

/* Unrestricted open-shell */

ul3r: [ Amat3(iq,D3_RA_RA_RA),    Amat3(iq,D3_RA_RA_RB),
        Amat3(iq,D3_RA_RB_RB),    Amat3(iq,D3_RB_RB_RB) ] $

ul3g: [ Cmat3(iq,D3_RA_RA_GAA),   Cmat3(iq,D3_RA_RA_GAB),
        Cmat3(iq,D3_RA_RA_GBB),   Cmat3(iq,D3_RA_RB_GAA),
        Cmat3(iq,D3_RA_RB_GAB),   Cmat3(iq,D3_RA_RB_GBB),
        Cmat3(iq,D3_RB_RB_GAA),   Cmat3(iq,D3_RB_RB_GAB),
        Cmat3(iq,D3_RB_RB_GBB),
        Cmat3(iq,D3_RA_GAA_GAA),  Cmat3(iq,D3_RA_GAA_GAB),
        Cmat3(iq,D3_RA_GAA_GBB),  Cmat3(iq,D3_RA_GAB_GAB),
        Cmat3(iq,D3_RA_GAB_GBB),  Cmat3(iq,D3_RA_GBB_GBB),
        Cmat3(iq,D3_RB_GAA_GAA),  Cmat3(iq,D3_RB_GAA_GAB),
        Cmat3(iq,D3_RB_GAA_GBB),  Cmat3(iq,D3_RB_GAB_GAB),
        Cmat3(iq,D3_RB_GAB_GBB),  Cmat3(iq,D3_RB_GBB_GBB),
        Cmat3(iq,D3_GAA_GAA_GAA), Cmat3(iq,D3_GAA_GAA_GAB),
        Cmat3(iq,D3_GAA_GAA_GBB), Cmat3(iq,D3_GAA_GAB_GAB),
        Cmat3(iq,D3_GAA_GAB_GBB), Cmat3(iq,D3_GAA_GBB_GBB),
        Cmat3(iq,D3_GAB_GAB_GAB), Cmat3(iq,D3_GAB_GAB_GBB),
        Cmat3(iq,D3_GAB_GBB_GBB), Cmat3(iq,D3_GBB_GBB_GBB) ] $

ul3t: [ Mmat3(iq,D3_RA_RA_TA),    Mmat3(iq,D3_RA_RA_TB),
        Mmat3(iq,D3_RA_RB_TA),    Mmat3(iq,D3_RA_RB_TB),
        Mmat3(iq,D3_RB_RB_TA),    Mmat3(iq,D3_RB_RB_TB),
        Mmat3(iq,D3_RA_GAA_TA),   Mmat3(iq,D3_RA_GAA_TB),
        Mmat3(iq,D3_RA_GAB_TA),   Mmat3(iq,D3_RA_GAB_TB),
        Mmat3(iq,D3_RA_GBB_TA),   Mmat3(iq,D3_RA_GBB_TB),
        Mmat3(iq,D3_RB_GAA_TA),   Mmat3(iq,D3_RB_GAA_TB),
        Mmat3(iq,D3_RB_GAB_TA),   Mmat3(iq,D3_RB_GAB_TB),
        Mmat3(iq,D3_RB_GBB_TA),   Mmat3(iq,D3_RB_GBB_TB),
        Mmat3(iq,D3_RA_TA_TA),    Mmat3(iq,D3_RA_TA_TB),
        Mmat3(iq,D3_RA_TB_TB),    Mmat3(iq,D3_RB_TA_TA),
        Mmat3(iq,D3_RB_TA_TB),    Mmat3(iq,D3_RB_TB_TB),
        Mmat3(iq,D3_GAA_GAA_TA),  Mmat3(iq,D3_GAA_GAA_TB),
        Mmat3(iq,D3_GAA_GAB_TA),  Mmat3(iq,D3_GAA_GAB_TB),
        Mmat3(iq,D3_GAA_GBB_TA),  Mmat3(iq,D3_GAA_GBB_TB),
        Mmat3(iq,D3_GAB_GAB_TA),  Mmat3(iq,D3_GAB_GAB_TB),
        Mmat3(iq,D3_GAB_GBB_TA),  Mmat3(iq,D3_GAB_GBB_TB),
        Mmat3(iq,D3_GBB_GBB_TA),  Mmat3(iq,D3_GBB_GBB_TB),
        Mmat3(iq,D3_GAA_TA_TA),   Mmat3(iq,D3_GAA_TA_TB),
        Mmat3(iq,D3_GAA_TB_TB),   Mmat3(iq,D3_GAB_TA_TA),
        Mmat3(iq,D3_GAB_TA_TB),   Mmat3(iq,D3_GAB_TB_TB),
        Mmat3(iq,D3_GBB_TA_TA),   Mmat3(iq,D3_GBB_TA_TB),
        Mmat3(iq,D3_GBB_TB_TB),
        Mmat3(iq,D3_TA_TA_TA),    Mmat3(iq,D3_TA_TA_TB),
        Mmat3(iq,D3_TA_TB_TB),    Mmat3(iq,D3_TB_TB_TB) ] $

ue3r: [ df3rarara(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rararb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbrb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbrbrb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $

ue3g: [ df3raragaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3raragab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3raragbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbgaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbrbgaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbrbgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbrbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbgbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $

ue3t: [ df3rarata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3raratb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rarbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3rbrbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbrbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3ragaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3ragabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3ragbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3ragbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3rbgaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3rbgabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3rbgbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3rbgbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub), 
        df3gaagaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaagbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabgbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbgbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbgbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaatata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaatatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gaatbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabtata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabtatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gabtbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbtata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbtatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3gbbtbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3tatata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3tatatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3tatbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),
        df3tbtbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub) ] $

/* Unrestricted open-shell, alpha density only (beta density equals zero) */

ula3r: [ Amat3(iq,D3_RA_RA_RA)  ] $
ula3g: [ Cmat3(iq,D3_RA_RA_GAA),  Cmat3(iq,D3_RA_GAA_GAA), 
         Cmat3(iq,D3_GAA_GAA_GAA) ] $
ula3t: [ Mmat3(iq,D3_RA_RA_TA),   Mmat3(iq,D3_RA_RA_TB),
         Mmat3(iq,D3_RA_GAA_TA),  Mmat3(iq,D3_RA_GAA_TB),
         Mmat3(iq,D3_GAA_GAA_TA), Mmat3(iq,D3_GAA_GAA_TB),
         Mmat3(iq,D3_RA_TA_TA),   Mmat3(iq,D3_RA_TA_TB),
         Mmat3(iq,D3_RA_TB_TB),
         Mmat3(iq,D3_GAA_TA_TA),  Mmat3(iq,D3_GAA_TA_TB),
         Mmat3(iq,D3_GAA_TB_TB),
         Mmat3(iq,D3_TA_TA_TA),   Mmat3(iq,D3_TA_TA_TB),
         Mmat3(iq,D3_TA_TB_TB),   Mmat3(iq,D3_TB_TB_TB) ] $

uea3r: [ dfs3rsrsrs(rhoa,gammaaa,taua,taub) ] $
uea3g: [ dfs3rsrsgss(rhoa,gammaaa,taua,taub),
         dfs3rsgssgss(rhoa,gammaaa,taua,taub),
         dfs3gssgssgss(rhoa,gammaaa,taua,taub) ] $
uea3t: [ dfs3rsrsts(rhoa,gammaaa,taua,taub),
         dfs3rsrstu(rhoa,gammaaa,taua,taub),
         dfs3rsgssts(rhoa,gammaaa,taua,taub),
         dfs3rsgsstu(rhoa,gammaaa,taua,taub),
         dfs3gssgssts(rhoa,gammaaa,taua,taub),
         dfs3gssgsstu(rhoa,gammaaa,taua,taub),
         dfs3rststs(rhoa,gammaaa,taua,taub),
         dfs3rststu(rhoa,gammaaa,taua,taub),
         dfs3rstutu(rhoa,gammaaa,taua,taub),
         dfs3gsststs(rhoa,gammaaa,taua,taub),
         dfs3gsststu(rhoa,gammaaa,taua,taub),
         dfs3gsstutu(rhoa,gammaaa,taua,taub),
         dfs3tststs(rhoa,gammaaa,taua,taub),
         dfs3tststu(rhoa,gammaaa,taua,taub),
         dfs3tstutu(rhoa,gammaaa,taua,taub),
         dfs3tututu(rhoa,gammaaa,taua,taub) ] $

/* Unrestricted open-shell, beta density only (alpha density equals zero) */

ulb3r: [ Amat3(iq,D3_RB_RB_RB)  ] $
ulb3g: [ Cmat3(iq,D3_RB_RB_GBB),  Cmat3(iq,D3_RB_GBB_GBB), 
         Cmat3(iq,D3_GBB_GBB_GBB) ] $
ulb3t: [ Mmat3(iq,D3_RB_RB_TA),   Mmat3(iq,D3_RB_RB_TB),
         Mmat3(iq,D3_RB_GBB_TA),  Mmat3(iq,D3_RB_GBB_TB),
         Mmat3(iq,D3_GBB_GBB_TA), Mmat3(iq,D3_GBB_GBB_TB),
         Mmat3(iq,D3_RB_TA_TA),   Mmat3(iq,D3_RB_TA_TB),
         Mmat3(iq,D3_RB_TB_TB),
         Mmat3(iq,D3_GBB_TA_TA),  Mmat3(iq,D3_GBB_TA_TB),
         Mmat3(iq,D3_GBB_TB_TB),
         Mmat3(iq,D3_TA_TA_TA),   Mmat3(iq,D3_TA_TA_TB),
         Mmat3(iq,D3_TA_TB_TB),   Mmat3(iq,D3_TB_TB_TB) ] $

ueb3r: [ dfs3rsrsrs(rhob,gammabb,taub,taua) ] $
ueb3g: [ dfs3rsrsgss(rhob,gammabb,taub,taua),
         dfs3rsgssgss(rhob,gammabb,taub,taua),
         dfs3gssgssgss(rhob,gammabb,taub,taua) ] $
ueb3t: [ dfs3rsrstu(rhob,gammabb,taub,taua),
         dfs3rsrsts(rhob,gammabb,taub,taua),
         dfs3rsgsstu(rhob,gammabb,taub,taua),
         dfs3rsgssts(rhob,gammabb,taub,taua),
         dfs3gssgsstu(rhob,gammabb,taub,taua),
         dfs3gssgssts(rhob,gammabb,taub,taua),
         dfs3rstutu(rhob,gammabb,taub,taua),
         dfs3rststu(rhob,gammabb,taub,taua),
         dfs3rststs(rhob,gammabb,taub,taua),
         dfs3gsstutu(rhob,gammabb,taub,taua),
         dfs3gsststu(rhob,gammabb,taub,taua),
         dfs3gsststs(rhob,gammabb,taub,taua),
         dfs3tututu(rhob,gammabb,taub,taua),
         dfs3tstutu(rhob,gammabb,taub,taua),
         dfs3tststu(rhob,gammabb,taub,taua),
         dfs3tststs(rhob,gammabb,taub,taua) ] $

/* Closed-shell */

cl3r: [ Amat3(iq,D3_RA_RA_RA),    Amat3(iq,D3_RA_RA_RB) ] $

cl3g: [ Cmat3(iq,D3_RA_RA_GAA),   Cmat3(iq,D3_RA_RA_GAB),
        Cmat3(iq,D3_RA_RA_GBB),   Cmat3(iq,D3_RA_RB_GAA),
        Cmat3(iq,D3_RA_RB_GAB),
        Cmat3(iq,D3_RA_GAA_GAA),  Cmat3(iq,D3_RA_GAA_GAB),
        Cmat3(iq,D3_RA_GAA_GBB),  Cmat3(iq,D3_RA_GAB_GAB),
        Cmat3(iq,D3_RA_GAB_GBB),  Cmat3(iq,D3_RA_GBB_GBB),
        Cmat3(iq,D3_GAA_GAA_GAA), Cmat3(iq,D3_GAA_GAA_GAB),
        Cmat3(iq,D3_GAA_GAA_GBB), Cmat3(iq,D3_GAA_GAB_GAB),
        Cmat3(iq,D3_GAA_GAB_GBB), Cmat3(iq,D3_GAB_GAB_GAB) ] $

cl3t: [ Mmat3(iq,D3_RA_RA_TA),    Mmat3(iq,D3_RA_RA_TB),
        Mmat3(iq,D3_RA_RB_TA),
        Mmat3(iq,D3_RA_GAA_TA),   Mmat3(iq,D3_RA_GAA_TB),
        Mmat3(iq,D3_RA_GAB_TA),   Mmat3(iq,D3_RA_GAB_TB),
        Mmat3(iq,D3_RA_GBB_TA),   Mmat3(iq,D3_RA_GBB_TB),
        Mmat3(iq,D3_GAA_GAA_TA),  Mmat3(iq,D3_GAA_GAA_TB),
        Mmat3(iq,D3_GAA_GAB_TA),  Mmat3(iq,D3_GAA_GAB_TB),
        Mmat3(iq,D3_GAA_GBB_TA),  Mmat3(iq,D3_GAB_GAB_TA),
        Mmat3(iq,D3_TA_TA_TA),    Mmat3(iq,D3_TA_TA_TB) ] $

ce3r: [ eliminateAt(at(df3rarara(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3rararb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $

ce3g: [ eliminateAt(at(df3raragaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3raragab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3raragbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3rarbgaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3rarbgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragbbgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagaagaa(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagaagab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagaagbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagabgbb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gabgabgab(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $

ce3t: [ eliminateAt(at(df3rarata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3raratb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3rarbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3ragbbtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagaata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagaatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagabtb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gaagbbta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3gabgabta(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3tatata(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])),
        eliminateAt(at(df3tatatb(rhoa,rhob,gammaaa,gammaab,gammabb,taua,taub),[rhoa=rhoa,rhob=rhoa,gammaaa=gammaaa,gammaab=gammaaa,gammabb=gammaaa,taua=taua,taub=taua])) ] $

/* if excess then */
  if rho_deriv then
    if sigma_deriv then
      if tau_deriv then (

        /* Lists combining 0th, and 1st order terms */

        ul01  : append(ul0,  ul1r,  ul1g,  ul1t) ,
        ue01  : append(ue0,  ue1r,  ue1g,  ue1t) ,
        ula01 : append(ula0, ula1r, ula1g, ula1t) ,
        uea01 : append(uea0, uea1r, uea1g, uea1t) ,
        ulb01 : append(ulb0, ulb1r, ulb1g, ulb1t) ,
        ueb01 : append(ueb0, ueb1r, ueb1g, ueb1t) ,
        cl01  : append(cl0,  cl1r,  cl1g,  cl1t) ,
        ce01  : append(ce0,  ce1r,  ce1g,  ce1t) ,

        /* Lists combining 0th, 1st, and 2nd order terms */

        ul012  : append(ul01,  ul2r,  ul2g,  ul2t) ,
        ue012  : append(ue01,  ue2r,  ue2g,  ue2t) ,
        ula012 : append(ula01, ula2r, ula2g, ula2t) ,
        uea012 : append(uea01, uea2r, uea2g, uea2t) ,
        ulb012 : append(ulb01, ulb2r, ulb2g, ulb2t) ,
        ueb012 : append(ueb01, ueb2r, ueb2g, ueb2t) ,
        cl012  : append(cl01,  cl2r,  cl2g,  cl2t) ,
        ce012  : append(ce01,  ce2r,  ce2g,  ce2t) ,

        /* Lists combining 0th, 1st, 2nd, and 3rd order terms */

        ul0123  : append(ul012,  ul3r,  ul3g,  ul3t) ,
        ue0123  : append(ue012,  ue3r,  ue3g,  ue3t) ,
        ula0123 : append(ula012, ula3r, ula3g, ula3t) ,
        uea0123 : append(uea012, uea3r, uea3g, uea3t) ,
        ulb0123 : append(ulb012, ulb3r, ulb3g, ulb3t) ,
        ueb0123 : append(ueb012, ueb3r, ueb3g, ueb3t) ,
        cl0123  : append(cl012,  cl3r,  cl3g,  cl3t) ,
        ce0123  : append(ce012,  ce3r,  ce3g,  ce3t) ,

        with_stdout("$outputfile",
          print("C> \\\\ingroup nwxc"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\file ${functional_name}.F"),
          print("C> The $functional_name functional"),
          print("C>"),
          print("C> @}"),
          print("C>"),
          print("C> \\\\ingroup nwxc_priv"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,tau,fnc,Amat,Cmat,Mmat)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision tau(nq,NCOL_TAU)      !< [Input] The kinetic"),
          print("                                             !< energy density"),
          print("      double precision fnc(nq)      !< [Output] The functional value"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("      double precision Mmat(nq,NCOL_MMAT)   !< [Output] The derivative"),
          print("                                            !< wrt tau"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          taua    = 0.5d0*tau(iq,T_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl01,ce01),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          taua    = tau(iq,T_A)"),
          print("          taub    = tau(iq,T_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul01,ue01),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula01,uea01),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb01,ueb01),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d2(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,tau,fnc,Amat,Amat2,Cmat,Cmat2,Mmat,Mmat2)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision tau(nq,NCOL_TAU)      !< [Input] The kinetic"),
          print("                                             !< energy density"),
          print("      double precision fnc(nq)      !< [Output] The value of the"),
          print("                                    !< functional"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("      double precision Mmat(nq,NCOL_MMAT)   !< [Output] The derivative"),
          print("                                            !< wrt tau"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat2(nq,NCOL_CMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("      double precision Mmat2(nq,NCOL_MMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt tau and"),
          print("                                             !< possibly rho or rgamma"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          taua    = 0.5d0*tau(iq,T_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl012,ce012),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          taua    = tau(iq,T_A)"),
          print("          taub    = tau(iq,T_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul012,ue012),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula012,uea012),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb012,ueb012),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d2"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d3(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,tau,fnc,Amat,Amat2,Amat3,"),
          print("     +Cmat,Cmat2,Cmat3,Mmat,Mmat2,Mmat3)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision tau(nq,NCOL_TAU)      !< [Input] The kinetic"),
          print("                                             !< energy density"),
          print("      double precision fnc(nq)      !< [Output] The value of the functional"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("      double precision Mmat(nq,NCOL_MMAT)   !< [Output] The derivative"),
          print("                                            !< wrt tau"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat2(nq,NCOL_CMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("      double precision Mmat2(nq,NCOL_MMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt tau and"),
          print("                                             !< possibly rho or rgamma"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat3(nq,NCOL_AMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat3(nq,NCOL_CMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("      double precision Mmat3(nq,NCOL_MMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt tau and"),
          print("                                             !< possibly rho or rgamma"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          taua    = 0.5d0*tau(iq,T_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl0123,ce0123),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          taua    = tau(iq,T_A)"),
          print("          taub    = tau(iq,T_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul0123,ue0123),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula0123,uea0123),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb0123,ueb0123),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d3"),
          print("C> @}")
          )
          )
      else ( /* rho sigma tau */

        /* Lists combining 0th, and 1st order terms */

        ul01  : append(ul0,  ul1r,  ul1g) ,
        ue01  : append(ue0,  ue1r,  ue1g) ,
        ula01 : append(ula0, ula1r, ula1g) ,
        uea01 : append(uea0, uea1r, uea1g) ,
        ulb01 : append(ulb0, ulb1r, ulb1g) ,
        ueb01 : append(ueb0, ueb1r, ueb1g) ,
        cl01  : append(cl0,  cl1r,  cl1g) ,
        ce01  : append(ce0,  ce1r,  ce1g) ,

        /* Lists combining 0th, 1st, and 2nd order terms */

        ul012  : append(ul01,  ul2r,  ul2g) ,
        ue012  : append(ue01,  ue2r,  ue2g) ,
        ula012 : append(ula01, ula2r, ula2g) ,
        uea012 : append(uea01, uea2r, uea2g) ,
        ulb012 : append(ulb01, ulb2r, ulb2g) ,
        ueb012 : append(ueb01, ueb2r, ueb2g) ,
        cl012  : append(cl01,  cl2r,  cl2g) ,
        ce012  : append(ce01,  ce2r,  ce2g) ,

        /* Lists combining 0th, 1st, 2nd, and 3rd order terms */

        ul0123  : append(ul012,  ul3r,  ul3g) ,
        ue0123  : append(ue012,  ue3r,  ue3g) ,
        ula0123 : append(ula012, ula3r, ula3g) ,
        uea0123 : append(uea012, uea3r, uea3g) ,
        ulb0123 : append(ulb012, ulb3r, ulb3g) ,
        ueb0123 : append(ueb012, ueb3r, ueb3g) ,
        cl0123  : append(cl012,  cl3r,  cl3g) ,
        ce0123  : append(ce012,  ce3r,  ce3g) ,

        with_stdout("$outputfile",
          print("C> \\\\ingroup nwxc"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\file ${functional_name}.F"),
          print("C> The $functional_name functional"),
          print("C>"),
          print("C> @}"),
          print("C>"),
          print("C> \\\\ingroup nwxc_priv"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,fnc,Amat,Cmat)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision fnc(nq)      !< [Output] The value of the functional"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl01,ce01),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul01,ue01),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula01,uea01),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb01,ueb01),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d2(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,fnc,Amat,Amat2,Cmat,Cmat2)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision fnc(nq)      !< [Output] The value of the functional"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat2(nq,NCOL_CMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl012,ce012),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul012,ue012),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula012,uea012),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb012,ueb012),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d2"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d3(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,rgamma,fnc,Amat,Amat2,Amat3,"),
          print("     +Cmat,Cmat2,Cmat3)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,NCOL_RHO)      !< [Input] The density"),
          print("      double precision rgamma(nq,NCOL_GAMMA) !< [Input] The norm of the"),
          print("                                             !< density gradients"),
          print("      double precision fnc(nq)      !< [Output] The value of the functional"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      double precision Cmat(nq,NCOL_CMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rgamma"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat2(nq,NCOL_CMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat3(nq,NCOL_AMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt rho"),
          print("      double precision Cmat3(nq,NCOL_CMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt rgamma"),
          print("                                             !< and possibly rho"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          gammaaa = 0.25d0*rgamma(iq,G_TT)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl0123,ce0123),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          gammaaa = rgamma(iq,G_AA)"),
          print("          gammaab = rgamma(iq,G_AB)"),
          print("          gammabb = rgamma(iq,G_BB)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul0123,ue0123),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula0123,uea0123),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb0123,ueb0123),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d3"),
          print("C> @}")
          )
          )
    else ( /* rho sigma */

        /* Lists combining 0th, and 1st order terms */

        ul01  : append(ul0,  ul1r) ,
        ue01  : append(ue0,  ue1r) ,
        ula01 : append(ula0, ula1r) ,
        uea01 : append(uea0, uea1r) ,
        ulb01 : append(ulb0, ulb1r) ,
        ueb01 : append(ueb0, ueb1r) ,
        cl01  : append(cl0,  cl1r) ,
        ce01  : append(ce0,  ce1r) ,

        /* Lists combining 0th, 1st, and 2nd order terms */

        ul012  : append(ul01,  ul2r) ,
        ue012  : append(ue01,  ue2r) ,
        ula012 : append(ula01, ula2r) ,
        uea012 : append(uea01, uea2r) ,
        ulb012 : append(ulb01, ulb2r) ,
        ueb012 : append(ueb01, ueb2r) ,
        cl012  : append(cl01,  cl2r) ,
        ce012  : append(ce01,  ce2r) ,

        /* Lists combining 0th, 1st, 2nd, and 3rd order terms */

        ul0123  : append(ul012,  ul3r) ,
        ue0123  : append(ue012,  ue3r) ,
        ula0123 : append(ula012, ula3r) ,
        uea0123 : append(uea012, uea3r) ,
        ulb0123 : append(ulb012, ulb3r) ,
        ueb0123 : append(ueb012, ueb3r) ,
        cl0123  : append(cl012,  cl3r) ,
        ce0123  : append(ce012,  ce3r) ,

        with_stdout("$outputfile",
          print("C> \\\\ingroup nwxc"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\file ${functional_name}.F"),
          print("C> The $functional_name functional"),
          print("C>"),
          print("C> @}"),
          print("C>"),
          print("C> \\\\ingroup nwxc_priv"),
          print("C> @{"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,fnc,Amat)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,*)    !< [Input] The density"),
          print("      double precision fnc(nq)      !< [Output] The functional value"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl01,ce01),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul01,ue01),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula01,uea01),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb01,ueb01),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d2(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,fnc,Amat,Amat2)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,*)    !< [Input] The density"),
          print("      double precision fnc(nq)      !< [Output] The functional value"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("c"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl012,ce012),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul012,ue012),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula012,uea012),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb012,ueb012),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d2"),
          print("C>"),
          print("C> \\\\brief Evaluate the $functional_name functional [1]"),
          print("C>"),
          print("C> \\\\f{eqnarray*}{"),
          TeX_opt(tl,te),
          print("C> \\\\f}"),
          print("C>"),
          print("C> Code generated with $maxima_version [2,3]"),
          print("C> driven by autoxc [4,5,6]."),
          print("C>"),
          print("C> ### References ###"),
          print("C>"),
          print("C> [1] $reference, DOI:"),
          print("C> <a href=\"http://dx.doi.org/$doi\">"),
          print("C> $doi</a>"),
          print("C>"),
          print("C> [2] Maxima, a computer algebra system,"),
          print("C> <a href=\"http://maxima.sourceforge.net/\">"),
          print("C> http://maxima.sourceforge.net/</a>"),
          print("C>"),
          print("C> [3] $lisp_version"),
          print("C>"),
          print("C> [4] $revision"),
          print("C>"),
          print("C> [5] $revision_rewrap"),
          print("C>"),
          print("C> [6] $revision_subr"),
          print("C>"),
          print("      subroutine ${functional_name}_d3(param,tol_rho,ipol,nq,wght,"),
          print("     +rho,fnc,Amat,Amat2,Amat3)"),
          print("c \$Id: \$"),
          print("#ifdef NWXC_QUAD_PREC"),
          print("      implicit real(kind=selected_real_kind(30))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(30)"),
          print("#else"),
          print("      implicit real(kind=selected_real_kind(15))(a-h,o-z),integer(i-n)"),
          print("      integer, parameter :: rk=selected_real_kind(15)"),
          print("#endif"),
          print("#include \"nwxc_param.fh\""),
          print("      double precision param(*)     !< [Input] Parameters of functional"),
          print("      double precision tol_rho      !< [Input] The lower limit on the"),
          print("                                    !< density"),
          print("      integer ipol                  !< [Input] The number of spin"),
          print("                                    !< channels"),
          print("      integer nq                    !< [Input] The number of points"),
          print("      double precision wght         !< [Input] The weight of the"),
          print("                                    !< functional"),
          print("      double precision rho(nq,*)    !< [Input] The density"),
          print("      double precision fnc(nq)      !< [Output] The functional value"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat(nq,NCOL_AMAT)   !< [Output] The derivative"),
          print("                                            !< wrt rho"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat2(nq,NCOL_AMAT2)  !< [Output] The 2nd"),
          print("                                             !< derivative wrt rho"),
          print("c"),
          print("c     Sampling Matrices for the XC Kernel"),
          print("c"),
          print("      double precision Amat3(nq,NCOL_AMAT3)  !< [Output] The 3rd"),
          print("                                             !< derivative wrt rho"),
          print("c"),
          print("      integer iq"),
          print("      double precision tmp"),
          print("      double precision rhoa,rhob"),
          print("      double precision gammaaa,gammaab,gammabb"),
          print("      double precision taua,taub"),
          print("      double precision nwxcm_heaviside"),
          print("      external         nwxcm_heaviside"),
          print("CDIR$ NOVECTOR"),
          print("      do iq = 1, nq"),
          print("        if (ipol.eq.1) then"),
          print("          rhoa    = 0.5d0*rho(iq,R_T)"),
          print("          if (rhoa.gt.tol_rho) then"),
          Fortran_opt(cl0123,ce0123),
          print("          endif ! rhoa.gt.tol_rho"),
          print("        else  ! ipol.eq.1"),
          print("          rhoa    = rho(iq,R_A)"),
          print("          rhob    = rho(iq,R_B)"),
          print("          if (rhoa.gt.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ul0123,ue0123),
          print("          elseif (rhoa.gt.tol_rho.and.rhob.le.tol_rho) then"),
          Fortran_opt(ula0123,uea0123),
          print("          elseif (rhoa.le.tol_rho.and.rhob.gt.tol_rho) then"),
          Fortran_opt(ulb0123,ueb0123),
          print("          endif ! rhoa.gt.tol_rho.and.rhob.gt.tol_rho"),
          print("        endif ! ipol.eq.1"),
          print("      enddo ! iq"),
          print("      end subroutine ${functional_name}_d3"),
          print("C> @}")
          )
          )
  else ( /* rho */
    print("The DENSITY FUNCTIONAL does not depend on the electron density???"),
    exit,
    if sigma_deriv then
      if tau_deriv then
        with_stdout("fortran.F",print("excess,!rho_deriv,sigma_deriv,tau_deriv"))
      else /* !rho sigma tau */
        with_stdout("fortran.F",print("excess,!rho_deriv,sigma_deriv,!tau_deriv"))
    else /* !rho sigma */
      if tau_deriv then
        with_stdout("fortran.F",print("excess,!rho_deriv,!sigma_deriv,tau_deriv"))
      else /* !rho !sigma tau */
        with_stdout("fortran.F",print("excess,!rho_deriv,!sigma_deriv,!tau_deriv"))
  )$
/* else
  if rho_deriv then
    if sigma_deriv then
      if tau_deriv then
        with_stdout("fortran.F",print("!excess,rho_deriv,sigma_deriv,tau_deriv"))
      else
        with_stdout("fortran.F",print("!excess,rho_deriv,sigma_deriv,!tau_deriv"))
    else
      if tau_deriv then
        with_stdout("fortran.F",print("!excess,rho_deriv,!sigma_deriv,tau_deriv"))
      else
        with_stdout("fortran.F",print("!excess,rho_deriv,!sigma_deriv,!tau_deriv"))
  else
    if sigma_deriv then
      if tau_deriv then
        with_stdout("fortran.F",print("!excess,!rho_deriv,sigma_deriv,tau_deriv"))
      else
        with_stdout("fortran.F",print("!excess,!rho_deriv,sigma_deriv,!tau_deriv"))
    else
      if tau_deriv then
        with_stdout("fortran.F",print("!excess,!rho_deriv,!sigma_deriv,tau_deriv"))
      else
        with_stdout("fortran.F",print("!excess,!rho_deriv,!sigma_deriv,!tau_deriv")) */ 
EOF
maxima -b $f_maxima

#
# Cleaning up (i.e. deleting all the temporary files)
#
rm $f_quiet
rm $f_maxima
rm $f_dependency
rm $f_dependency_sh
#
# Convert the partial Fortran files
#
./bin/rewrap.py < $outputfile > tmpa.$$
error=$?
if [ $error -eq 0 ] ; then
   ./bin/call_subroutine.py < tmpa.$$ > tmpb.$$
   error=$?
   if [ $error -eq 0 ] ; then
      mv tmpb.$$ $outputfile
      rm tmpa.$$
   fi
fi
