/*
  Copyright (C) 2000-2004

  Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane

  This file is part of xmds.
 
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/*
  $Id: xmdsclasses.h,v 1.39 2005/10/18 23:33:16 joehope Exp $
*/

/*! @file xmdsclasses.h
  @brief Classes used in xmds

  More detailed explanation...
*/

#include <string>
#ifndef LIST
#include<list>
#define LIST
#endif

/*! @def DEBUG
  @brief Macro set to output debugging information

  Set DEBUG to 1 for full debugging output
  Set DEBUG to 0 to turn debugging off.
*/
//#define DEBUG 1

// *****************************************************************************
// *****************************************************************************
//                              xmdsElement
// *****************************************************************************
// *****************************************************************************

class xmdsSimulation;

//! Class representing an element in an xmds simulation
class xmdsElement :     public xmdsUtility {

public :

  //! Constructor of xmdsElement object
  xmdsElement(
              const xmdsSimulation *const yourSimulation,
              const bool& yourVerboseMode);

  ~xmdsElement();  //!< xmdsElement destructor

  // This was in protected!
  //! Returns the xmds simulation
  const xmdsSimulation* simulation() const;

protected :

  //! Writes the defines of output C++ code
  virtual void writeDefines(
                            FILE *const outfile) const;

  //! Writes the global variables to output C++ code
  virtual void writeGlobals(
                            FILE *const outfile) const;

  //! Writes the prototypes of the C++ code
  virtual void writePrototypes(
                               FILE *const outfile) const;

  //! Writes the routines of the xmds C++ code
  virtual void writeRoutines(
                             FILE *const outfile) const;

  //! Adds a child
  void addChild(
                const xmdsElement *const newChild);

  //! Determines if output is verbose
  bool verbose() const;

private :

  const xmdsSimulation *const mySimulation;  //!< The main simulation object
  const bool myVerbose;                      //!< Variable describing if the output should be verbose or not
  list<const xmdsElement*> myChildList;      //!< List of child elements

  //! Parse the XMLString inString and generate the output list of XML strings outXMLStringList
  void parseXMLString(
                      const XMLString *const inString,
                      list<XMLString>& outXMLStringList);
};

// ******************************************************************************
// ******************************************************************************
//                              xmdsGlobals
// ******************************************************************************
// ******************************************************************************

//! Class containing the parameters used to control an entire xmds simulation
class xmdsGlobals : public xmdsElement {

public :

  //! Constructor of xmdsGlobals object
  xmdsGlobals(
              const xmdsSimulation *const yourSimulation,
              const bool& yourVerboseMode);

  //! Destructor
  ~xmdsGlobals();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  XMLString myGlobalsCode;  //!< The XMLString containing the code entered in the globals section

