/**---------------------------------------------------------------------------
 ** 
 ** vgeo.h -- 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/08/04 14:56:48
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/08/04 15:22:55
 ** Update Count    : 12
 ** Directory       : /home/pego/pcd1/codas3c/gfi/src/apps/util/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    Undocumented.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

#include "geninc.h"
#include "profmask.h"
#include "ioserv.h"
#include "dbsource.h"
#include "use_db.h"
#include "vector.h"
#include "vstat.h"
#include "ocean.h"
#include "gfimisc.h"
#include "gfidb.h"
#include "gfimath.h"

/* ------------------------------------------------------------------
	 -Types:
	 
	 There are two main structures:

	    VGEO_TYPE contains data changing during the programme
			
			VGEO_REF_TYPE contains data relative to the way reference level is
			              calculated.

	 At startup, all values for VGEO_REF_TYPE are set to default.
	 ------------------------------------------------------------------ */

/* 
	 Space to hold correspondance between a selected keyword and its associated
	 list of options
	 */
typedef struct
{
	int code;
	OPTION_TYPE *list;
} VGEO_OPTION_TABLE_TYPE;

/*
	Space for holding all options
	*/
typedef struct
{
	int            data_format;      /* Data format of external file       */
	FILE_NAME_TYPE data_file;        /* File name for external data        */	
	RANGE_TYPE     data_range;       /* Range of external data to consider */
	ULONG          bits;             /* Option flags                       */
	int            ref_method;       /* Reference method to use            */
	double         z0;               /* Reference level                    */  
	double         v0;               /* Reference velocity                 */
	int            ctd_good_bins;    /* Min allowed good bins in CTD       */
	int            data_good_bins;   /* Minimum allowed number of bins     */ 
	int            data_interp_axis; /* Interpolation axis for data        */
	int            nprf_method;      /* Method for number of data profiles */
	int            n_profiles;       /* Number of profiles                 */
	int            adcp_uv_ref;      /* ADCP velocity reference            */
	int            ctd_sort_axis;    /* Axis for sorting CTD profiles      */
	int            ctd_steps;        /* Number of CTD profiles to move     */
	LONG           ctd_time_offset;  /* Time correction for CTD profiles   */
	int            time_tolerance;   /* Time tolerance (seconds)           */
	DOUBLE         good_prof_ratio;  /* Min ratio of good data profiles    */
	int            vgeo_axis_dir;    /* Axis direction for vgeo            */
	DOUBLE         vgeo_scale;       /* Output scale for velocities        */
	FLOAT          *grid;            /* Output grid points                 */
	int            n_grid;           /* Number of grid points              */
} VGEO_OPTIONS_TYPE;

/*
	Space for holding all file pointers
	*/
typedef struct
{
	int  n;                        /* Number of files       */
	FILE **first;                  /* Pointer to first file */
	FILE *fp_con;                  /* Output contour file   */
	FILE *fp_log;                  /* Log file              */
	FILE *fp_sta;                  /* Statistics file       */
	FILE *fp_grd;                  /* Grid values           */
	FILE *fp_asc;                  /* ASCII ADCP data       */
} VGEO_FILES_TYPE;

/*
	Space for holding data from a ctd profile 
	*/
typedef struct {    
	int            n;              /* Number of data         */
	DOUBLE         yd;             /* Decimal day            */ 
	DOUBLE_LL_TYPE pos;            /* Longitude and latitude */
	DOUBLE         *rho;           /* Density                */
	DOUBLE         *z;             /* Depth                  */
} VGEO_CTD_PRF_TYPE;

/*
	Space for holding external current profile data
	*/
typedef struct {
	int            n;     /* Number of data elements in profile */
	DOUBLE         yd;    /* Profile time                       */
	DOUBLE_LL_TYPE pos;   /* Profile position                   */
	DOUBLE         *u;    /* Eastward current component         */
	DOUBLE         *v;    /* Northward current component        */
	DOUBLE         *z;    /* Depths                             */
} VGEO_EXT_PRF_TYPE;

/*
	Space to hold consecutive profiles of external data 
	*/
typedef struct {
	int               n;      /* Number of profiles            */
	VGEO_EXT_PRF_TYPE *data;  /* Pointer to arrays of profiles */
} VGEO_EXT_TYPE;

/*
	Space for holding a profile of geostrophic current
	*/
typedef struct {       
	int            n;              /* Number of data                  */
	DOUBLE         *v;             /* Geostrophic current             */
	DOUBLE         *z;             /* Depth                           */
	DOUBLE         yd;             /* time                            */
	DOUBLE_LL_TYPE pos;            /* Position                        */
	DOUBLE unit_vector[2];         /* Unit vector orthogonal to track */
} VGEO_VGEO_TYPE;

