/* sim.h

   written by Don Maszle
   6 October 1991
   
   Copyright (c) 1993.  Don Maszle, Frederic Bois.  All rights reserved.

   -- Revisions -----
     Logfile:  SCCS/s.sim.h
    Revision:  1.1
        Date:  7/14/93
     Modtime:  19:15:06
      Author:  @a
   -- SCCS  ---------

   Header file for simulation
*/

/* ----- Inclusions  */

#include "modiface.h"
#include "list.h"
#include "difsub.h"
#include "matutil.h"
#include "random.h"

/* ----- Constants  */

  /* Keyword Map constants */

#define KM_INTEGRATE	1
#define KM_SIMULATE	2
#define KM_PRINT	5

#define KM_SIMTYPE      8		/* For simulation type specification */
#define KM_DEFAULTSIM   9		/* `Normal' keyword: normal sims */

#define KM_EXPERIMENT	10
#define KM_MONTECARLO	11
#define KM_MCVARY	12
#define KM_SETPOINTS	13
#define KM_OUTPUTFILE	14
#define KM_GIBBS	15
#define KM_OPTIMIZE	20
  
#define KM_END	100

  /* Function argument keywords */

#define KM_YES		200
#define KM_NO		201

#define KM_UNIFORM	210
#define KM_LOGUNIFORM	211
#define KM_BETA         212
#define KM_NORMAL       213
#define KM_LOGNORMAL    214
#define KM_TRUNCNORMAL  215
#define KM_TRUNCLOGNORMAL  216
#define KM_CHI2         217
#define KM_SINE         218

#define KM_GEAR		400
#define KM_JACOBIAN	500

  /* Context bit flags */

#define CN_END	     	0x0000	/* No context */

#define CN_GLOBAL	0x0001
#define CN_EXPERIMENT	0x0002
#define CN_FUNCARG	0x0100

#define CN_ALL	     0xFFFF	/* All contexts */


  /* Analysis Types */

#define AT_NOTSPECD     0       /* Not yet specified */
#define AT_DEFAULTSIM	1	/* Normal simulation */
#define AT_MONTECARLO	2	/* Monte Carlo variations */
#define AT_SETPOINTS	3	/* Set points simulation */
#define AT_GIBBS	4	/* Gibbs estimation */


  /* Options Flags -- bit flags */

#define OF_PARMLIST    0x0001   /* Print parameter list */
#define OF_MCOUTPUTS   0x0002   /* Print MCOutData array -- output values    */
#define OF_MCRESULT    0x0004   /* Print result of MC or SetPoints analysis  */
#define OF_PASSFAIL    0x0008   /* Print result of MC as Pass/Fail [1 or 0]  */
#define OF_MONTEBITS   0x000F

#define OF_COMMENT     0x0010   /* Print a comment (no comment) to outfile */
#define OF_VARNAMES    0x0020   /* Print the variable names (no names)     */
#define OF_VERT_OUTPUT 0x0040   /* Print variables in columns (rows) */
#define OF_NORMALBITS  0x00F0

#define OF_CMDLSEED    0x1000	/* Seed given on command-line */
#define OF_CMDLOUTFILE 0x2000	/* Output filename given on command-line */
#define OF_CMDLBITS    0xF000

  /* Monte Carlo Variation types */

#define MCV_SETPOINTS	(-1)	    /* Not really Monte Carlo */
#define MCV_UNIFORM	    0
#define MCV_LOGUNIFORM	    1
#define MCV_BETA            2
#define MCV_NORMAL          3
#define MCV_LOGNORMAL       4
#define MCV_TRUNCNORMAL     5
#define MCV_TRUNCLOGNORMAL  6
#define MCV_CHI2            7
#define MCV_SINE            8

				    /* Variables names valid in all CN_ */
#define ARGS_MAX 8	/* Maximum number of args to lex */
			/* Used in allocating space for argument strings */

  /* Integration Method types */

#define IM_JACOB 1	/* Use Jacobian */
#define IM_GEAR	 2	/* Differential method */

  /* Integrator spec defaults */

#define DSTEP_DEFAULT		(1.e-8)
#define DSTEP_MIN_DEFAULT	(1.e-12)
#define DSTEP_MAX_DEFAULT	(30.00)
#define ERROR_MAX_DEFAULT	(1.e-6)
#define IM_DEFAULT		IM_GEAR
#define MAX_DERIV_DEFAULT	6

  /* Simulation specification defaults */

