|
|
/******************************************************
|
|
|
* MadDeriveEngine is the private module used to derive
|
|
|
* all possible requested methods given the existence
|
|
|
* of measured parameters and methods to derive parameters
|
|
|
* as defined in madDeriveMethods. This module is not
|
|
|
* meant to be used by any end user - all public methods are
|
|
|
* exposed via the maddata module.
|
|
|
*
|
|
|
* The madDeriveEngine contains no code whatsoever that
|
|
|
* pertains to the meaning of any particular parameter - that
|
|
|
* code is entirely in madDeriveMethods. The purpose of
|
|
|
* this code is to analyze at runtime the available measured
|
|
|
* parameters and derivation methods to plan which methods need
|
|
|
* to be called, given which parameters were requested. For
|
|
|
* that reason, this module should never need to be modified
|
|
|
* to extend or modify the derivations methods, except to
|
|
|
* register new methods in the global gCompExtList. The module
|
|
|
* madDeriveMethods both documents how all derivation
|
|
|
* methods work, and how to add more. This module populates
|
|
|
* the maddata data structures by calling the methods in
|
|
|
* madDeriveMethods. It is responsible for copying data into
|
|
|
* input arrays for those methods, and copy out the data it needs.
|
|
|
*
|
|
|
* The madDeriveEngine was built to be both flexible and fast.
|
|
|
* It tries to minimize the number of calls required to
|
|
|
* madDeriveMethods by testing filters as soon as possible in order
|
|
|
* to drop records or 2D rows as soon as possible. This basic
|
|
|
* algorithm is as follows:
|
|
|
* - if the analysis says a filter depends on an underivable
|
|
|
* parameter, the record is rejected immediately.
|
|
|
* - 1D measured data is read in
|
|
|
* - Any filter that depends on only 1D measured data is applied
|
|
|
* - all 1D data is derived
|
|
|
* - Any filter that depends on only 1D data is applied
|
|
|
* 2D loop:
|
|
|
* - 2D measured data is read in
|
|
|
* - Any filter that depends on only 2D measured data is applied
|
|
|
* - all 2D data is derived
|
|
|
* - Remaining filters are applied
|
|
|
*
|
|
|
* There are three basic data structures in this module: CompiledExt,
|
|
|
* InfoDerived, and InfoDerivedFile. CompiledExt defines everything the
|
|
|
* madDeriveEngine needs to know about a particular derivation method.
|
|
|
* InfoDerived contains everything needed to handle one particular record
|
|
|
* type, where a record type is defined by an ordered list of 1D and 2D
|
|
|
* measured Madrigal parameters. InfoDerivedFile contains a list of
|
|
|
* InfoDerived structs, one for each record type found in a file. Note that
|
|
|
* only the InfoDerivedFile struct deals in any way with Cedar files; the
|
|
|
* InfoDerived struct and its methods are storage neutral, and could be used
|
|
|
* for data stored in another format such as a relational database.
|
|
|
*
|
|
|
* These data structures contain a number of members that begin map* and
|
|
|
* are int arrays. These maps are designed for rapid copying of arrays
|
|
|
* of doubles into and out of methods, and into new maddata objects when
|
|
|
* they need to be created.
|
|
|
*
|
|
|
* While this module is written in C and not C++; its methods
|
|
|
* and design are as close as I could get to object-oriented.
|
|
|
* Every data structure should be instantiated via a create*
|
|
|
* method and released via destroy*. All other methods take
|
|
|
* the respective data structure pointer as the first argument.
|
|
|
*/
|
|
|
|
|
|
#ifndef _MAD_DERIVE_ENGINE_
|
|
|
#define _MAD_DERIVE_ENGINE_
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
#include <stdio.h>
|
|
|
#include <cedarIO.h>
|
|
|
#include <madrec.h>
|
|
|
#include <cedar.h>
|
|
|
#include <maddata.h>
|
|
|
|
|
|
#define MAX_NEEDED_METH 500 /* upper limit to number of methods a method can depend on */
|
|
|
#define NUM_PROLOG_PARM 18 /* The number of 1D parameters that are loaded via the prolog */
|
|
|
#define NUM_2D_PROLOG_PARM 1 /* The number of 2D parameters that are loaded via the prolog */
|
|
|
#define CYC_CODE 95 /* The only parameter read by the engine directly, since cycle */
|
|
|
/* is a fundamental part of the maddata structure */
|
|
|
#define MAX_2D_ROWS 100000 /* maximum number of 2D rows a multi-row method can handle */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct compiledExt {
|
|
|
|
|
|
/* this structure holds all data for a single compiled extension */
|
|
|
|
|
|
int (*compExt) (int inCount,
|
|
|
double * inputArr,
|
|
|
int outCount,
|
|
|
double * outputArr,
|
|
|
FILE * errFile);
|
|
|
|
|
|
int inputCount; /* number of input mnemonics */
|
|
|
const char ** inputMnemList; /* pointer to char array of MNEM names, len=inputCount */
|
|
|
int outputCount; /* number of output mnemonics */
|
|
|
const char ** outputMnemList; /* pointer to char array of MNEM names, len=outputCount */
|
|
|
|
|
|
} CompiledExt;
|
|
|
|
|
|
|
|
|
typedef struct compiledMultiRowExt {
|
|
|
|
|
|
/* this structure holds all data for a single compiled extension that deals with multiple rows at once */
|
|
|
|
|
|
int (*compExt) (int numRows,
|
|
|
int inCount,
|
|
|
double ** inputArr,
|
|
|
int outCount,
|
|
|
double ** outputArr,
|
|
|
FILE * errFile);
|
|
|
|
|
|
int inputCount; /* number of input mnemonics */
|
|
|
const char ** inputMnemList; /* pointer to char array of MNEM names, len=inputCount */
|
|
|
const int * inputMnemType; /* pointer to int array of MNEM types (1 or 2), len=inputCount */
|
|
|
int outputCount; /* number of output mnemonics */
|
|
|
const char ** outputMnemList; /* pointer to char array of MNEM names, len=outputCount */
|
|
|
const int * outputMnemType; /* pointer to int array of MNEM types (1 or 2), len=outputCount */
|
|
|
|
|
|
} CompiledMultiRowExt;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _infoMethod {
|
|
|
|
|
|
/* this structure is used to hold information about how to use each derived */
|
|
|
/* parameter method for a given record type. Each InfoDerived struct contains */
|
|
|
/* a list of these, with len = total number of derived methods */
|
|
|
|
|
|
int numInputMethods; /* how many methods does this method depend on ? */
|
|
|
int neededMethods[MAX_NEEDED_METH]; /* which methods? (refers to gCompExtList) */
|
|
|
int all1D; /* are all inputs 1D? */
|
|
|
int isAvailable; /* can all inputs be calculated? */
|
|
|
int isNeeded; /* does method need to be called? */
|
|
|
int * inputMap; /* where in InfoDerived.allUsed?DParmList does */
|
|
|
/* this input come from? Length of this array is */
|
|
|
/* 2* number of inputs for method. First int in */
|
|
|
/* pair is either 1 or 2 depending on whether */
|
|
|
/* input is 1D or 2D, second is index into that */
|
|
|
/* array. */
|
|
|
int * outputMap; /* index into InfoDerived.allUsed?DParmList for */
|
|
|
/* output data. If all1D, refers to 1DParmList, */
|
|
|
/* else refers to 2DParmList. Length of this */
|
|
|
/* array is number of outputs for method. A */
|
|
|
/* value of -1 is used to indicate the output */
|
|
|
/* should be ignored because previously */
|
|
|
/* determined. */
|
|
|
|
|
|
} InfoMethod;
|
|
|
|
|
|
|
|
|
typedef struct _infoMultiRowMethod {
|
|
|
|
|
|
/* this structure is used to hold information about how to use each multi-row */
|
|
|
/* method for a given record type. Each InfoDerived struct contains */
|
|
|
/* a list of these, with len = total number of derived multi-row methods */
|
|
|
|
|
|
int isNeeded; /* does method need to be called? */
|
|
|
int numInputs; /* number of inputs for this method */
|
|
|
int numOutputs; /* number of outputs for this method */
|
|
|
int * inputMap; /* where in InfoDerived.allUsed?DParmList does */
|
|
|
/* this input come from? If compiledMultiRowExt */
|
|
|
/* ->inputMnemType = 1, refers to 1DParmList, */
|
|
|
/* else refers to 2DParmList. Length of this */
|
|
|
/* array is number of inputs for method. */
|
|
|
double ** inputArr; /* temp storage for 1 and 2D inputs, */
|
|
|
/* len = numInputs. If 2D, array len = MAX_2D_ROWS */
|
|
|
double ** outputArr; /* temp storage for 1 and 2D outputs, */
|
|
|
/* len = numOutputs. If 2D, array len = MAX_2D_ROWS */
|
|
|
} InfoMultiRowMethod;
|
|
|
|
|
|
|
|
|
typedef struct _infoDerived {
|
|
|
|
|
|
/* this structure is used to hold all information used when */
|
|
|
/* deriving parameters for a given record type, where a */
|
|
|
/* record type is defined by an ordered list of 1D and 2D */
|
|
|
/* measured parameters */
|
|
|
|
|
|
int numDervMeth; /* total number of derived methods */
|
|
|
InfoMethod ** infoMethodArr; /* array of InfoMethod about each derived method */
|
|
|
/* length = numDervMeth */
|
|
|
int numMultiRowMeth; /* total number of multi-row derived methods */
|
|
|
InfoMultiRowMethod ** infoMultiRowMethArr; /* array of InfoMultiRowMethod about each multi-row derived method */
|
|
|
/* length = numMultiRowMeth */
|
|
|
int anyMultRowNeeded; /* int indicates whether any multi-row method needed */
|
|
|
MadparmList * meas1DParmList; /* list of 1D parameters measured */
|
|
|
int * meas1DCodeList; /* list of 1D parameter codes - used for rapid access */
|
|
|
/* Len = len of meas1DParmList - NUM_PROLOG_PARM */
|
|
|
MadparmList * meas2DParmList; /* list of 2D parameters measured */
|
|
|
int * meas2DCodeList; /* list of 2D parameter codes - used for rapid access */
|
|
|
/* Len = len of meas2DParmList */
|
|
|
MadparmList * requestedParmList; /* list of parameters requested */
|
|
|
MadparmList * req1DParmList; /* list of requested parameters found to be 1D - includes unavailable parms */
|
|
|
int * mapReq1DParmList; /* int array that specifies index into allUsed1DParmList of each 1D parm */
|
|
|
/* If parameter unavailable, = -1 */
|
|
|
MadparmList * req2DParmList; /* list of requested parameters found to be 2D */
|
|
|
int * mapReq2DParmList; /* int array that specifies index into allUsed2DParmList of each 2D parm */
|
|
|
MadparmList * unavailParmList; /* list of parameters found to not be available */
|
|
|
MadparmList * allUsed1DParmList; /* list of all 1D parameters used in derivation */
|
|
|
MadparmList * allAvail1DParmList; /* list of all 1D parameters that can be derived */
|
|
|
MadparmList * allUsed2DParmList; /* list of all 2D parameters used in derivation */
|
|
|
MadparmList * allAvail2DParmList; /* list of all 2D parameters that can be derived */
|
|
|
double * all1DParm; /* array of doubles of len = len(allUsed1DParmList) */
|
|
|
double * all2DParm; /* array of doubles of len = len(allUsed2DParmList) */
|
|
|
double * tmpInputParm; /* array of doubles of len = len(allUsed1DParmList) + */
|
|
|
/* len(allUsed2DParmList) - used to pass input parms to */
|
|
|
/* methods */
|
|
|
double * tmpOutputParm; /* array of doubles of len = len(allUsed1DParmList) + */
|
|
|
/* len(allUsed2DParmList) - used to get output parms */
|
|
|
/* from methods */
|
|
|
int validFilters; /* if 1, all filters can potentially be applied, if 0, */
|
|
|
/* some filter uses unavailParmList and always rejects */
|
|
|
MadfilterList * filt1DList; /* the list of zero or more 1D filters to apply */
|
|
|
int * onlyMeas1DList; /* a list of int of len=filt1DList len. If 1, 1D */
|
|
|
/* filter uses only measured parameters */
|
|
|
int * mapFilt1DParm; /* an int array used to map filter parameters from filt1DList to */
|
|
|
/* allUsed1DParmList. Len = 2*filt1DList len, because each filter */
|
|
|
/* has two parameters. If filter has only one parameter, second */
|
|
|
/* value will be -1 */
|
|
|
MadfilterList * filt2DList; /* the list of zero or more 2D filters to apply */
|
|
|
int * onlyMeas2DList; /* a list of int of len=filt2DList len. If 1, 2D */
|
|
|
/* filter uses only 2D measured parameters (and */
|
|
|
/* possibly a 1D parameter) */
|
|
|
int * mapFilt2DParm; /* an int array used to map filter parameters from filt2DList to */
|
|
|
/* allUsed1DParmList and allUsed2DParmList. Len = 4*filt1DList */
|
|
|
/* len. For each filter, there are four ints: */
|
|
|
/* 1. 1 if first parm is 1D, 2 if 2D */
|
|
|
/* 2. index into either allUsed1DParmList and allUsed2DParmList */
|
|
|
/* 3. 1 if 2nd parm is 1D, 2 if 2D (or -1 if single parameter) */
|
|
|
/* 4. index as in 2 for 2nd parameter (or -1 if single parameter) */
|
|
|
} InfoDerived;
|
|
|
|
|
|
typedef struct _infoDervFile {
|
|
|
|
|
|
/* this structure is used to hold an array of InfoDerived */
|
|
|
/* for an entire file, and a list of records each */
|
|
|
/* InfoDerived is relevant to */
|
|
|
|
|
|
int numTypesRec; /* number of different types of records in file */
|
|
|
int * numEachTypeRec; /* an array of int of len=numTypesRec, each int */
|
|
|
/* gives the number of records of that type in */
|
|
|
/* file */
|
|
|
int * cycleNum; /* an array of ints that give the cycle number */
|
|
|
/* of each data record. Len = # data records */
|
|
|
int ** eachTypeList; /* an array of int arrays, len=numTypesRec. Each */
|
|
|
/* list's length is given by value in */
|
|
|
/* numEachTypeRec. Each list contains list of */
|
|
|
/* record numbers of that type in file */
|
|
|
InfoDerived ** infoDervList; /* An array of InfoDerived structs, one for each */
|
|
|
/* numTypesRec */
|
|
|
} InfoDervFile;
|
|
|
|
|
|
|
|
|
|
|
|
/* Method declarations */
|
|
|
|
|
|
InfoMethod * createInfoMethod(int numInputs, int numOutputs);
|
|
|
|
|
|
void destroyInfoMethod(InfoMethod * infoMethod);
|
|
|
|
|
|
InfoMultiRowMethod * createInfoMultiRowMethod(int numInputs,
|
|
|
const int * inputType,
|
|
|
int numOutputs,
|
|
|
const int * outputType);
|
|
|
|
|
|
void destroyInfoMultiRowMethod(InfoMultiRowMethod * infoMultiRowMethod);
|
|
|
|
|
|
InfoDervFile * createInfoDervFile(Madrec * madrecp,
|
|
|
MadparmList * requestParm,
|
|
|
MadfilterList * filtList,
|
|
|
FILE * errFile);
|
|
|
|
|
|
void destroyInfoDervFile(InfoDervFile * infoDervFile);
|
|
|
|
|
|
int getRecType(InfoDervFile * infoDervFile, int recno);
|
|
|
|
|
|
void load1DMeasData(InfoDervFile * infoDervFile,
|
|
|
Madrec * madrecp,
|
|
|
int recType,
|
|
|
double first_ibyr,
|
|
|
double first_ibdt,
|
|
|
double first_ibhm,
|
|
|
double first_ibcs);
|
|
|
|
|
|
void load2DMeasData(InfoDervFile * infoDervFile,
|
|
|
Madrec * madrecp,
|
|
|
int recType,
|
|
|
int row);
|
|
|
|
|
|
void load1DMultiRowData(InfoDervFile * infoDervFile,
|
|
|
int recType);
|
|
|
|
|
|
void load1DMultiRowDataNonfile(InfoDerived * infoDerived);
|
|
|
|
|
|
void load2DMultiRowData(InfoDervFile * infoDervFile,
|
|
|
int recType,
|
|
|
int count2D);
|
|
|
|
|
|
void load2DMultiRowDataNonfile(InfoDerived * infoDerived,
|
|
|
int count2D);
|
|
|
|
|
|
int evaluateFilter(InfoDervFile * infoDervFile,
|
|
|
int recType,
|
|
|
int dim,
|
|
|
int filtIndex);
|
|
|
|
|
|
int appendMadrecord(Maddata * maddata,
|
|
|
InfoDerived * infoDerv,
|
|
|
int cycIndex,
|
|
|
int typeIndex,
|
|
|
Rec_type rectype,
|
|
|
char * text,
|
|
|
int kinst,
|
|
|
double starttime,
|
|
|
double endtime);
|
|
|
|
|
|
|
|
|
int updateMadrecordWithMultiRow(Maddata * maddata,
|
|
|
InfoMultiRowMethod * infoMultiRowMeth,
|
|
|
int methIndex,
|
|
|
int cycIndex,
|
|
|
int recIndex,
|
|
|
int typeIndex,
|
|
|
int numRows);
|
|
|
|
|
|
int append2DRow(Maddata * maddata,
|
|
|
InfoDerived * infoDerv,
|
|
|
int cycIndex,
|
|
|
int typeIndex,
|
|
|
int recIndex);
|
|
|
|
|
|
InfoDerived * createInfoDerived(MadparmList * meas1DParmList,
|
|
|
MadparmList * meas2DParmList,
|
|
|
MadparmList * requestedParmList,
|
|
|
MadfilterList * filtList);
|
|
|
|
|
|
void destroyInfoDerived(InfoDerived * info);
|
|
|
|
|
|
int hasOutput(const CompiledExt * exten, const char * mnem);
|
|
|
|
|
|
void checkIf1DMethodNeeded(InfoDerived * infoDeriv,
|
|
|
int methIndex,
|
|
|
MadparmList * filtParmsNotRequestedList);
|
|
|
|
|
|
void checkIf2DMethodNeeded(InfoDerived * infoDeriv,
|
|
|
int methIndex,
|
|
|
MadparmList * filtParmsNotRequestedList);
|
|
|
|
|
|
void make1DMethodNeeded(InfoDerived * infoDeriv, int methIndex);
|
|
|
|
|
|
void make2DMethodNeeded(InfoDerived * infoDeriv, int methIndex);
|
|
|
|
|
|
void checkIfMultiRowMethodNeeded(InfoDerived * infoDeriv,
|
|
|
int methIndex);
|
|
|
|
|
|
int dispatchMethod(InfoDerived * infoDeriv, int methIndex, FILE * errFile);
|
|
|
|
|
|
int dispatchMultiRowMethod(InfoDerived * infoDeriv,
|
|
|
int methIndex,
|
|
|
int numRows,
|
|
|
FILE * errFile);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|