  //! Writes the globals code to the output file
  void writeGlobals(
                    FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              dimension
// *****************************************************************************
// *****************************************************************************

//! Structure containing dimension parameters
struct dimensionStruct {

  XMLString name;        //!< The name of the dimension
  unsigned long lattice; //!< The lattice of the dimension
  domainStruct domain;   //!< The structure of the domain's dimension
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsFieldGeometry
// *****************************************************************************
// *****************************************************************************

//! xmds field geometry class
class xmdsFieldGeometry {

public :

  //! Clears the dimensions list
  void clear();

  //! Returns the number of dimensions
  unsigned long nDims() const;

  //! Returns the dimension of the field geometry as a dimensionStruct
  const dimensionStruct* dimension(
                                   const unsigned long& index) const;

  //! Sets the dimension of the field geometry
  void setDimension(
                    const unsigned long& index,
                    const dimensionStruct& newDimension);

  //! Adds a dimension to the field geometry
  void addDimension(
                    const dimensionStruct& newDimension);

  //! Gets dimension number
  /*! Why in the crap is this called getDimNumber if it returns boolean?
    And if it actually does return the dimension number then why
    does it return boolean?
  */
  bool getDimNumber(
                    const XMLString& dimName,
                    unsigned long& dimNumber) const;

  //! Returns the full space
  unsigned long fullSpace() const;

private :

  list<dimensionStruct> myDimensionsList;  //!< The list of the dimensions of the field
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsField
// *****************************************************************************
// *****************************************************************************

//! Enumerator of the different kinds of type a vector can be
enum xmdsVectorType {
  COMPLEX       = 0,
  DOUBLE        = 1};

class xmdsVector;

class xmdsVectorElement;

//! xmds field class
class xmdsField : public xmdsElement {

public :

  //! Constructor of xmdsField object
  xmdsField(
            const xmdsSimulation *const yourSimulation,
            const bool& yourVerboseMode);

  //! Destructor
  ~xmdsField();

  //! Processes the xmds element
  void processElement(
                      const Element *const yourElement);

  //! Processes the vectors in the vector names list
  void processVectors(
                      const list<XMLString>& vectorNamesList,
                      const unsigned long& space) const;

  //! The output sample count (but doesn't return anything... Why?)
  void outputSampleCount() const;

  //! Determines if needs FFTW plans
  bool needsFFTWPlans() const;

  //! Writes the initialisation calls to the C++ file
  virtual void writeInitialisationCalls(
                                        FILE *const outfile,
                                        const char *const indent) const;

  //! Writes the sample calls to the C++ file
  void writeSampleCalls(
                        FILE *const outfile,
                        const char *const indent) const;

  //! Assigns the active vector pointers
  void assignActiveVectorPointers(
                                  FILE *const outfile,
                                  const char *const tempVectorName) const;

  //! Returns the name of the field(?)
  const XMLString* name() const;

  //! Returns the field geometry
  const xmdsFieldGeometry* geometry() const;

  //! Gets the vector?
  /*! 
    Why does this return boolean if it gets the vector?
  */
  bool getVector(
                 const XMLString& vectorName,
                 const xmdsVector*& theVector) const;

  //! Returns the vector names in a list
  void vectorNames(
                   list<XMLString>& vectorNamesList) const;

  //! Converts the vectors to the relevant space
  void vectors2space(
                     FILE *const outfile,
                     const unsigned long& space,
                     const list<XMLString>& vectorNamesList,
                     const char *const indent) const;

  //! Opens the loops
  void openLoops(
                 FILE *const outfile,
                 unsigned long space,
                 const list<XMLString>& vectorNamesList) const;

  //! Closes the loops
  void closeLoops(
                  FILE *const outfile,
                  unsigned long space,
                  const list<XMLString>& vectorNamesList) const;

  //! Writes the plan creation calls for fftw
  void writePlanCreationCalls(
                              FILE *const outfile,
                              const bool& useFFTWMeasure,
                              const bool& useWisdom) const;

  //! Writes the plan deletion calls for fftw
  void writePlanDeletionCalls(
                              FILE *const outfile) const;

  //! Creats an xmds vector
  xmdsVector* createxmdsVector();

protected:

  //! Writes defines to outfile
  void writeDefines(
                    FILE *const outfile) const;

  //! Writes global variables to outfile
  void writeGlobals(
                    FILE *const outfile) const;

  //! Writes function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes simulation routines to outfile
  void writeRoutines(
                     FILE *const outfile) const;

  //! Sets the name of the field
  void setName(
               const XMLString& yourName);

  //! Sets the geometry of the field
  void setGeometry(
                   const xmdsFieldGeometry& yourGeometry);

private :

  XMLString                 myName;           //!< The name of the field
  xmdsFieldGeometry         myGeometry;       //!< The field geometry
  list<const xmdsVector*>   myVectorsList;    //!< The list of vectors in the field
  list<unsigned long>       mySamplesList;    //!< The list of samples of the field
  mutable bool              myNeedsFFTWPlans; //!< Whether or not the field needs the fftw plans

  //! Creates an xmds vector element
  xmdsVectorElement* createxmdsVectorElement();
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsVector
// *****************************************************************************
// *****************************************************************************

//! xmds vector class
class xmdsVector {

public :

  //! Constructor for xmdsVector object
  xmdsVector(
             const xmdsField *const yourField);

  //! Destructor
  virtual ~xmdsVector();

  //! Writes relevant #defines out to file
  void writeDefines(
                    FILE *const outfile) const;

  //! Writes relevant global variable declarations to file
  void writeGlobals(
                    FILE *const outfile) const;

  //! Writes function prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the function routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Writes the initialisation call
  void writeInitialisationCall(
                               FILE *const outfile,
                               const char *const indent) const;

  //! I think this grabs the xmds simulation name
  const XMLString* name() const;

  //! Sets the name of something, possibly the xmds simulation name
  void setName(
               const XMLString& yourName);

  //! Returns the vector type of an xmds vector
  xmdsVectorType vectorType() const;

  //! Sets the vector type (duh!)
  void setVectorType(
                     const xmdsVectorType& yourType);

  //! Obtains the number of components (possibly in the xmds simulation)
  unsigned long nComponents() const;

  //! Obtains the name of the component
  const XMLString* componentName(
                                 const unsigned long& index) const;

  //! Gets the component
  bool getComponent(
                    const XMLString& ofName,
                    unsigned long& index) const;

  //! Sets a component
  void setComponents(
                     const list<XMLString>& yourComponentsNamesList);

  //! Determines if the FFTW routines are needed
  bool needsFFTWRoutines() const;

  //! Sets whether the FFTW routines are needed
  void setNeedsFFTWRoutines() const;

  //! Determines the initial space for the xmds vector (x-space or k-space)
  unsigned long initialSpace() const;

  //! Sets the initial space to x-space or k-space
  void setInitialSpace(
                       const unsigned long& yourInitialSpace);

protected:

  //! Writes the initialise routine
  virtual void writeInitialiseRoutine(
                                      FILE *const outfile) const;

  //! Obtains an instance of the xmdsField object
  const xmdsField* field() const;

  //! Returns true if the space at index is the initial space (I think...)
  bool space(
             const long unsigned int& index) const;
private :

  const xmdsField *const  myField;                 //!< The field object
  XMLString               myName;                  //!< The name of the field
  xmdsVectorType          myType;                  //!< The data type of the field (double or complex)
  unsigned long           myInitialSpace;          //!< The initial space of the simulation (x-space or k-space)
  list<XMLString>         myComponentsNamesList;   //!< The list of the names of the components
  mutable bool            myNeedsFFTWRoutines;     //!< Whether or not the fftw routines are needed

};

// *****************************************************************************
// *****************************************************************************
//                              xmdsVectorElement
// *****************************************************************************
// *****************************************************************************

//! xmds vector element class
class xmdsVectorElement :       public xmdsVector,
                                public xmdsElement {

public :

  //! Constructor for the xmdsVectorElement object
  xmdsVectorElement(
                    const xmdsSimulation *const yourSimulation,
                    const bool& yourVerboseMode,
                    const xmdsField *const yourField);

  //! Destructor
  ~xmdsVectorElement();

  //! Processes an element of an xmds vector element
  void processElement(
                      const Element *const yourElement);

private :

  XMLString     myFileName;            //!< The input filename of the initialisation vector
  int           myInputFileFormat;     //!< The input file format
  list<XMLString> myVectorNamesList;   //!< The list of vector names
  XMLString     myCode;                //!< The string of code for initialisation of the vector(s)

  //! Write the initialisation routine to file
  void writeInitialiseRoutine(
                              FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsArgv
// *****************************************************************************
// *****************************************************************************

class xmdsArg;

class xmdsArgElement;

//! xmds argv class
/*!
  The class that handles command line arguments to xmds simulations.  
  This is equivalent to the **argv array in C.
*/
class xmdsArgv : public xmdsElement {

public :

  //! Constructor of xmdsArgv object
  xmdsArgv(
           const xmdsSimulation *const yourSimulation,
           const bool& yourVerboseMode);

  //! Destructor
  ~xmdsArgv();

  //! Processes the xmds element
  void processElement(
                      const Element *const yourElement);

  //! Processes the args in the argument names list
  void processArgs(
                   const list<XMLString>& argNamesList,
                   const unsigned long& space) const;

  //! Gets the arg?
  /*! 
    Why does this return boolean if it gets the argument?
  */
  bool getArg(
              const XMLString& argName,
              const xmdsArg*& theArg) const;

  //! Returns the argument names in a list
  void argNames(
                list<XMLString>& argNamesList) const;

  //! Creates an xmds argument
  xmdsArg* createxmdsArg();

protected:

private :

  list<const xmdsArg*>  myArgsList;       //!< The list of arguments
  
  //! Create an xmds argument element object
  xmdsArgElement* createxmdsArgElement();
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsArg
// *****************************************************************************
// *****************************************************************************

//! xmds arg class
/*!
  The class that handles individual arguments for the simulation command line.
  More specifically, it handles the name, type and default value of arguments 
  to be used on the command line.
*/
class xmdsArg {

public :

  //! Constructor for xmdsArg object
  xmdsArg(
          const xmdsArgv *const yourArgv);

  //! Destructor
  virtual ~xmdsArg();

  //! grabs the argument name
  const XMLString* name() const;

  //! Sets the argument name
  void setName(
               const XMLString& yourName);

protected:

  //! Obtains an instance of the xmdsArgv object
  const xmdsArgv* argv() const;

private :

  const xmdsArgv *const myArgv;  //!< The "vector" of arguments
  XMLString             myName;  //!< The name of the argument

};

// *****************************************************************************
// *****************************************************************************
//                              xmdsArgElement
// *****************************************************************************
// *****************************************************************************

//! xmds arg element class
/*! 
  The class that handles individual elements of an argument.  These are the 
  name of the argument, its type and its default value.
*/
class xmdsArgElement :  public xmdsArg,
                        public xmdsElement {

public :

  //! Constructor for the xmdsArgElement object
  xmdsArgElement(
                 const xmdsSimulation *const yourSimulation,
                 const bool& yourVerboseMode,
                 const xmdsArgv *const yourArgv);

  //! Destructor
  ~xmdsArgElement();

  //! Processes an element of an xmds vector element
  void processElement(
                      const Element *const yourElement);

private :

  //   void writeArgDeclaration(
  //                        FILE *const outfile) const;

  //   void writeArgCode(
  //                FILE *const outfile) const;

  //   list<XMLString> myArgNamesList;

};

// *****************************************************************************
// *****************************************************************************
//                              xmdsMomentGroup
// *****************************************************************************
// *****************************************************************************

//! xmds moment group class
class xmdsMomentGroup : public xmdsField {

public :

  //! Constructor for the xmdsMomentGroup class
  /*! 
    @param yourSimulation an xmdsSimulation object
    @param yourVerboseMode a boolean
    @param yourGroupNumber an unsigned long
  */
  xmdsMomentGroup(
                  const xmdsSimulation *const yourSimulation,
                  const bool& yourVerboseMode,
                  const unsigned long& yourGroupNumber);

  //! Destructor
  ~xmdsMomentGroup();

  //! Process elements within a moment group
  void processElement(
                      const Element *const yourElement);

  //! Adds the specified number of samples to the moment group
  void addSamples(
                  const unsigned long& n2add) const;

  //! Sets up the final geometry of the moment group
  void finaliseGeometry();

  //! Function to determine if simulation requires integrations
  bool requiresIntegrations() const;

  //! Function to determine if simulation requires a complex raw vector
  bool needscomplexRawVector() const;

private :

  const unsigned long   myGroupNumber;                   //!< The group number (of the current object?)

  list<XMLString>       myVectorNamesList;               //!< The list of vector names
  unsigned long         mySamplingSpace;                 //!< The sampling space (x-space or k-space)
  list<unsigned long>   mySamplingLatticeList;           //!< The sampling lattice list
  list<XMLString>       mySamplingMomentsList;           //!< The sampling moments list
  XMLString             mySamplingCode;                  //!< String containing the sampling code
  unsigned long         myRawSpace;                      //!< Integer representing the raw space (before post-processing)
  unsigned long         myPostSpace;                     //!< Integer representing the post space
  list<XMLString>       myPostMomentsList;               //!< List of moments in the post space
  XMLString             myPostCode;                      //!< Code for post-propagation
  list<XMLString>       myPostProcessingVectorNamesList; //!< List of vector names in post-propagation
  list<unsigned long>   myMain2PostDimList;              //!< List of dimensions from main space to post space (I think)
  list<unsigned long>   myPost2MainDimList;              //!< List of dimensions from post space to main space (I think)
  xmdsFieldGeometry     tempGeometry;                    //!< Temporary field geometry
  bool                  complexRawVector;                //!< Whether or not we have a complex raw vector
  bool                  myRequiresIntegrations;          //!< Whether or not integrations are required

  mutable unsigned long nSamples;                        //!< The number of samples to take

  //! Write the moment group defines to file
  void writeDefines(
                    FILE *const outfile) const;

  //! Write the moment group globals to file
  void writeGlobals(
                    FILE *const outfile) const;
  
  //! Write the moment group prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the moment group routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Determine the sampling space at index
  bool samplingSpace(
                     const unsigned long& index) const;

  //! Determin the post space at index
  bool postSpace(
                 const unsigned long& index) const;

  //! Return the main to post-propagation dimension
  unsigned long main2PostDim(
                             const unsigned long& index) const;

  //! Return the post-propagation to main dimension
  unsigned long post2MainDim(
                             const unsigned long& index) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsBreakPoint
// *****************************************************************************
// *****************************************************************************

//! xmds break point class
class xmdsBreakPoint : public xmdsField {

public :

  //! Constructor for the xmdsBreakPoint class
  /*! 
    @param yourSimulation an xmdsSimulation object
    @param yourVerboseMode a boolean

    @todo Break points need to be implemented
  */
  xmdsBreakPoint(
		 const xmdsSimulation *const yourSimulation,
		 const bool& yourVerboseMode);

  //! Destructor
  ~xmdsBreakPoint();

  //! Process elements within a moment group
  void processElement(
                      const Element *const yourElement);

private :

  XMLString             bpFname;  //!< The filename for the breakpoint file
  XMLString             bpStatus; //!< The status of the breakpoint file (old, new, unknown)
  XMLString             bpFormat; //!< The format of the breakpoint file (ascii, binary)

  /*
    const unsigned long   myGroupNumber;

    list<XMLString>       myVectorNamesList;
    unsigned long         mySamplingSpace;
    list<unsigned long>   mySamplingLatticeList;
    list<XMLString>       mySamplingMomentsList;
    XMLString             mySamplingCode;
    unsigned long         myRawSpace;
    unsigned long         myPostSpace;
    list<XMLString>       myPostMomentsList;
    XMLString             myPostCode;
    list<XMLString>       myPostProcessingVectorNamesList;
    list<unsigned long>   myMain2PostDimList;
    list<unsigned long>   myPost2MainDimList;
    xmdsFieldGeometry     tempGeometry;
    bool                  complexRawVector;
    bool                  myRequiresIntegrations;
  */

  //! Write the breakpoint specific defines to file
  void writeDefines(
                    FILE *const outfile) const;

  //! Write the breakpoint specific globals to file
  void writeGlobals(
                    FILE *const outfile) const;

  //! Write the breakpoint prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the breakpoint routines to file
  void writeRoutines(
                     FILE *const outfile) const;

};

// *****************************************************************************
// *****************************************************************************
//                              xmdsOutput
// *****************************************************************************
// *****************************************************************************

//! Class which organises data output of simulation
class xmdsOutput : public xmdsElement {

public :

  //! Constructor of xmdsOutput object
  xmdsOutput(
             const xmdsSimulation *const yourSimulation,
             const bool& yourVerboseMode);

  //! Destructor
  ~xmdsOutput();

  //! Process elements defined in output section of xmds file
  void processElement(
                      const Element *const yourElement);

  //! Sets the point in the input file to split
  void setInFileSplitPoint(
                           const unsigned long& inFileSplitPoint);

  //! Determines the number of moment groups for output
  unsigned long nMomentGroups() const;

  //! Return the output file name
  XMLString getOutputFileName() const;

  //! Creates an xmdsMomentGroup object
  const xmdsMomentGroup* momentGroup(
                                     const unsigned long& index) const;

  //! Adds samples to the output samples list
  void addSamples(
                  const list<unsigned long>& samplesList) const;

  //! Sets up the final geometry to use for output
  void finaliseGeometry();

  //! Assigns the active vector pointers in the list of moment groups
  void assignActiveVectorPointers(
                                  FILE *const outfile,
                                  const char *const tempVectorName) const;

  //! Writes the FFTW plan creation calls to file
  void writePlanCreationCalls(
                              FILE *const outfile,
                              const bool& useFFTWMeasure,
                              const bool& useWisdom) const;

  //! Writes the FFTW plan deletion calls to file
  void writePlanDeletionCalls(
                              FILE *const outfile) const;

private :

  XMLString               myOutputFileName;    //!< The output filename
  list<xmdsMomentGroup*>  myMomentGroupsList;  //!< The list of output moment groups
  unsigned long           myInFileSplitPoint;  //!< The point at which to split the input file
  bool                    bpEnabledFlag;       //!< Whether or not breakpoints are enabled

  //! Write the output prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the output routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Create an xmds moment group object
  xmdsMomentGroup* createxmdsMomentGroup();

  //! Create an xmds breakpoint object
  xmdsBreakPoint* createxmdsBreakPoint();
};


// *****************************************************************************
// *****************************************************************************
//                              xmdsSegment
// *****************************************************************************
// *****************************************************************************

//! xmds segment class
class xmdsSegment : public xmdsElement {

public :

  //! Number of segments or current segment number (buh?)
  const unsigned long segmentNumber;

  //! Constructor of xmdsSegment object
  xmdsSegment(
              const xmdsSimulation *const yourSimulation,
              const bool& yourVerboseMode);

  //! Destructor
  ~xmdsSegment();

  //! Returns the output sample count
  virtual void outputSampleCount() const;

  //! Writes initialisation calls to file
  virtual void writeInitialisationCalls(
                                        FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsSequence
// *****************************************************************************
// *****************************************************************************

//! I think this organises the sequence in which elements of the simulation are processed.
class xmdsSequence : public xmdsSegment {

public :

  //! Constructor for xmdsSequence object
  xmdsSequence(
               const xmdsSimulation *const yourSimulation,
               const bool& yourVerboseMode);

  //! Destructor
  ~xmdsSequence();

  //! Processes elements within an xmds sequence
  void processElement(
                      const Element *const yourElement);

  //! Returns the output sample count of the sequence
  void outputSampleCount() const;

private :

  unsigned long nCycles;                   //!< The number of cycles in the sequence
  list<const xmdsSegment*> mySegmentList;  //!< The list of segments

  //! Write the sequence defines to file
  void writeDefines(
                    FILE *const outfile) const;

  //! Write the sequence globals to file
  void writeGlobals(
                    FILE *const outfile) const;

  //! Write the sequence prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the sequence routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Create an xmds sequence object
  xmdsSegment* createxmdsSequence();

  //! Create an xmds integrate RK4 EX object
  xmdsSegment* createxmdsIntegrateRK4EX();

  //! Create an xmds integrate RK4 IP object
  xmdsSegment* createxmdsIntegrateRK4IP();

  //! Create an xmds integrate ARK45 EX object
  xmdsSegment* createxmdsIntegrateARK45EX();

  //! Create an xmds integrate ARK45 IP object
  xmdsSegment* createxmdsIntegrateARK45IP();

  //! Create an xmds integrate SI EX object
  xmdsSegment* createxmdsIntegrateSIEX();

  //! Create an xmds integrate SI IP object
  xmdsSegment* createxmdsIntegrateSIIP();

  //! Create an xmds filte object
  xmdsSegment* createxmdsFilter();
};

//! Structure containing components of an xmdsSequence
struct coStruct {

  unsigned long componentNumber;           //!< The component number
  list<unsigned long> operatorNumbersList; //!< The operator numbers list
  list<unsigned long> coKeysList;          //!< The component keys list
};

//! Structure containing components of an integrate moment group
struct integrateMomentGroup {

  list<XMLString> momentNameList;           //!< The list of moment names
  list<bool>      integrateDimensionList;   //!< List of whether dimensions are integrated
  XMLString       integrateMomentGroupCode; //!< The integrate moment group code
};


// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrate
// *****************************************************************************
// *****************************************************************************

//! Class to organise integration of relevant equations in simulation
class xmdsIntegrate : public xmdsSegment {

public :

  //! Enumerator containing the half and full step integration parameters
  enum stepCaseEnum {
    FIRST_HALFSTEP,
    SECOND_HALFSTEP,
    FULLSTEP
  };

  //! Constructor for xmdsIntegrate object
  xmdsIntegrate(
                const xmdsSimulation *const yourSimulation,
                const bool& yourVerboseMode, const bool& adaptiveIP = false);

  //! Destructor
  ~xmdsIntegrate();

  //! Processes the xmds element
  void processElement(
                      const Element *const yourElement);

protected :

  //! Writes the defines to outfile
  void writeDefines(
                    FILE *const outfile) const;

  //! Writes global variables to outfile
  void writeGlobals(
                    FILE *const outfile) const;

  //! Writes function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the x-space prototypes to outfile
  virtual void writexSpacePrototype(
                                    FILE *const outfile) const;

  //! Writes the simulation routines
  void writeRoutines(
                     FILE *const outfile) const;

  //! Writes the x-space simulation routines
  virtual void writexSpaceRoutine(
                                  FILE *const outfile) const;

  //! Returns the interval (buh?)
  const XMLString* interval() const;

  //! Returns the lattice
  unsigned long lattice() const;

  //! Returns the number of samples
  unsigned long samples(
                        const unsigned long& index) const;

  //! Returns the vector name list in k-space
  const list<XMLString>* KVectorNamesList() const;

  //! Determines if k is constant (buh?)
  bool constantK() const;

  //! Returns the number of operators in k-space
  unsigned long nKOperators() const;

  //! Returns the k-space operator as XMLString
  const XMLString* KOperator(
                             const unsigned long& index) const;

  //! Returns the k-space operator
  /*!
    Why does this return boolean?
  */
  bool getKOperator(
                    const XMLString& operatorName,
                    unsigned long& index) const;
        
  //! k-space operators code
  const XMLString* KOperatorsCode() const;

  //! Returns the vector names list
  list<XMLString>* vectorNamesList();

  //! Returns the vector names list
  const list<XMLString>* vectorNamesList() const;

  //! Returns the propagation code
  XMLString* propagationCode();

  //! Returns the propagation code
  const XMLString* propagationCode() const;

  //! Returns the cross vector names list
  const list<XMLString>* crossVectorNamesList() const;

  //! Returns the cross dimension number
  unsigned long crossDimNumber() const;

  //! Returns the cross propagation code
  const XMLString* crossPropagationCode() const;

  //! Determines if k-space operators are used
  bool usesKOperators() const;
  
  //! returns true if the algorithm is ARK45IP 
  const bool AdaptiveIP() const;
  
  //! returns if k_propagate should always use the time-dependend version
  const bool Smallmemory() const;

  //! Returns the code element list
  list<XMLString>* codeElementList();

  //! Returns the code element list
  const list<XMLString>* codeElementList() const;

  //! Returns number of non-loop propagation elements
  long unsigned int numNonLoopPropagation() const;

  //! Returns the non-loop propagation code list
  const list<XMLString>* nonLoopPropagationCodeList() const;

  //! Returns the non-loop propagation code list
  list<XMLString>* nonLoopPropagationCodeList();

  //! Returns number of integrate moment groups
  long unsigned int numIntegrateMomentGroups() const;

  //! Returns the integrate moment group list
  const list<integrateMomentGroup>* integrateMomentGroupList() const;

  //! Returns the integrate moment group list
  list<integrateMomentGroup>* integrateMomentGroupList();

  //! Gets the component structure
  /*!
    Why does this return boolean?
  */
  bool getcoStruct(
                   const unsigned long& componentNumber,
                   const coStruct*& thecoStruct) const;

  //! Gets the component key
  /*! 
    Why does this return boolean?
  */
  bool getcoKey(
                const unsigned long& componentNumber,
                const unsigned long& operatorNumber,
                unsigned long& coKey) const;

  //! Adds a component pair
  unsigned long addcoPair(
                          const unsigned long& componentNumber,
                          const unsigned long& operatorNumber);

  //! Finds the next component pair
  /*!
    Why does this return boolean?
  */
  bool findNextcoPair(
                      XMLString& operatorName,
                      XMLString& componentName,
                      unsigned long& start,
                      unsigned long& end) const;
					  
  //! Determines if generation of noises is to be supressed
  bool noNoises() const;



private :

  XMLString                   myInterval;                     //!< The interval over which to integrate
  unsigned long               myLattice;                      //!< The integration lattice
  list<unsigned long>         mySamplesList;                  //!< The list of samples over the lattice
  list<XMLString>             myKVectorNamesList;             //!< The list of the names of the k-space vectors
  bool                        myConstantK;                    //!< Whether or not the k-operators are constant
  list<XMLString>             myKOperatorNamesList;           //!< The list of k-operator names
  XMLString                   myKOperatorsCode;               //!< The k-operators code
  list<XMLString>             myVectorNamesList;              //!< The list of vector names
  XMLString                   myPropagationCode;              //!< The propagation code
  list<XMLString>             myCrossVectorNamesList;         //!< The list of cross-propagation vector names
  unsigned long               myCrossDimNumber;               //!< The cross-propagation dimension number
  list<XMLString>             myCodeElementList;              //!< Names of code elements
  long                        myNumIntegrateMomentGroups;     //!< Number of non-loop propagation elements
  list<integrateMomentGroup>  myIntegrateMomentGroupList;     //!< The list of integrate moment group elements
  long                        myNumNonLoopPropagation;        //!< Number of non-loop propagation elements
  list<XMLString>             myNonLoopPropagationCodeList;   //!< The list of non-loop propagation codes
  XMLString                   myCrossPropagationCode;         //!< The cross-propagation code
  list<coStruct>              mycoStructList;                 //!< The component structure list
  unsigned long               myNextcoKey;                    //!< The key of the next component
  bool						 myNonoises;					  //!< Flag for turning off noise generation
  bool						  myAdaptiveIP;						// Is it adaptive?                                     
  bool                        mySmallmemory;                  // can it save six copies of k-op fields

  //! The output sample count 
  void outputSampleCount() const;

  //! Write the integrate initialisation calls to file
  void writeInitialisationCalls(
                                FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsFilter
// *****************************************************************************
// *****************************************************************************

//! xmds filter class
class xmdsFilter : public xmdsSegment {

public :

  //! Constructor for xmdsFilter object
  xmdsFilter(
             const xmdsSimulation *const yourSimulation,
             const bool& yourVerboseMode);

  //! Destructor
  ~xmdsFilter();

  //! Processes filter element
  void processElement(
                      const Element *const yourElement);

protected:

  //! Returns the code element list
  list<XMLString>* codeElementList();

  //! Returns the code element list
  const list<XMLString>* codeElementList() const;

  //! Returns number of non-loop propagation elements
  long unsigned int numNonLoopPropagation() const;

  //! Returns the non-loop propagation code list
  list<XMLString>* nonLoopPropagationCodeList();

  //! Returns the non-loop propagation code list
  const list<XMLString>* nonLoopPropagationCodeList() const;

  //! Returns number of integrate moment groups
  long unsigned int numIntegrateMomentGroups() const;

  //! Returns the integrate moment group list
  list<integrateMomentGroup>* integrateMomentGroupList();

  //! Returns the integrate moment group list
  const list<integrateMomentGroup>* integrateMomentGroupList() const;


private :

  list<XMLString>             myVectorNamesList;              //!< List of vector names
  unsigned long               mySpace;                        //!< Space of filter (x-space or k-space)
  XMLString                   myCode;                         //!< The filter code
  list<XMLString>             myCodeElementList;              //!< Names of code elements
  long                        myNumIntegrateMomentGroups;     //!< Number of non-loop propagation elements
  list<integrateMomentGroup>  myIntegrateMomentGroupList;     //!< The list of integrate moment group elements
  long                        myNumNonLoopPropagation;        //!< Number of non-loop propagation elements
  list<XMLString>             myNonLoopPropagationCodeList;   //!< The list of non-loop propagation codes
  bool						  myNonoises;					  //!< Flag for turning off noise generation

  //! Write the filter prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the filter routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Determine the space at index (buh?)
  bool space(
             const long unsigned int& index) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateIP
// *****************************************************************************
// *****************************************************************************

//! Class to integrate the equations in the interaction picture
class xmdsIntegrateIP : public virtual xmdsIntegrate {

public :

  //! Constructor of xmdsIntegrateIP object
  xmdsIntegrateIP(
                  const xmdsSimulation *const yourSimulation,
                  const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateIP();

  //! Processes the element
  void processElement(
                      const Element *const yourElement);

protected :

  //! Writes the function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the routines to outfile
  void writeRoutines(
                     FILE *const outfile) const;

private :

  //! Write the calculate k-operator field routine to file
  void writeCalculatekOperatorFieldRoutine(
                                           FILE *const outfile) const;

  //! Write the constant k-operators propagate routine to file
  void writeConstkPropagateRoutine(
                                   FILE *const outfile) const;

  //! Write the time dependent k-operators propagate routine to file
  void writeTimeDepkPropagateRoutine(
                                     FILE *const outfile) const;
                                     
  //! Write the calculate k-operator field routine for the adaptive algorithm to file
  void writeARK45CalculatekOperatorFieldRoutine(
                                           FILE *const outfile) const;
                                           
  //! Write the calculate k-operator field routine for the adaptive algorithm to file
  void writeARK45TimeDepkCalculatekOperatorFieldRoutine(
                                           FILE *const outfile) const;

  //! Write the constant k-operators propagate routine for the adaptive algorithm to file
  void writeARK45kPropagateRoutine(
                                   FILE *const outfile) const;


};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateEX
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations in explicit picture
class xmdsIntegrateEX : public virtual xmdsIntegrate {

public :

  //! Constructor of xmdsIntegrateEX object
  xmdsIntegrateEX(
                  const xmdsSimulation *const yourSimulation,
                  const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateEX();

  //! Processes the element
  void processElement(
                      const Element *const yourElement);

protected :

  //! Writes the function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the routines to outfile
  void writeRoutines(
                     FILE *const outfile) const;

private :

  //! Writes the routine for calculating the k-operator field to file
  void writeCalculatekOperatorFieldRoutine(
                                           FILE *const outfile) const;

  //! Writes the routine for calculating the component terms for constant k-operators to file
  void writeCalculateCOTermsConstantKRoutine(
                                             FILE *const outfile) const;

  //! Writes the routine for calculating the component terms for time dependent k-operators to file
  void writeCalculateCOTermsTimeDepKRoutine(
                                            FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateSI
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the semi-implicit method
class xmdsIntegrateSI : public virtual xmdsIntegrate {

public :

  //! Constructor of xmdsIntegrateSI object
  xmdsIntegrateSI(
                  const xmdsSimulation *const yourSimulation,
                  const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateSI();

  //! Processes the element
  void processElement(
                      const Element *const yourElement);

protected :

  //! Returns the number of iterations
  unsigned long nIterations() const;

private :

  unsigned long mynIterations;  //!< The number of iterations to be performed
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateARK45
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the fourth order Runge-Kutta method
class xmdsIntegrateARK45 : public virtual xmdsIntegrate {

public :

  //! Constructor of xmdsIntegrateARK45 object
  xmdsIntegrateARK45(
                   const xmdsSimulation *const yourSimulation,
                   const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateARK45();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

protected :

  //! returns the tolerance
  const XMLString* tolerance() const;

  //! returns the cutoff
  const XMLString* cutoff() const;

  //! Writes the function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the routines to outfile
  void writeRoutines(
                     FILE *const outfile) const;

  //! Writes the single step code to outfile
  virtual void writeSingleStepCode(
                                   FILE *const outfile,
                                   const stepCaseEnum& stepCase) const = 0;
private :

  //! Write the error-finding routine to file
  void writeTimestepErrorRoutine(
                                 FILE *const outfile) const;
                                 
  //! Write the routine that finds who to sample when
  void writeSetupSamplingRoutine(
                                 FILE *const outfile) const;

  //! Write the main integrate routine to file
  void writeMainIntegrateRoutine(
                                 FILE *const outfile) const;

  //! Write the routine to calculate the cross field to file
  void writeCalculateCrossFieldRoutine(
                                       FILE *const outfile) const;
                                       
  XMLString     myTolerance;       // error tolerance for adaptive timestep
  XMLString     myCutoff;          // optional function size cutoff for determination of timestep error
  unsigned long     myMaxIterations;   // optional safety-device: aborts integration when given number of iterations is reached
                                       
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateRK4
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the fourth order Runge-Kutta method
class xmdsIntegrateRK4 : public virtual xmdsIntegrate {

public :

  //! Constructor of xmdsIntegrateRK4 object
  xmdsIntegrateRK4(
                   const xmdsSimulation *const yourSimulation,
                   const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateRK4();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

protected :

  //! Writes the function prototypes to outfile
  void writePrototypes(
                       FILE *const outfile) const;

  //! Writes the routines to outfile
  void writeRoutines(
                     FILE *const outfile) const;

  //! Writes the single step code to outfile
  virtual void writeSingleStepCode(
                                   FILE *const outfile,
                                   const stepCaseEnum& stepCase) const = 0;
private :

  //! Write the main integrate routine to file
  void writeMainIntegrateRoutine(
                                 FILE *const outfile) const;

  //! Write the routine to calculate the cross field to file
  void writeCalculateCrossFieldRoutine(
                                       FILE *const outfile) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateSIIP
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the semi-implicit method in the interaction picture
class xmdsIntegrateSIIP :       public xmdsIntegrateIP,
                                public xmdsIntegrateSI{

public :

  //! Constructor of xmdsIntegrateSIIP object
  xmdsIntegrateSIIP(
                    const xmdsSimulation *const yourSimulation,
                    const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateSIIP();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  //! Write the integrate SIIP prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the integrate SIIP x-space prototypes to file
  void writexSpacePrototype(
                            FILE *const outfile) const;

  //! Write the integrate SIIP routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Write the main SIIP integrate routine to file
  void writeMainIntegrateRoutine(
                                 FILE *const outfile) const;

  //! Write the integrate SIIP x-space routine to file
  void writexSpaceRoutine(
                          FILE *const outfile) const;

  //! Write the integrate SIIP single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateSIEX
// *****************************************************************************
// *****************************************************************************

//! Class to integrate the equations using the semi-implicit method in the explicit picture
class xmdsIntegrateSIEX : public xmdsIntegrateEX,
                          public xmdsIntegrateSI {

public :

  //! Constructor of xmdsIntegrateSIEX object
  xmdsIntegrateSIEX(
                    const xmdsSimulation *const yourSimulation,
                    const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateSIEX();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  //! Write the integrate SIEX prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the integrate SIEX routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Write the main SIEX integrate routine to file
  void writeMainIntegrateRoutine(
                                 FILE *const outfile) const;

  //! Write the integrate SIEX cross-field calculating routine to file
  void writeCalculateCrossFieldRoutine(
                                       FILE *const outfile) const;

  //! Write the integrate SIEX single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateRK4IP
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the fourth order Runge-Kutta method in the interaction picture
class xmdsIntegrateRK4IP :      public xmdsIntegrateIP,
                                public xmdsIntegrateRK4{

public :

  //! Constructor of xmdsIntetrageRK4IP object
  xmdsIntegrateRK4IP(
                     const xmdsSimulation *const yourSimulation,
                     const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateRK4IP();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  //! Write the integrate RK4IP prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the integrate RK4IP routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Write the integrate RK4IP single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateRK4EX
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the fourth order Runge-Kutta method in the explicit picture
class xmdsIntegrateRK4EX : public xmdsIntegrateEX,
                           public xmdsIntegrateRK4 {

public :

  //! Constructor of an xmdsIntegrateRK4EX object
  xmdsIntegrateRK4EX(
                     const xmdsSimulation *const yourSimulation,
                     const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateRK4EX();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  //! Write the integrate RK4EX prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the integrate RK4EX routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Write the integrate RK4EX single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateARK45IP
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the adaptive fourth-fifth order Runge-Kutta method in the interaction picture
class xmdsIntegrateARK45IP :      public xmdsIntegrateIP,
                                public xmdsIntegrateARK45{

public :

  //! Constructor of xmdsIntetrageARK45IP object
  xmdsIntegrateARK45IP(
                     const xmdsSimulation *const yourSimulation,
                     const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateARK45IP();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);
                    

private :

  //! Write the integrate ARK45IP prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;
                       
  //! Writes the Routine to "undo" bad timesteps
  void writeResetRoutine(
					     FILE *const outfile) const;

  //! Write the integrate ARK45IP routines to file
  void writeRoutines(
                     FILE *const outfile) const;
                     

  //! Write the integrate ARK45IP single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
                           
};

// *****************************************************************************
// *****************************************************************************
//                              xmdsIntegrateARK45EX
// *****************************************************************************
// *****************************************************************************

//! Class to integrate equations using the adaptive fourth-fifth order Runge-Kutta method in the explicit picture
class xmdsIntegrateARK45EX : public xmdsIntegrateEX,
                           public xmdsIntegrateARK45 {

public :

  //! Constructor of an xmdsIntegrateARK45EX object
  xmdsIntegrateARK45EX(
                     const xmdsSimulation *const yourSimulation,
                     const bool& yourVerboseMode);

  //! Destructor
  ~xmdsIntegrateARK45EX();

  //! Processes an element
  void processElement(
                      const Element *const yourElement);

private :

  //! Write the integrate ARK45EX prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the integrate ARK45EX routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Writes the Routine to "undo" bad timesteps
  void writeResetRoutine(
					     FILE *const outfile) const;

  //! Write the integrate ARK45EX single step code to file
  void writeSingleStepCode(
                           FILE *const outfile,
                           const stepCaseEnum& stepCase) const;
};


// *****************************************************************************
// *****************************************************************************
//                              xmdsSimulation
// *****************************************************************************
// *****************************************************************************

//! Class to organise a simulation in xmds
class xmdsSimulation : public xmdsElement {

public :

  //! Structure of parameters used in an xmds simulation
  struct simulationParametersStruct {
    XMLString rawFileName;    //!< Raw simulation file name
    XMLString simulationName; //!< Simulation name
    XMLString propDimName;    //!< Propagation dimension name
    XMLString authorName;     //!< Name of the author the xmds script
    XMLString description;    //!< Description of what the script is supposed to do
    long nThreads;            //!< Number of threads
    bool stochastic;          //!< Is this a stochastic simulation?
    long nPaths;              //!< Number of paths
    bool mpiAvailable;        //!< Is mpi available?
    bool usempi;              //!< Use mpi?
    bool bing;                //!< Play sound when simulation is finished?
    long seed[2];             //!< Random number seed
    long nNoises;             //!< Number of noise terms
    XMLString noiseKind;      //!< The kind of noise to be generated
	XMLString mpiMethod;      //!< The method of dividing paths amongst nodes 
    double noiseMean;         //!< The mean of the noise distribution; only used for Poissonian distributions
    bool errorCheck;          //!< Should I error check?
    bool useWisdom;           //!< Should wisdom be used?
    bool usePrefs;            //!< Should the values in the preferences file be used?
    bool binaryOutput;        //!< Is binary output required?
    bool useDouble;           //!< Should double precision be used?
    bool benchmark;           //!< Time the main loop?
    XMLString version;        //!< The current xmds version number
    XMLString release;        //!< The current xmds release number
  };

  //! Structure of arguments on command line to simulation
  struct argvStruct {
    mutable list<string> nameList;             //!< List storing the argument names
    mutable list<string> typeList;             //!< List storing the argument types
    mutable list<string> defaultValueList;     //!< List storing the argument default values
    mutable list<string> shortOptionList;      //!< List storing the short option names
    mutable list<string> typeConversionList;   //!< List storing how to perform the type conversion
  };

  //! Constructor of xmdsSimulation object
  xmdsSimulation(
                 const char *const yourRawFileName,
                 const bool& yourVerboseMode,
                 const bool& mpiAvailable);

  //! Destructor
  ~xmdsSimulation();

  //! Process element within xmds simulation
  void processElement(
                      const Element *const yourElement);

  //! Returns structure holding parameters controlling the simulation
  const simulationParametersStruct* parameters() const;

  //! Returns the structure containing the command line argument information
  argvStruct* argStruct() const;

  //! Returns an xmdsArgv object
  xmdsArgv* argv() const;

  //! Returns an xmdsField object
  xmdsField* field() const;

  //! Returns an xmdsOutput object to manage output to file
  const xmdsOutput* output() const;

  //! Returns an xmdsSequence object
  const xmdsSequence* sequence() const;

  //! Returns the next segment number in the simulation sequence
  unsigned long nextSegmentNumber() const;

  //! Inserts relevant code at relevant point in output C++ file
  void makeCode(
                const unsigned long& inFileSplitPoint) const;

private :
  
  simulationParametersStruct    myParameters;            //!< Structure of parameters of simulation
  mutable argvStruct            myArgStruct;             //!< Structure of command line arguments to simulation
  mutable list<string>          myArgvNameList;          //!< List of names of command line arguments
  xmdsArgv*                     myArgv;                  //!< The command line argument "vector" object
  xmdsField*                    myField;                 //!< The xmdsField object
  xmdsOutput*                   myOutput;                //!< The xmdsOutput object
  xmdsSequence*                 mySequence;              //!< The xmdsSequence object
  mutable unsigned long         myCurrentSegmentNumber;  //!< The current segment number

  //! Write the simulation include statements to file
  void writeIncludes(
                     FILE *const outfile) const;

  //! Write the simulation define statements to file
  void writeDefines(
                    FILE *const outfile) const;

  //! Write the simulation global variables to file
  void writeGlobals(
                    FILE *const outfile) const;

  //! Write the simulation prototypes to file
  void writePrototypes(
                       FILE *const outfile) const;

  //! Write the simulation routines to file
  void writeRoutines(
                     FILE *const outfile) const;

  //! Create an xmdsGlobals object
  xmdsGlobals* createxmdsGlobals();

  //! Create an xmdsField object
  xmdsField* createxmdsField();

  //! Create an xmdsArgv object
  xmdsArgv* createxmdsArgv();

  //! Create an xmdsOutput object
  xmdsOutput* createxmdsOutput();

  //! Create an xmdsSequence object
  xmdsSequence* createxmdsSequence();
};



syntax highlighted by Code2HTML, v. 0.9.1