#define SEED_DEFAULT 3141592.653589793

#define T0_DEFAULT		0.0
#define TFINAL_DEFAULT		0.0
#define NSIMULATIONS_DEFAULT	0

/* ----- Enumerations  */

/* ----- Typedefs  */

typedef void paramRec;		/* Carry over from Frederic's code */
typedef void controlRec;   

      /*----- Union of two types of variables: constants and input fns */

typedef union tagUVAR {
  double dVal;
  PIFN pifn;
} UVAR; /* tagUVAR */


      /*----- Modification specification for one variable */

typedef struct tagVARMODIFICATION {
  HVAR hvar;		/* Handle to the variable */
  UVAR uvar;		/* Union of variable value or input function spec */

} VARMODIFICATION, *PVARMOD;  /* tagVARMODIFICATION */


	  /*----- Specification of integrator settings */

typedef struct tagINTSPEC {
  double dStep;
  double dStepMin;
  double dStepMax;       /* Current max dynamically set */
  double dStepMaxUser;   /* User specified max */
  double dErrorMax;
  long	 iMethod;	 /* One of IM_ types */
  long   iMaxDeriv;

} INTSPEC, *PINTSPEC;    /* tagINTSPEC */


	  /*----- Print Record:  for info from a Print() statement */

typedef struct tagPRINTREC {
  PSTR szOutputName;
  HVAR hvar;
  int  cTimes;
  PDOUBLE pdTimes;

} PRINTREC, *PPRINTREC;  /* tagPRINTREC */
    

	  /*----- Output specification */

typedef struct tagOUTSPEC {
  PSTR  szOutfilename;		/* Name of file for regular output */
  PFILE pfileOut;		/* Pointer to file */
  BOOL	bCommandLineSpec;	/* Output file specified on command line */
  
  int	nOutputs;		/* Number of outputs */
  PSTR	*pszOutputNames;	/* Array of output names */
  HVAR  *phvar;			/* Array of handles to outputs */

  PLIST plistPrintRecs;		/* List of records from Print()'s */

			/* The list is converted into the following */

  PINT	pcOutputTimes;		/* Count of output times for each var */
  PINT	piCurrentOut;		/* Index to current output for each var */
  PDOUBLE *prgdOutputTimes;	/* Array of output times for each var */
  PDOUBLE *prgdOutputVals;	/* Array of output values for each var */
  
  int cDistinctTimes;		/* Count of distinct output times */
  PDOUBLE rgdDistinctTimes;	/* Array of distinct output times */
  
} OUTSPEC, *POUTSPEC;    /* tagOUTSPEC */


	  /*----- Monte Carlo Variation for one parameter */

#define	SET_MCVAR(pMCvar, h, i, dmin, dmax) \
	  (pMCvar)->hvar = (h); \
	  (pMCvar)->iType = (i); \
	  (pMCvar)->dMin = (dmin); \
	  (pMCvar)->dMax = (dmax); 

typedef struct tagMCVAR {
  HVAR hvar;		/* Handle to variable to be modified */
  int  iType;		/* One of MCV_ types */
  double dParm1, dParm2;/* Shape parms */
  double dMin, dMax;	/* Range */
  double dVal;		/* Value for this run */
  
} MCVAR, *PMCVAR;   /* tagMCVAR */


/* vvvvv from fredi vvvvv */

/* types specific of transforme with MLE */

#define maxData         300   /* max number of data points for comparison */
  
typedef double matTypeT[maxData];
typedef long tabTypeT[maxData];


typedef struct tagMCEXTDATA  {
  long     nbrdy;
  tabTypeT n;      /* nbr of observations */
  matTypeT ssqr;   /* sum of squared deviates from mean */
  matTypeT ybar;   /* means */

} MCEXTDATA, *PMCEXTDATA, dataRec; /* tagMCEXTDATA */


typedef struct tagGIBBSDATA {
  long nMaxIter;                        /*-- Number of iterations */
  long nOutExp;                         /*-- Last n exps are for output */
  long nPhis;				/*-- Last n MCparms are phi parms */
      
  PSTR szGout;				/*-- Filename for Gibbs output */
  PSTR szGparmout;			/*-- Filename to write parms to */
  
  PSTR szGrestart;			/*-- Parm file  for restarting Gibbs */
  PSTR szGdata;				/*-- Filename for Gibbs input data */

} GIBBSDATA;  /* tagGIBBSDATA */