/*
	Structure for holding two consecutive ctd profiles
	*/
typedef struct {                
	VGEO_CTD_PRF_TYPE prev;
	VGEO_CTD_PRF_TYPE this;
} VGEO_CTD_TYPE;
	
/*
	Structure for holding regridded geostrophic current
	*/
typedef struct {
	int n;
	DOUBLE *z;
	DOUBLE *v;
} VGEO_VGRID_TYPE;

/*
	Structure for holding reference data
	*/
typedef struct {
	DOUBLE z;                      /* Depth of reference level             */ 
	DOUBLE v;                      /* Value of reference velocity          */ 
	DOUBLE e;                      /* Error on reference velocity          */
	int    n;                      /* Number of points used to get ref.    */
} VGEO_REF_TYPE;

typedef struct {
	int n;                         /* Number of profile times in array     */
	YMDHMS_TIME_TYPE *times;       /* Sorted CTD profile times             */
} VGEO_PRFT_TYPE;

typedef struct {
	VGEO_REF_TYPE    ref;          /* Reference level data                 */
	VGEO_VGEO_TYPE   vgeo;         /* Geostrophic current                  */
	TIME_RANGE_TYPE  trng;         /* CTD time range                       */
	VGEO_CTD_TYPE    ctd;          /* CTD profiles                         */
	VGEO_PRFT_TYPE   prft;         /* Sorted VTD profile times             */
	VGEO_FILES_TYPE  fps;          /* File pointers                        */
	VGEO_VGRID_TYPE  grid;         /* Regrided vgeo velocities             */
} VGEO_TYPE;

/* ------------------------------------------------------------------
	 -Functions:
	 ------------------------------------------------------------------ */

#if PROTOTYPE_ALLOWED
char *vgeo_read_options(FILE *fp, char *arg, int code);
#else
char *vgeo_read_options();
#endif

#if PROTOTYPE_ALLOWED
char *vgeo_read_grid(FILE *fp, char *arg, int code);
#else
char *vgeo_read_grid();
#endif

/* ------------------------------------------------------------------
	 -Global Variables:
	 ------------------------------------------------------------------ */
static VGEO_OPTIONS_TYPE opts;
static int year_base;
static FILE_NAME_TYPE ctd_db_name;
static FILE_NAME_TYPE output;

/* ------------------------------------------------------------------
	 -Definitions:
	 ------------------------------------------------------------------ */
#define VGEO_ERROR_CODE        -999
#define VGEO_EXIT_CODE         -998
#define UNKNOWN_CODE            999

/* 
	 Database identifiers               
	 */ 
#define CTD_DBID_CODE         1 
#define ADCP_DBID_CODE        2 

/*
	Index codes to the option keyword lists
	*/
#define REFERENCE_METHOD_INDEX 1    /* Select reference method              */
#define CTD_SORT_AXIS_INDEX    2    /* Select CTD sort axis                 */
#define VGEO_AXIS_DIR_INDEX    3    /* Select vgeo axis direction           */
#define OUTPUT_GRID_INDEX      4    /* Select output grid                   */
#define DATA_FORMAT_INDEX      11   /* Select data file format              */
#define NPRF_METHOD_INDEX      12   /* Method for number of data profiles   */
#define INTERP_AXIS_INDEX      13   /* Select interpolation axis for data   */
#define ADCP_REFERENCE_INDEX   14   /* Select reference for adcp velocities */

/*
	Codes for the different methods
	*/

#define ADCP_MIN_SHEAR_METHOD   1   /* ref from adcp min shear            */
#define CTD_MAX_DEPTH_METHOD    2   /* ref from ctd max common depth      */
#define CONST_DEPTH_METHOD      3   /* ref from constant values           */
#define ASCII_DATA_METHOD      11   /* data from ascii file               */
#define CODAS_DB_METHOD        12   /* data from codas db                 */
#define NPRF_CONST_METHOD      21   /* data from const number of profiles */ 
#define NPRF_BCTD_METHOD       22   /* data from profiles between ctd     */
#define ADCP_NOREF_METHOD      31   /* no adcp velocity ref               */
#define ADCP_SHIPREF_METHOD    32   /* adcp velocity ref from ship        */
#define ADCP_NAVREF_METHOD     33   /* adcp velocity ref from nav         */
#define GRID_LIST_METHOD       41   /* grid points from a list            */

/*
	Codes for axis directions
	*/
#define NORTH_DIRECTION_CODE   51
#define SOUTH_DIRECTION_CODE   52
#define WEST_DIRECTION_CODE    53
#define EAST_DIRECTION_CODE    54

/*
	Codes for positionnal axis names
	*/
#define VGEO_TIME_CODE              61
#define VGEO_LONGITUDE_CODE         62
#define VGEO_LATITUDE_CODE          63

/* Special Flags */
#define LON_180_CODE            0 
#define USE_ADCP_POSITION_CODE  1
#define STAT_OUTPUT_CODE        2
#define LOG_OUTPUT_CODE         3
#define CONTOUR_OUTPUT_CODE     4
#define USE_PROFILE_FLAGS_CODE  5
#define REGRID_OUTPUT_CODE      6

/* Codes for selecting specific structures */
#define VGEO_EXT_PRF_CODE       0
#define VGEO_EXT_CODE           1
#define VGEO_PRFT_CODE          2
#define VGEO_CTD_PRF_CODE       3
#define VGEO_CTD_CODE           4
#define VGEO_VGEO_CODE          5
#define VGEO_CODE               6
#define VGEO_OPTIONS_CODE       7
#define VGEO_VGRID_CODE         8


/* ------------------------------------------------------------------
	 -Name Lists:
	 ------------------------------------------------------------------ */

/* 
	 Define code for the different methods for getting the reference 
*/
NAME_LIST_ENTRY_TYPE method_name_list[]=
{
	{"adcp_min_H_shear", ADCP_MIN_SHEAR_METHOD},  
	{"ctd_max_depth",    CTD_MAX_DEPTH_METHOD },
	{"const_depth",      CONST_DEPTH_METHOD   },
	{NULL, 0}
};

/*
	Define positionnal axes names. These are used for sorting and interpolating
	data 
	*/
NAME_LIST_ENTRY_TYPE axis_name_list[]=
{
	{"none",      VGEO_TIME_CODE     },
	{"time",      VGEO_TIME_CODE     },
	{"longitude", VGEO_LONGITUDE_CODE},
	{"latitude",  VGEO_LATITUDE_CODE },
	{NULL, 0}
};

/* 
	 Define axis direction names. These are used for calculating the current
	 projections and the geostrophic current
	 */
NAME_LIST_ENTRY_TYPE axis_dir_name_list[]=
{
	{"northward", NORTH_DIRECTION_CODE},
	{"southward", SOUTH_DIRECTION_CODE},
	{"westward",  WEST_DIRECTION_CODE },
	{"eastward",  EAST_DIRECTION_CODE },
	{NULL, 0}
};

/*
	Define names for specifying an output grid
	*/
NAME_LIST_ENTRY_TYPE grid_name_list[]=
{
	{"grid_list:", GRID_LIST_METHOD},
	{NULL, 0}
};

/*
	Define names for spcifying how absolute adcp current should calculated
	*/
NAME_LIST_ENTRY_TYPE adcp_ref_name_list[]=
{
  {"none",       ADCP_NOREF_METHOD  },
	{"ship",       ADCP_SHIPREF_METHOD},
	{"navigation", ADCP_NAVREF_METHOD },
	{NULL, 0}
};

/*
	Define names for specifying the access to data. CTD data are always read
	from a CODAS database, but reference and/or ADCP data may be supplied from
	different media
	*/
NAME_LIST_ENTRY_TYPE data_format_name_list[]=
{
  {"codas_db", CODAS_DB_METHOD  },
	{"ascii"   , ASCII_DATA_METHOD},
	{NULL, 0}
};

/*
	Define names for the number of profiles to use to get the geostrophic
	reference 
	*/
NAME_LIST_ENTRY_TYPE nprf_method_name_list[]=
{
  {"constant"   , NPRF_CONST_METHOD},
	{"between_ctd", NPRF_BCTD_METHOD },
	{NULL, 0}
};

/* ------------------------------------------------------------------
	 -Parameters:
	 ------------------------------------------------------------------ */

PARAMETER_LIST_ENTRY_TYPE vgeo_param[]=
{
	{" year_base:", "%d"  , (char *) &year_base , TYPE_INT   },
	{" ctd_db:"   , "%79s", (char *) ctd_db_name, TYPE_STRING},
	{" output:"   , "%79s", (char *) output     , TYPE_STRING},
  {NULL, NULL, NULL, 0}
};

/* ------------------------------------------------------------------
	 -Options:
	 ------------------------------------------------------------------ */

/*
	Options for getting adcp reference from a fixed number of profiles centered
	on the profile for geostrophic current
	*/
OPTION_TYPE nprf_const_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{ /* Number of adcp profiles */
		"nprf=", TYPE_INT, op_get_param, (char *) &(opts.n_profiles)
	},
	{NULL, 0, NULL, (char *) NULL}
};