typedef struct tagMCDATAOUT {
  long nbrdy2;   /* number of kinetic ys */
  long nbrdy3;   /* number of other ys */
  matTypeT data;
} MCDATAOUT, *PMCDATAOUT, dataRec2;


	/*-----  Specification for Monte Carlo type experiment */

typedef struct tagMONTECARLO {
  int    nRuns;			/* Number of Monte Carlo runs */
  double dRandTemp;             /* Temporary random number draw */
  BOOL	 bIndependent;		/* Variables independent from run to run */

  int    iRun;			/* Number of current Run */

  int	nPasses, nFails;	/* Number of passes and fails */
  
  PSTR szMCOutfilename;		/* File name for Monte Carlo output */
  PFILE pfileMCOut;		/* File for Monte Carlo output */

  PSTR szMCPassFilename;	/* File name for Monte Carlo output */
  PFILE pfileMCPass;		/* File for Monte Carlo output */

  PSTR szMCFailFilename;	/* File name for Monte Carlo output */
  PFILE pfileMCFail;		/* File for Monte Carlo output */

  PSTR szMCBehavFilename;	/* File name for Monte Carlo output */
  PFILE pfileMCBehav;		/* File for Monte Carlo output */

  PSTR szMCSumFilename; 	/* File name for Monte Carlo output */
  PFILE pfileMCSum;		/* File for Monte Carlo output */

  PSTR szExtDataFilename;	/* File name for external data */
  MCEXTDATA mcextdata;		/* Record of external data file */
  
  PSTR szSetPointsFilename;	/* File name for set points */
  PFILE pfileSetPoints;		/* File of set points */

  PLIST plistMCVars;		/* List of MCVAR record, variation specs */
				/*-- The list is converted to the following */

  long nParms;			/* Count of parameters */
  double *rgdParms;		/* The actually used parameter vector */
  HVAR *rghvar;		        /* Array of handles to the parameters */
  MCVAR **rgpMCVar;		/* A priori distributions for each */

} MONTECARLO, *PMONTECARLO;  /* tagMONTECARLO */


  	/*-----  Record of info about the model */
  
typedef struct tagMODELINFO {
  long		nStates;
  long		nModelVars;

  PDOUBLE 	pdModelVars;
  matType31	rgDeriv;	
  matType1	rgStatesMax;	
  matType1	rgError;
  memRec	mem;
  BOOL		bDirty;			/* The memRec needs to be cleaned */

} MODELINFO, *PMODELINFO;  /* tagMODELINFO */



      	/*-----  Record of information for one experiment.

		 An experiment specifies a set of experimental
		 conditions, parameter settings, input levels, etc.
        */

typedef struct tagEXPERIMENT {
  int iExp;			/* Number of this experiment */
  
  double dT0;			/* Time limits */
  double dTfinal;

  double dTime;			/* Current Time -- not used for global sim */
  long  iStepFlag;		/* difsub flags -- not used for global sim */
  long	iDSFlag;

  PMODELINFO pmodelinfo;	/* Pointer to the model information */
  PLIST plistParmMods;		/* List of parameter mods (elt = PVARMOD) */
  INTSPEC is;			/* Integrator spec, this experiment */
  OUTSPEC os;			/* Output spec, this experiment */

} EXPERIMENT, *PEXPERIMENT;  /* tagEXPERIMENT */

  


    /* Defines an analysis for an input file */

#define MAX_EXPERIMENTS 35

typedef struct tagANALYSIS {

  int iType;			/* Type of analysis. One of AT_ types */
  int fOptions;			/* Options flags -- combination of OF_ above */

  int fCmdOptions;		/* Command line opts, overwrite defaults */
  int fNotOptions;		/* Command line opts, inhibits these options */

  WORD wContext;		/* Context flag used during input processing */
  double dSeed;			/* Random seed used for all analyses */

  MODELINFO	modelinfo;	/* The model we are using */

  EXPERIMENT	expGlobal;	/* Global experiment settings */
				/* List of pointer to input experiments */
  PEXPERIMENT	rgpExps[MAX_EXPERIMENTS];
  PEXPERIMENT   pexpCurrent;	/* Experiment being currently defined */

  MONTECARLO	mc;		/* Monte Carlo specification */
  GIBBSDATA     gd;		/* Gibbs estimate specification */

} ANALYSIS, *PANALYSIS;  /* tagANALYSIS */



  
/* ----- Macros  */

#define AnalysisSetSeed(panal, seed) \
  {if (!(panal->fCmdOptions & OF_CMDLSEED)) \
    (panal)->dSeed = (seed);}