/*
	List of all sub options for vgeo_sub_list_of_kw
	*/

VGEO_OPTION_TABLE_TYPE vgeo_sub_list_of_options[]=
{
	{ NPRF_CONST_METHOD, nprf_const_options },
	{ 0, NULL}
};

/*
	Keyword list and actions for adcp minimum shear method */
XOPTION_TYPE vgeo_sub_list_of_kw[]=
{
	{ /* Method for accessing external data */
		DATA_FORMAT_INDEX, (char *) &(opts.data_format), 
		vgeo_read_options, TYPE_INT, data_format_name_list,
		(char *) vgeo_sub_list_of_options
	},
	{ /* Method defining the number of profiles to use */
		NPRF_METHOD_INDEX, (char *) &(opts.nprf_method), 
		vgeo_read_options, TYPE_INT, nprf_method_name_list, 
		(char *) vgeo_sub_list_of_options
	},
	{ /* Getting interpolation axis for data */
		INTERP_AXIS_INDEX, (char *) &(opts.data_interp_axis),
		vgeo_read_options, TYPE_INT, axis_name_list, 
		(char *) vgeo_sub_list_of_options
	},
	{ /* Getting reference for adcp velocity */
		ADCP_REFERENCE_INDEX, (char *) &(opts.adcp_uv_ref), 
		vgeo_read_options, TYPE_INT, adcp_ref_name_list, 
		(char *) vgeo_sub_list_of_options
	},
	{ 0, NULL, NULL, 0, NULL, NULL}  
};

	
/* 
	 Options for ADCP minimum shear (AMS) method 
	 */
OPTION_TYPE adcp_min_shear_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{ /* Range to consider from external data */
		"range:", 0, op_get_range, (char *) &(opts.data_range)
	},
	{ /* Method to use when getting profiles from external data */
		"data_profiles:", NPRF_METHOD_INDEX, op_get_keyword, 
		(char *) vgeo_sub_list_of_kw
	},
	{ /* Minimum percent of good profiles allowed to calculate minimum shear
			 statistics */
		"profile_tolerance=", TYPE_DOUBLE, op_get_param, 
		(char *) &(opts.good_prof_ratio)
	},
	{ /* Do not consider profiles of external data containing less than this
			 number of good z levels */
		"data_good_bins=", TYPE_INT, op_get_param, (char *) &(opts.data_good_bins)
	},
	{ /* Name of file containing external data */
		"data_file:", TYPE_STRING, op_get_param, (char *) opts.data_file
	},
	{ /* Set position of geostrophic profile from external data */
		"use_adcp_pos", USE_ADCP_POSITION_CODE, set_long_bit, 
		(char *) &(opts.bits)
	},
	{ /* Flag data according to profile flags */
		"flag_data", USE_PROFILE_FLAGS_CODE, set_long_bit, 
		(char *) &(opts.bits)
	},
	{ /* Method for accessing external data */
		"data_format:", DATA_FORMAT_INDEX, op_get_keyword, 
		(char *) vgeo_sub_list_of_kw
	},
	{ /* Interpolation axis */
		"data_interp_axis:", INTERP_AXIS_INDEX, op_get_keyword, 
		(char *) vgeo_sub_list_of_kw
	},
	{ /* Method for getting adcp reference velocity */
		"adcp_reference:", ADCP_REFERENCE_INDEX, op_get_keyword, 
		(char *) vgeo_sub_list_of_kw
	},
	{NULL, 0, NULL, (char *) NULL}
};

/*
	Options for setting reference at constant depth
	*/
OPTION_TYPE const_depth_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{ /* Reference level */
		"z=",  TYPE_DOUBLE, op_get_param, (char *) &(opts.z0)
	},
	{ /* Reference velocity */
		"v=",  TYPE_DOUBLE, op_get_param, (char *) &(opts.v0)
	},
	{NULL, 0, NULL, (char *) NULL}
};

/*
	Options for setting reference at the deepest common CTD level
	*/
OPTION_TYPE ctd_max_depth_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{ /* Reference velocity to use */
		"v=",  TYPE_DOUBLE, op_get_param, (char *) &(opts.v0)
	},
	{NULL, 0, NULL, (char *) NULL}
};

/*
	This array contains the list of options above
	*/
VGEO_OPTION_TABLE_TYPE vgeo_list_of_options[]=
{
	{ ADCP_MIN_SHEAR_METHOD, adcp_min_shear_options },
	{ CTD_MAX_DEPTH_METHOD , ctd_max_depth_options  },
	{ CONST_DEPTH_METHOD   , const_depth_options    },
	{ 0, NULL}
};
		