#define AnalysisGetSeed(panal) ((panal)->dSeed)
  
#define DifSub(pexp) \
\
(difsub(&(pexp)->pmodelinfo->nStates,	&(pexp)->dTime,\
        (pexp)->pmodelinfo->pdModelVars,(pexp)->pmodelinfo->rgDeriv,\
	&(pexp)->is.dStep,	&(pexp)->is.dStepMin,	&(pexp)->is.dStepMax,\
	&(pexp)->is.dErrorMax,	&(pexp)->is.iMethod, \
	(pexp)->pmodelinfo->rgStatesMax,(pexp)->pmodelinfo->rgError,\
	&(pexp)->iDSFlag,	&(pexp)->iStepFlag,	&(pexp)->is.iMaxDeriv,\
	&(pexp)->pmodelinfo->mem,	NULL,		NULL))


/* ----- Globals/Externals  */

extern PSTRLEX vrgszlexArgs[];

/* ----- Prototypes  */

void ChooseGrid (int cGridPoints);
void CloseMCFiles (PANALYSIS);
void CorrectInputToTransition (PEXPERIMENT, PDOUBLE);
void CorrectModelToTime(PEXPERIMENT pexp, PDOUBLE pdTtrans);

int DoOneExperiment (PEXPERIMENT pexp);
void DoGibbsEstimation (PANALYSIS panal);

void difsub (long *n,
             double *t_,
	     double *y,
	     double **deriv,
	     double *h_, double *hmin, double *hmax_, double *eps,
	     long *mf,
	     double *ymax_, double *error,
	     long *kflag, long *jstart, long *maxder_,
	     memRec *mem,
	     controlRec *control_,
	     paramRec *param_);

void interpole (double **deriv,
                double *incremTemps,
		long *nbrEq,
		memRec *mem,
		double *temps, double *tToReach,
		double *y, double *yInterpole);

PSTR GetKeyword (int iKWCode);
BOOL GetMCMods (PANALYSIS panal, double rgdOptionalParms[]);
int GetMCVarySpec (PINPUTBUF pibIn, PANALYSIS panal, PSTR szLex);
int GetSetPointsSpec (PINPUTBUF pibIn, PANALYSIS  panal, PSTR szLex);
int GetMonteCarloSpec (PINPUTBUF pibIn, PANALYSIS panal, PSTR szLex);
void GetModelInfo (PMODELINFO pmi);
BOOL GetStringArg (PINPUTBUF pibIn, PSTR *pszArg, PSTR szLex, BOOL bDelim);

long ImFromLex (PSTR szLex);
void InitAnalysis (PANALYSIS panal);
BOOL InitOutputs (PEXPERIMENT pexp, PINT piOut, PDOUBLE pdTout);

void matinv (double **mat, long dim, double *det);
int  McvFromLex (PSTR szLex);
void ModifyParms (PLIST plistParmMods);
void ModifyMCParms (PMONTECARLO pMC);

void NextOutputTime (PEXPERIMENT pexp, PDOUBLE pdTout, PINT piOut);

BOOL PrepareOutSpec (PEXPERIMENT pexp);
int  ProcessMonteCarlo (PINPUTBUF, PANALYSIS, PSTR, int);

BOOL ReadAnalysis (PINPUTBUF);
BOOL ReadExtData (PMONTECARLO pMC);
BOOL ReadSetPointData (PMONTECARLO pMC);

void SaveOutputs (PEXPERIMENT pexp, PDOUBLE pdTout, PDOUBLE pdTrans);
void NewSaveOutputs (PEXPERIMENT pexp, PDOUBLE pdTout, PDOUBLE pdTrans);
void SetOptions (PANALYSIS panal);

void SetParms (long cParms, HVAR *rghvar, double *rgdParm);
void SetParmsLog (long cParms, HVAR *rghvar, double *rgdParm);

void ShowHelp (char *szKeyword);
void ShowHelpMessage (char *const szProgName);

void TransformData (PANALYSIS, PMCDATAOUT);

void WriteArray (FILE *pfile, long cElems, double *rg);
void WriteArrayLog (FILE *pfile, long cElems, double *rg);
void WriteMCOutput (PANALYSIS, PMCDATAOUT);
void WriteNormalOutput (PANALYSIS, PEXPERIMENT);
void WriteMCSummary (PANALYSIS panal);
     
BOOL YesNoFromLex (PSTR szLex);