XOPTION_TYPE vgeo_list_of_kw[]=
{
	{ /* Read options for specified reference method */
		REFERENCE_METHOD_INDEX, (char *) &(opts.ref_method), vgeo_read_options, 
		TYPE_INT, method_name_list, (char *) vgeo_list_of_options
	},
	{ /* CTD sort axis */
		CTD_SORT_AXIS_INDEX, (char *) &(opts.ctd_sort_axis), vgeo_read_options, 
		TYPE_INT, axis_name_list , (char *) vgeo_list_of_options
	},
	{ /* Axis direction for geostrophic current */
		VGEO_AXIS_DIR_INDEX, (char *) &(opts.vgeo_axis_dir), vgeo_read_options,
		TYPE_INT, axis_dir_name_list, (char *) vgeo_list_of_options
	},
	{ /* Getting grid for output data */
		OUTPUT_GRID_INDEX,  (char *) NULL, vgeo_read_grid, 
		TYPE_INT, grid_name_list, (char *) vgeo_list_of_options
	},
	{0, (char *) NULL, NULL, 0, NULL, (char *) NULL}
};

OPTION_TYPE vgeo_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"OPTIONS:", 0, NULL, (char *) NULL},
	{ /* Method for getting reference */
		"reference_method:", REFERENCE_METHOD_INDEX, op_get_keyword, 
		(char *) vgeo_list_of_kw
	},
	{ /* Axis for sorting CTD profiles */
		"ctd_sort_axis:", CTD_SORT_AXIS_INDEX, op_get_keyword, 
		(char *) vgeo_list_of_kw
	},
	{ /* Axis for vgeo calculations */
		"vgeo_direction:", VGEO_AXIS_DIR_INDEX, op_get_keyword, 
		(char *) vgeo_list_of_kw
	},
	{ /* Defining an output grid */
		"grid:", OUTPUT_GRID_INDEX, op_get_keyword, (char *) vgeo_list_of_kw
	},
	{ /* Tolreance for time */
		"time_tolerance=", TYPE_INT, op_get_param, 
		(char *) &(opts.time_tolerance)
	},
	{ /* Minimum number of good bins allowed in a CTD profile */
		"ctd_good_bins=", TYPE_INT, op_get_param, 
		(char *) &(opts.ctd_good_bins)
	},
	{ /* Output scaling values for velocities */
		"velocity_scale=", TYPE_DOUBLE, op_get_param, 
		(char *) &(opts.vgeo_scale)
	},
	{ /* Time offset for CTD profiles */
			"ctd_time_offset=", TYPE_INT, op_get_param, 
			(char *) &(opts.ctd_time_offset)
	},
	{ /* Steps along CTD profiles */
		"ctd_steps=", TYPE_INT, op_get_param, 
		(char *) &(opts.ctd_steps)
	},
	{ /* Use longitude between -180 and +180 */
		"longitude_180", LON_180_CODE, set_long_bit, (char *) &(opts.bits)
	}, 
	{ /* Output of statistics */
		"stat_output", STAT_OUTPUT_CODE, set_long_bit, (char *) &(opts.bits)
	}, 
	{ /* Output of log data */
		"log_output", LOG_OUTPUT_CODE, set_long_bit, (char *) &(opts.bits)
	}, 
	{ /* Output of contour data */
		"contour", CONTOUR_OUTPUT_CODE, set_long_bit, (char *) &(opts.bits)
	}, 
	{NULL, 0, NULL, (char *) NULL}
};

/* ------------------------------------------------------------------
	 -Macros:
	 ------------------------------------------------------------------ */

#define LON_180             ((((opts.bits) >> (LON_180_CODE)) \
															& (0x0001)) ? (1) : (0))
#define CON_OUT             ((((opts.bits) >> (CONTOUR_OUTPUT_CODE)) \
															& (0x0001)) ? (1) : (0))
#define STA_OUT             ((((opts.bits) >> (STAT_OUTPUT_CODE)) \
															& (0x0001)) ? (1) : (0))
#define LOG_OUT             ((((opts.bits) >> (LOG_OUTPUT_CODE)) \
															& (0x0001)) ? (1) : (0))
#define FLAG_DATA           ((((opts.bits) >> (USE_PROFILE_FLAGS_CODE)) \
															& (0x0001)) ? (1) : (0))
#define GRD_OUT             ((((opts.bits) >> (REGRID_OUTPUT_CODE)) \
															& (0x0001)) ? (1) : (0))

#define KNOT_TO_MPS         0.51479

#define lon_to_lon(x)       ((LON_180) ? (to180((x))) : (to360((x))))
															 








