2486 lines
97 KiB
C
2486 lines
97 KiB
C
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* NGDC's Geomagnetic Field Modeling software for the IGRF and WMM */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Disclaimer: This program has undergone limited testing. It is */
|
||
|
/* being distributed unoffically. The National Geophysical Data */
|
||
|
/* Center does not guarantee it's correctness. */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Version 7.0: */
|
||
|
/* - input file format changed to */
|
||
|
/* -- accept new DGRF2005 coeffs with 0.01 nT precision */
|
||
|
/* -- make sure all values are separated by blanks */
|
||
|
/* -- swapped n and m: first is degree, second is order */
|
||
|
/* - new my_isnan function improves portablility */
|
||
|
/* - corrected feet to km conversion factor */
|
||
|
/* - fixed date conversion errors for yyyy,mm,dd format */
|
||
|
/* - fixed lon/lat conversion errors for deg,min,sec format */
|
||
|
/* - simplified leap year identification */
|
||
|
/* - changed comment: units of ddot and idot are arc-min/yr */
|
||
|
/* - added note that this program computes the secular variation as */
|
||
|
/* the 1-year difference, rather than the instantaneous change, */
|
||
|
/* which can be slightly different */
|
||
|
/* - clarified that height is above ellipsoid, not above mean sea level */
|
||
|
/* although the difference is negligible for magnetics */
|
||
|
/* - changed main(argv,argc) to usual definition main(argc,argv) */
|
||
|
/* - corrected rounding of angles close to 60 minutes */
|
||
|
/* Thanks to all who provided bug reports and suggested fixes */
|
||
|
/* */
|
||
|
/* Stefan Maus Jan-25-2010 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Version 6.1: */
|
||
|
/* Included option to read coordinates from a file and output the */
|
||
|
/* results to a new file, repeating the input and adding columns */
|
||
|
/* for the output */
|
||
|
/* Stefan Maus Jan-31-2008 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Version 6.0: */
|
||
|
/* Bug fixes for the interpolation between models. Also added warnings */
|
||
|
/* for declination at low H and corrected behaviour at geogr. poles. */
|
||
|
/* Placed print-out commands into separate routines to facilitate */
|
||
|
/* fine-tuning of the tables */
|
||
|
/* Stefan Maus Aug-24-2004 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* This program calculates the geomagnetic field values from */
|
||
|
/* a spherical harmonic model. Inputs required by the user are: */
|
||
|
/* a spherical harmonic model data file, coordinate preference, */
|
||
|
/* altitude, date/range-step, latitude, and longitude. */
|
||
|
/* */
|
||
|
/* Spherical Harmonic */
|
||
|
/* Model Data File : Name of the data file containing the */
|
||
|
/* spherical harmonic coefficients of */
|
||
|
/* the chosen model. The model and path */
|
||
|
/* must be less than PATH chars. */
|
||
|
/* */
|
||
|
/* Coordinate Preference : Geodetic (WGS84 latitude and altitude */
|
||
|
/* above ellipsoid (WGS84), */
|
||
|
/* or geocentric (spherical, altitude */
|
||
|
/* measured from the center of the Earth). */
|
||
|
/* */
|
||
|
/* Altitude : Altitude above ellipsoid (WGS84). The */
|
||
|
/* program asks for altitude above mean */
|
||
|
/* sea level, because the altitude above */
|
||
|
/* ellipsoid is not known to most users. */
|
||
|
/* The resulting error is very small and */
|
||
|
/* negligible for most practical purposes. */
|
||
|
/* If geocentric coordinate preference is */
|
||
|
/* used, then the altitude must be in the */
|
||
|
/* range of 6370.20 km - 6971.20 km as */
|
||
|
/* measured from the center of the earth. */
|
||
|
/* Enter altitude in kilometers, meters, */
|
||
|
/* or feet */
|
||
|
/* */
|
||
|
/* Date : Date, in decimal years, for which to */
|
||
|
/* calculate the values of the magnetic */
|
||
|
/* field. The date must be within the */
|
||
|
/* limits of the model chosen. */
|
||
|
/* */
|
||
|
/* Latitude : Entered in decimal degrees in the */
|
||
|
/* form xxx.xxx. Positive for northern */
|
||
|
/* hemisphere, negative for the southern */
|
||
|
/* hemisphere. */
|
||
|
/* */
|
||
|
/* Longitude : Entered in decimal degrees in the */
|
||
|
/* form xxx.xxx. Positive for eastern */
|
||
|
/* hemisphere, negative for the western */
|
||
|
/* hemisphere. */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutines called : degrees_to_decimal,julday,getshc,interpsh, */
|
||
|
/* extrapsh,shval3,dihf,safegets */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
int my_isnan(double d)
|
||
|
{
|
||
|
return (d != d); /* IEEE: only NaN is not equal to itself */
|
||
|
}
|
||
|
|
||
|
#define NaN log(-1.0)
|
||
|
#define FT2KM (1.0/0.0003048)
|
||
|
#define PI 3.141592654
|
||
|
#define RAD2DEG (180.0/PI)
|
||
|
|
||
|
#ifndef SEEK_SET
|
||
|
#define SEEK_SET 0
|
||
|
#define SEEK_CUR 1
|
||
|
#define SEEK_END 2
|
||
|
#endif
|
||
|
|
||
|
#define IEXT 0
|
||
|
#define FALSE 0
|
||
|
#define TRUE 1 /* constants */
|
||
|
#define RECL 81
|
||
|
|
||
|
#define MAXINBUFF RECL+14
|
||
|
|
||
|
/** Max size of in buffer **/
|
||
|
|
||
|
#define MAXREAD MAXINBUFF-2
|
||
|
/** Max to read 2 less than total size (just to be safe) **/
|
||
|
|
||
|
#define MAXMOD 30
|
||
|
/** Max number of models in a file **/
|
||
|
|
||
|
#define PATH MAXREAD
|
||
|
/** Max path and filename length **/
|
||
|
|
||
|
#define EXT_COEFF1 (double)0
|
||
|
#define EXT_COEFF2 (double)0
|
||
|
#define EXT_COEFF3 (double)0
|
||
|
|
||
|
#define MAXDEG 13
|
||
|
#define MAXCOEFF (MAXDEG*(MAXDEG+2)+1) /* index starts with 1!, (from old Fortran?) */
|
||
|
double gh1[MAXCOEFF];
|
||
|
double gh2[MAXCOEFF];
|
||
|
double gha[MAXCOEFF]; /* Geomag global variables */
|
||
|
double ghb[MAXCOEFF];
|
||
|
double d=0,f=0,h=0,i=0;
|
||
|
double dtemp,ftemp,htemp,itemp;
|
||
|
double x=0,y=0,z=0;
|
||
|
double xtemp,ytemp,ztemp;
|
||
|
|
||
|
FILE *stream = NULL; /* Pointer to specified model data file */
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Program Geomag */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* This program, originally written in FORTRAN, was developed using */
|
||
|
/* subroutines written by */
|
||
|
/* A. Zunde */
|
||
|
/* USGS, MS 964, Box 25046 Federal Center, Denver, Co. 80225 */
|
||
|
/* and */
|
||
|
/* S.R.C. Malin & D.R. Barraclough */
|
||
|
/* Institute of Geological Sciences, United Kingdom. */
|
||
|
/* */
|
||
|
/* Translated */
|
||
|
/* into C by : Craig H. Shaffer */
|
||
|
/* 29 July, 1988 */
|
||
|
/* */
|
||
|
/* Rewritten by : David Owens */
|
||
|
/* For Susan McLean */
|
||
|
/* */
|
||
|
/* Maintained by: Adam Woods */
|
||
|
/* Contact : geomag.models@noaa.gov */
|
||
|
/* National Geophysical Data Center */
|
||
|
/* World Data Center-A for Solid Earth Geophysics */
|
||
|
/* NOAA, E/GC1, 325 Broadway, */
|
||
|
/* Boulder, CO 80303 */
|
||
|
/* */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Some variables used in this program */
|
||
|
/* */
|
||
|
/* Name Type Usage */
|
||
|
/* ------------------------------------------------------------------------ */
|
||
|
/* */
|
||
|
/* a2,b2 Scalar Double Squares of semi-major and semi-minor */
|
||
|
/* axes of the reference spheroid used */
|
||
|
/* for transforming between geodetic or */
|
||
|
/* geocentric coordinates. */
|
||
|
/* */
|
||
|
/* minalt Double array of MAXMOD Minimum height of model. */
|
||
|
/* */
|
||
|
/* altmin Double Minimum height of selected model. */
|
||
|
/* */
|
||
|
/* altmax Double array of MAXMOD Maximum height of model. */
|
||
|
/* */
|
||
|
/* maxalt Double Maximum height of selected model. */
|
||
|
/* */
|
||
|
/* d Scalar Double Declination of the field from the */
|
||
|
/* geographic north (deg). */
|
||
|
/* */
|
||
|
/* sdate Scalar Double start date inputted */
|
||
|
/* */
|
||
|
/* ddot Scalar Double annual rate of change of decl. */
|
||
|
/* (arc-min/yr) */
|
||
|
/* */
|
||
|
/* alt Scalar Double altitude above WGS84 Ellipsoid */
|
||
|
/* */
|
||
|
/* epoch Double array of MAXMOD epoch of model. */
|
||
|
/* */
|
||
|
/* ext Scalar Double Three 1st-degree external coeff. */
|
||
|
/* */
|
||
|
/* latitude Scalar Double Latitude. */
|
||
|
/* */
|
||
|
/* longitude Scalar Double Longitude. */
|
||
|
/* */
|
||
|
/* gh1 Double array Schmidt quasi-normal internal */
|
||
|
/* spherical harmonic coeff. */
|
||
|
/* */
|
||
|
/* gh2 Double array Schmidt quasi-normal internal */
|
||
|
/* spherical harmonic coeff. */
|
||
|
/* */
|
||
|
/* gha Double array Coefficients of resulting model. */
|
||
|
/* */
|
||
|
/* ghb Double array Coefficients of rate of change model.*/
|
||
|
/* */
|
||
|
/* i Scalar Double Inclination (deg). */
|
||
|
/* */
|
||
|
/* idot Scalar Double Rate of change of i (arc-min/yr). */
|
||
|
/* */
|
||
|
/* igdgc Integer Flag for geodetic or geocentric */
|
||
|
/* coordinate choice. */
|
||
|
/* */
|
||
|
/* inbuff Char a of MAXINBUF Input buffer. */
|
||
|
/* */
|
||
|
/* irec_pos Integer array of MAXMOD Record counter for header */
|
||
|
/* */
|
||
|
/* stream Integer File handles for an opened file. */
|
||
|
/* */
|
||
|
/* fileline Integer Current line in file (for errors) */
|
||
|
/* */
|
||
|
/* max1 Integer array of MAXMOD Main field coefficient. */
|
||
|
/* */
|
||
|
/* max2 Integer array of MAXMOD Secular variation coefficient. */
|
||
|
/* */
|
||
|
/* max3 Integer array of MAXMOD Acceleration coefficient. */
|
||
|
/* */
|
||
|
/* mdfile Character array of PATH Model file name. */
|
||
|
/* */
|
||
|
/* minyr Double Min year of all models */
|
||
|
/* */
|
||
|
/* maxyr Double Max year of all models */
|
||
|
/* */
|
||
|
/* yrmax Double array of MAXMOD Max year of model. */
|
||
|
/* */
|
||
|
/* yrmin Double array of MAXMOD Min year of model. */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
int main(int argc, char**argv)
|
||
|
{
|
||
|
#ifdef MAC
|
||
|
ccommand(argc, argv);
|
||
|
#endif
|
||
|
/* Variable declaration */
|
||
|
|
||
|
/* Control variables */
|
||
|
int again = 1;
|
||
|
int decyears = 3;
|
||
|
int units = 4;
|
||
|
int decdeg = 3;
|
||
|
int range = -1;
|
||
|
int counter = 0;
|
||
|
int warn_H, warn_H_strong, warn_P;
|
||
|
|
||
|
int modelI; /* Which model (Index) */
|
||
|
int nmodel; /* Number of models in file */
|
||
|
int max1[MAXMOD];
|
||
|
int max2[MAXMOD];
|
||
|
int max3[MAXMOD];
|
||
|
int nmax;
|
||
|
int igdgc=3;
|
||
|
int isyear=-1;
|
||
|
int ismonth=-1;
|
||
|
int isday=-1;
|
||
|
int ieyear=-1;
|
||
|
int iemonth=-1;
|
||
|
int ieday=-1;
|
||
|
int ilat_deg=200;
|
||
|
int ilat_min=200;
|
||
|
int ilat_sec=200;
|
||
|
int ilon_deg=200;
|
||
|
int ilon_min=200;
|
||
|
int ilon_sec=200;
|
||
|
int fileline;
|
||
|
long irec_pos[MAXMOD];
|
||
|
|
||
|
int coords_from_file = 0;
|
||
|
int arg_err = 0;
|
||
|
int need_to_read_model = 1;
|
||
|
|
||
|
char mdfile[PATH];
|
||
|
char inbuff[MAXINBUFF];
|
||
|
char model[MAXMOD][9];
|
||
|
char *begin;
|
||
|
char *rest;
|
||
|
char args[7][MAXREAD];
|
||
|
int iarg;
|
||
|
|
||
|
char coord_fname[PATH];
|
||
|
char out_fname[PATH];
|
||
|
FILE *coordfile,*outfile;
|
||
|
int iline=0;
|
||
|
int read_flag;
|
||
|
|
||
|
double epoch[MAXMOD];
|
||
|
double yrmin[MAXMOD];
|
||
|
double yrmax[MAXMOD];
|
||
|
double minyr;
|
||
|
double maxyr;
|
||
|
double altmin[MAXMOD];
|
||
|
double altmax[MAXMOD];
|
||
|
double minalt;
|
||
|
double maxalt;
|
||
|
double alt=-999999;
|
||
|
double sdate=-1;
|
||
|
double step=-1;
|
||
|
double syr;
|
||
|
double edate=-1;
|
||
|
double latitude=200;
|
||
|
double longitude=200;
|
||
|
double ddot;
|
||
|
double fdot;
|
||
|
double hdot;
|
||
|
double idot;
|
||
|
double xdot;
|
||
|
double ydot;
|
||
|
double zdot;
|
||
|
double warn_H_val, warn_H_strong_val;
|
||
|
|
||
|
/* Subroutines used */
|
||
|
|
||
|
void print_dashed_line();
|
||
|
void print_long_dashed_line(void);
|
||
|
void print_header();
|
||
|
void print_result(double date, double d, double i, double h, double x, double y, double z, double f);
|
||
|
void print_header_sv();
|
||
|
void print_result_sv(double date, double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot);
|
||
|
void print_result_file(FILE *outf, double d, double i, double h, double x, double y, double z, double f,
|
||
|
double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot);
|
||
|
double degrees_to_decimal();
|
||
|
double julday();
|
||
|
int interpsh();
|
||
|
int extrapsh();
|
||
|
int shval3();
|
||
|
int dihf();
|
||
|
int safegets(char *buffer,int n);
|
||
|
int getshc();
|
||
|
|
||
|
|
||
|
/* Initializations. */
|
||
|
|
||
|
inbuff[MAXREAD+1]='\0'; /* Just to protect mem. */
|
||
|
inbuff[MAXINBUFF-1]='\0'; /* Just to protect mem. */
|
||
|
|
||
|
for (iarg=0; iarg<argc; iarg++)
|
||
|
if (argv[iarg] != NULL)
|
||
|
strncpy(args[iarg],argv[iarg],MAXREAD);
|
||
|
|
||
|
/* printing out version number and header */
|
||
|
printf("\n\n Geomag v7.0 - Jan 25, 2010 ");
|
||
|
|
||
|
if ((argc==2)&&((*(args[1])=='h')||(*(args[1])=='?')||(args[1][1]=='?')))
|
||
|
{
|
||
|
printf("\n\nUSAGE:\n");
|
||
|
printf("interactive: geomag\n");
|
||
|
printf("command line: geomag model_file date coord alt lat lon\n");
|
||
|
printf("coordinate file: geomag model_file f input_file output_file\n");
|
||
|
printf("or for help: geomag h (or ? or -? or /?) \n");
|
||
|
printf("\n");
|
||
|
printf("Date and location Formats: \n");
|
||
|
printf(" Date: xxxx.xxx for decimal (1947.32)\n");
|
||
|
printf(" YYYY,MM,DD for year, month, day (1947,10,13)\n");
|
||
|
printf(" or start_date-end_date (1943.21-1966.11)\n");
|
||
|
printf(" or start_date-end_date-step (1943.21-1966.11-1.2)\n");
|
||
|
printf(" Coord: D - Geodetic (WGS84 latitude and altitude above mean sea level)\n");
|
||
|
printf(" C - Geocentric (spherical, altitude relative to Earth's center)\n");
|
||
|
printf(" Altitude: Kxxxxxx.xxx for kilometers (K1000.13)\n");
|
||
|
printf(" Mxxxxxx.xxx for meters (m1389.24)\n");
|
||
|
printf(" Fxxxxxx.xxx for feet (F192133.73)\n");
|
||
|
printf(" Lat/Lon: xxx.xxx for decimal (-76.53)\n");
|
||
|
printf(" ddd,mm,ss for degrees, minutes, seconds (-60,23,22)\n");
|
||
|
printf(" (Lat and Lon must be specified in the same format,\n");
|
||
|
printf(" for ddd,mm,ss format, two commas each are required \n");
|
||
|
printf(" and decimals of arc-seconds are ignored) \n");
|
||
|
printf("\nRange (only for interactive and command line options): \n");
|
||
|
printf(" Date and altitude must fit model.\n");
|
||
|
printf(" Lat: -90 to 90 (Use - to denote Southern latitude.)\n");
|
||
|
printf(" Lon: -180 to 180 (Use - to denote Westen longitude.)\n");
|
||
|
printf(" Minutes and Seconds: -59 to 59.\n");
|
||
|
printf("\nNote for command line option: \n");
|
||
|
printf(" All arguments are optional but must preserve order.\n");
|
||
|
printf(" You can only omit arguments AT THE END, not in between.\n");
|
||
|
printf(" Invalid arguments are assumed to be 0.\n");
|
||
|
printf("\nNote that this program computes secular variation as the \n");
|
||
|
printf(" change over the coming year, rather than instantaneous,\n");
|
||
|
printf(" which can be different for declination near magnetic poles.\n");
|
||
|
exit(2);
|
||
|
} /* help */
|
||
|
|
||
|
if ((argc==5)&&(*(args[2])=='f'))
|
||
|
{
|
||
|
printf("\n\n 'f' switch: converting file with multiple locations.\n");
|
||
|
printf(" The first five output columns repeat the input coordinates.\n");
|
||
|
printf(" Then follows D, I, H, X, Y, Z, and F.\n");
|
||
|
printf(" Finally the SV: dD, dI, dH, dX, dY, dZ, and dF\n");
|
||
|
printf(" The units are the same as when the program is\n");
|
||
|
printf(" run in command line or interactive mode.\n\n");
|
||
|
coords_from_file = 1;
|
||
|
strncpy(coord_fname,args[3],MAXREAD);
|
||
|
coordfile=fopen(coord_fname, "rt");
|
||
|
strncpy(out_fname,args[4],MAXREAD);
|
||
|
outfile=fopen(out_fname, "w");
|
||
|
fprintf(outfile,"Date Coord-System Altitude Latitude Longitude D_deg D_min I_deg I_min H_nT X_nT Y_nT Z_nT F_nT dD_min dI_min dH_nT dX_nT dY_nT dZ_nT dF_nT\n");
|
||
|
} /* file option */
|
||
|
|
||
|
if (argc>=3 && argc !=5 && *(args[2])=='f')
|
||
|
{
|
||
|
printf("\n\nERROR in 'f' switch option: wrong number of arguments\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((argc==3)||(argc==4)||(argc==6))
|
||
|
{
|
||
|
printf("\n\nUSAGE:\n");
|
||
|
printf("interactive: geomag\n");
|
||
|
printf("command line: geomag model_file date coord alt lat lon\n");
|
||
|
printf("coordinate file: geomag model_file f input_file output_file\n");
|
||
|
printf("or for help: geomag h \n\n");
|
||
|
} /* missing arguments (not fatal) */
|
||
|
|
||
|
while (again == 1)
|
||
|
{
|
||
|
if (coords_from_file)
|
||
|
{
|
||
|
argc = 7;
|
||
|
read_flag = fscanf(coordfile,"%s%s%s%s%s%*[^\n]",args[2],args[3],args[4],args[5],args[6]);
|
||
|
if (read_flag == EOF) goto reached_EOF;
|
||
|
fprintf(outfile,"%s %s %s %s %s ",args[2],args[3],args[4],args[5],args[6]);fflush(outfile);
|
||
|
iline++;
|
||
|
} /* coords_from_file */
|
||
|
|
||
|
/* Switch on how many arguments are supplied. */
|
||
|
/* Note that there are no 'breaks' after the cases, so these are entry points */
|
||
|
switch(argc)
|
||
|
{
|
||
|
case 7 : strncpy(inbuff, args[6], MAXREAD);
|
||
|
if ((rest=strchr(inbuff, ','))) /* If it contains a comma */
|
||
|
{
|
||
|
decdeg=2; /* Then not decimal degrees */
|
||
|
begin=inbuff;
|
||
|
rest[0]='\0'; /* Chop into sub string */
|
||
|
rest++; /* Move to next substring */
|
||
|
ilon_deg=atoi(begin);
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, ',')))
|
||
|
{
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ilon_min=atoi(begin);
|
||
|
ilon_sec=atoi(rest);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ilon_min=0;
|
||
|
ilon_sec=0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decdeg=1; /* Else it's decimal */
|
||
|
longitude=atof(args[6]);
|
||
|
}
|
||
|
|
||
|
case 6 : strncpy(inbuff, args[5], MAXREAD);
|
||
|
if ((rest=strchr(inbuff, ',')))
|
||
|
{
|
||
|
decdeg=2;
|
||
|
begin=inbuff;
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ilat_deg=atoi(begin);
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, ',')))
|
||
|
{
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ilat_min=atoi(begin);
|
||
|
ilat_sec=atoi(rest);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ilat_min=0;
|
||
|
ilat_sec=0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decdeg=1;
|
||
|
latitude=atof(args[5]);
|
||
|
}
|
||
|
|
||
|
case 5 : strncpy(inbuff, args[4], MAXREAD);
|
||
|
inbuff[0]=toupper(inbuff[0]);
|
||
|
if (inbuff[0]=='K') units=1;
|
||
|
else if (inbuff[0]=='M') units=2;
|
||
|
else if (inbuff[0]=='F') units=3;
|
||
|
if (strlen(inbuff)>1)
|
||
|
{
|
||
|
inbuff[0]='\0';
|
||
|
begin=inbuff+1;
|
||
|
alt=atof(begin);
|
||
|
}
|
||
|
|
||
|
case 4 : strncpy(inbuff, args[3], MAXREAD);
|
||
|
inbuff[0]=toupper(inbuff[0]);
|
||
|
if (inbuff[0]=='D') igdgc=1;
|
||
|
else if (inbuff[0]=='C') igdgc=2;
|
||
|
|
||
|
case 3 : strncpy(inbuff, args[2], MAXREAD);
|
||
|
if ((rest=strchr(inbuff, '-'))) /* If it contains a dash */
|
||
|
{
|
||
|
range = 2; /* They want a range */
|
||
|
rest[0]='\0'; /* Sep dates */
|
||
|
rest++;
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, '-'))) /* If it contains 2 dashs */
|
||
|
{
|
||
|
rest[0]='\0'; /* Sep step */
|
||
|
rest++;
|
||
|
step=atof(rest); /* Get step size */
|
||
|
}
|
||
|
if ((rest=strchr(begin, ','))) /* If it contains a comma */
|
||
|
{
|
||
|
decyears=2; /* It's not decimal years */
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ieyear=atoi(begin);
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, ',')))
|
||
|
{
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
iemonth=atoi(begin);
|
||
|
ieday=atoi(rest);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iemonth=0;
|
||
|
ieday=0;
|
||
|
}
|
||
|
if ((rest=strchr(inbuff, ',')))
|
||
|
{
|
||
|
begin=inbuff;
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
isyear=atoi(begin);
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, ',')))
|
||
|
{
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ismonth=atoi(begin);
|
||
|
isday=atoi(rest);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ismonth=0;
|
||
|
isday=0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sdate=atof(inbuff);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decyears=1; /* Else it's decimal years */
|
||
|
sdate=atof(inbuff);
|
||
|
edate=atof(begin);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
range = 1;
|
||
|
if ((rest=strchr(inbuff, ','))) /* If it contains a comma */
|
||
|
{
|
||
|
decyears=2; /* It's not decimal years */
|
||
|
begin=inbuff;
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
isyear=atoi(begin);
|
||
|
begin=rest;
|
||
|
if ((rest=strchr(begin, ',')))
|
||
|
{
|
||
|
rest[0]='\0';
|
||
|
rest++;
|
||
|
ismonth=atoi(begin);
|
||
|
isday=atoi(rest);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ismonth=0;
|
||
|
isday=0;
|
||
|
}
|
||
|
sdate = julday(ismonth,isday,isyear);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decyears=1; /* Else it's decimal years */
|
||
|
sdate=atof(args[2]);
|
||
|
}
|
||
|
}
|
||
|
if (sdate==0)
|
||
|
{ /* If date not valid */
|
||
|
decyears=-1;
|
||
|
range=-1;
|
||
|
}
|
||
|
|
||
|
case 2 :
|
||
|
if (need_to_read_model)
|
||
|
{
|
||
|
strncpy(mdfile,args[1],MAXREAD);
|
||
|
stream=fopen(mdfile, "rt");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (range == 2 && coords_from_file)
|
||
|
{
|
||
|
printf("Error in line %1d, date = %s: date ranges not allowed for file option\n\n",iline,args[2]);
|
||
|
exit(2);
|
||
|
}
|
||
|
|
||
|
/* Obtain the desired model file and read the data */
|
||
|
|
||
|
warn_H = 0;
|
||
|
warn_H_val = 99999.0;
|
||
|
warn_H_strong = 0;
|
||
|
warn_H_strong_val = 99999.0;
|
||
|
warn_P = 0;
|
||
|
|
||
|
if (need_to_read_model)
|
||
|
{
|
||
|
while (stream == NULL)
|
||
|
{
|
||
|
printf("\n\n");
|
||
|
printf("What is the name of the model data file to be opened? ==> ");
|
||
|
safegets(inbuff,MAXREAD);
|
||
|
strcpy(mdfile, inbuff);
|
||
|
if (!(stream = fopen(mdfile, "rt")))
|
||
|
printf("\nError opening file %s.", mdfile);
|
||
|
}
|
||
|
rewind(stream);
|
||
|
|
||
|
fileline = 0; /* First line will be 1 */
|
||
|
modelI = -1; /* First model will be 0 */
|
||
|
while (fgets(inbuff,MAXREAD,stream)) /* While not end of file
|
||
|
* read to end of line or buffer */
|
||
|
{
|
||
|
fileline++; /* On new line */
|
||
|
|
||
|
|
||
|
if (strlen(inbuff) != RECL) /* IF incorrect record size */
|
||
|
{
|
||
|
printf("Corrupt record in file %s on line %d.\n", mdfile, fileline);
|
||
|
fclose(stream);
|
||
|
exit(5);
|
||
|
}
|
||
|
|
||
|
/* old statement Dec 1999 */
|
||
|
/* if (!strncmp(inbuff," ",4)){ /* If 1st 4 chars are spaces */
|
||
|
/* New statement Dec 1999 changed by wmd required by year 2000 models */
|
||
|
if (!strncmp(inbuff," ",3)) /* If 1st 3 chars are spaces */
|
||
|
{
|
||
|
modelI++; /* New model */
|
||
|
|
||
|
if (modelI > MAXMOD) /* If too many headers */
|
||
|
{
|
||
|
printf("Too many models in file %s on line %d.", mdfile, fileline);
|
||
|
fclose(stream);
|
||
|
exit(6);
|
||
|
}
|
||
|
|
||
|
irec_pos[modelI]=ftell(stream);
|
||
|
/* Get fields from buffer into individual vars. */
|
||
|
sscanf(inbuff, "%s%lg%d%d%d%lg%lg%lg%lg", model[modelI], &epoch[modelI],
|
||
|
&max1[modelI], &max2[modelI], &max3[modelI], &yrmin[modelI],
|
||
|
&yrmax[modelI], &altmin[modelI], &altmax[modelI]);
|
||
|
|
||
|
/* Compute date range for all models */
|
||
|
if (modelI == 0) /*If first model */
|
||
|
{
|
||
|
minyr=yrmin[0];
|
||
|
maxyr=yrmax[0];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (yrmin[modelI]<minyr)
|
||
|
{
|
||
|
minyr=yrmin[modelI];
|
||
|
}
|
||
|
if (yrmax[modelI]>maxyr){
|
||
|
maxyr=yrmax[modelI];
|
||
|
}
|
||
|
} /* if modelI != 0 */
|
||
|
|
||
|
} /* If 1st 3 chars are spaces */
|
||
|
|
||
|
} /* While not end of model file */
|
||
|
|
||
|
nmodel = modelI + 1;
|
||
|
fclose(stream);
|
||
|
|
||
|
/* if date specified in command line then warn if past end of validity */
|
||
|
|
||
|
if ((sdate>maxyr)&&(sdate<maxyr+1))
|
||
|
{
|
||
|
printf("\nWarning: The date %4.2f is out of range,\n", sdate);
|
||
|
printf(" but still within one year of model expiration date.\n");
|
||
|
printf(" An updated model file is available before 1.1.%4.0f\n",maxyr);
|
||
|
}
|
||
|
|
||
|
} /* if need_to_read_model */
|
||
|
|
||
|
/* Take in field data */
|
||
|
|
||
|
/* Get date */
|
||
|
|
||
|
if (coords_from_file && !arg_err && (decyears != 1 && decyears != 2))
|
||
|
{printf("\nError: unrecognized date %s in coordinate file line %1d\n\n",args[2],iline); arg_err = 1;}
|
||
|
|
||
|
while ((decyears!=1)&&(decyears!=2))
|
||
|
{
|
||
|
printf("\nHow would you like to enter the date?\n");
|
||
|
printf(" 1) In decimal years.\n");
|
||
|
printf(" 2) In year, month, and day.\n");
|
||
|
printf("\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
decyears=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
if (coords_from_file && !arg_err && range != 1)
|
||
|
{printf("\nError: unrecognized date %s in coordinate file line %1d\n\n",args[2],iline); arg_err = 1;}
|
||
|
|
||
|
while ((range!=1)&&(range!=2))
|
||
|
{
|
||
|
printf("\nWould you like output for a single date or for a range of dates?\n");
|
||
|
printf(" 1) A single date.\n");
|
||
|
printf(" 2) A range of dates.\n");
|
||
|
printf("\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
range=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (range == 1)
|
||
|
{
|
||
|
if (coords_from_file && !arg_err && (sdate < minyr || sdate > maxyr+1))
|
||
|
{printf("\nError: unrecognized date %s in coordinate file line %1d\n\n",args[2],iline); arg_err = 1;}
|
||
|
|
||
|
while ((sdate<minyr)||(sdate>maxyr+1))
|
||
|
{
|
||
|
if (decyears==1)
|
||
|
{
|
||
|
printf("\nEnter the decimal date (%4.2f to %4.0f): ",minyr, maxyr);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
sdate=atof(inbuff);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while ((isyear>(int)maxyr+1)||(isyear<(int)minyr))
|
||
|
{
|
||
|
printf("\nEnter the date (%4.2f to %4.2f)\n ", minyr, maxyr);
|
||
|
printf("\n Year (%d to %d): ",(int)minyr,(int)maxyr);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
isyear=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
while ((ismonth>12)||(ismonth<1))
|
||
|
{
|
||
|
printf("\n Month (1-12): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ismonth=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
while ((isday>31)||(isday<1))
|
||
|
{
|
||
|
printf("\n Day (1-31): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
isday=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
sdate = julday(ismonth,isday,isyear);
|
||
|
}
|
||
|
if ((sdate<minyr)||(sdate>=maxyr+1))
|
||
|
{
|
||
|
ismonth=isday=isyear=0;
|
||
|
printf("\nError: The date %4.2f is out of range.\n", sdate);
|
||
|
}
|
||
|
|
||
|
if ((sdate>maxyr)&&(sdate<maxyr+1))
|
||
|
{
|
||
|
printf("\nWarning: The date %4.2f is out of range,\n", sdate);
|
||
|
printf(" but still within one year of model expiration date.\n");
|
||
|
printf(" An updated model file is available before 1.1.%4.0f\n",maxyr);
|
||
|
}
|
||
|
|
||
|
} /* if single date */
|
||
|
} /* (range == 1) */
|
||
|
else
|
||
|
{
|
||
|
while ((sdate<minyr)||(sdate>maxyr))
|
||
|
{
|
||
|
if (decyears==1)
|
||
|
{
|
||
|
printf("\nEnter the decimal start date (%4.2f to %4.0f): ",minyr, maxyr);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
sdate=atof(inbuff);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while ((isyear>(int)maxyr)||(isyear<(int)minyr))
|
||
|
{
|
||
|
ismonth=isday=isyear=0;
|
||
|
printf("\nEnter the start date (%4.2f to %4.2f)\n ", minyr, maxyr);
|
||
|
printf("\n Year (%d to %d): ",(int)minyr,(int)(maxyr));
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
isyear=atoi(inbuff);
|
||
|
}
|
||
|
while ((ismonth>12)||(ismonth<1))
|
||
|
{
|
||
|
printf("\n Month (1-12): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ismonth=atoi(inbuff);
|
||
|
}
|
||
|
while ((isday>31)||(isday<1))
|
||
|
{
|
||
|
printf("\n Day (1-31): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
isday=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
sdate = julday(ismonth,isday,isyear);
|
||
|
|
||
|
if ((sdate<minyr)||(sdate>maxyr))
|
||
|
{
|
||
|
printf("\nThe start date %4.2f is out of range.\n", sdate);
|
||
|
}
|
||
|
}
|
||
|
} /* WHILE ((sdate<minyr)||(sdate>maxyr)) */
|
||
|
|
||
|
while ((edate<=sdate)||(edate>maxyr+1))
|
||
|
{
|
||
|
if (decyears==1)
|
||
|
{
|
||
|
printf("\nEnter the decimal end date (%4.2f to %4.0f): ",sdate, maxyr);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
edate=atof(inbuff);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while ((ieyear>(int)maxyr)||(ieyear<(int)sdate))
|
||
|
{
|
||
|
iemonth=ieday=ieyear=0;
|
||
|
printf("\nEnter the end date (%4.2f to %4.0f)\n ", sdate, maxyr);
|
||
|
printf("\n Year (%d to %d): ",(int)sdate,(int)(maxyr));
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ieyear=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
while ((iemonth>12)||(iemonth<1))
|
||
|
{
|
||
|
printf("\n Month (1-12): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
iemonth=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
while ((ieday>31)||(ieday<1))
|
||
|
{
|
||
|
printf("\n Day (1-31): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ieday=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
edate = julday(iemonth,ieday,ieyear);
|
||
|
|
||
|
}
|
||
|
|
||
|
if ((edate<sdate)||(edate>maxyr+1))
|
||
|
{
|
||
|
printf("\nThe date %4.2f is out of range.\n", edate);
|
||
|
}
|
||
|
|
||
|
if (edate>maxyr && edate<=maxyr+1)
|
||
|
{
|
||
|
printf("\nWarning: The end date %4.2f is out of range,\n", edate);
|
||
|
printf(" but still within one year of model expiration date.\n");
|
||
|
printf(" An updated model file is available before 1.1.%4.0f\n",maxyr);
|
||
|
}
|
||
|
} /* while ((edate<=sdate)||(edate>maxyr+1)) */
|
||
|
|
||
|
while ((step<=0)||(step>(edate-sdate)))
|
||
|
{
|
||
|
printf("\nEnter the step size in years. (0 to %4.2f): ",edate-sdate);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
step=atof(inbuff);
|
||
|
}
|
||
|
|
||
|
} /* if (range == 2) */
|
||
|
|
||
|
|
||
|
/* Pick model */
|
||
|
for (modelI=0; modelI<nmodel; modelI++)
|
||
|
if (sdate<yrmax[modelI]) break;
|
||
|
if (modelI == nmodel) modelI--; /* if beyond end of last model use last model */
|
||
|
|
||
|
/* Get altitude min and max for selected model. */
|
||
|
minalt=altmin[modelI];
|
||
|
maxalt=altmax[modelI];
|
||
|
|
||
|
/* Get Coordinate prefs */
|
||
|
|
||
|
if (coords_from_file && !arg_err && (igdgc != 1 && igdgc != 2))
|
||
|
{printf("\nError: unrecognized coordinate system %s in coordinate file line %1d\n\n",args[3],iline); arg_err = 1;}
|
||
|
|
||
|
while ((igdgc!=1)&&(igdgc!=2))
|
||
|
{
|
||
|
printf("\n\nEnter Coordinate Preferences:");
|
||
|
printf("\n 1) Geodetic (WGS84 latitude and altitude above mean sea level)");
|
||
|
printf("\n 2) Geocentric (spherical, altitude relative to Earth's center)\n");
|
||
|
printf("\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
igdgc=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
/* If needed modify ranges to reflect coords. */
|
||
|
if (igdgc==2)
|
||
|
{
|
||
|
minalt+=6371.2; /* Add radius to ranges. */
|
||
|
maxalt+=6371.2;
|
||
|
}
|
||
|
|
||
|
/* Get unit prefs */
|
||
|
if (igdgc==1)
|
||
|
{
|
||
|
if (coords_from_file && !arg_err && (units > 3 || units < 1))
|
||
|
{printf("\nError: unrecognized altitude units %s in coordinate file line %1d\n\n",args[4],iline); arg_err = 1;}
|
||
|
|
||
|
while ((units>3)||(units<1))
|
||
|
{
|
||
|
printf("\n\nEnter Unit Preferences:");
|
||
|
printf("\n 1) Kilometers");
|
||
|
printf("\n 2) Meters");
|
||
|
printf("\n 3) Feet\n");
|
||
|
printf("\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
units=atoi(inbuff);
|
||
|
}
|
||
|
}
|
||
|
else units = 1; /* geocentric always in km */
|
||
|
|
||
|
/* Do unit conversions if neccessary */
|
||
|
if (units==2)
|
||
|
{
|
||
|
minalt*=1000.0;
|
||
|
maxalt*=1000.0;
|
||
|
}
|
||
|
else if (units==3)
|
||
|
{
|
||
|
minalt*=FT2KM;
|
||
|
maxalt*=FT2KM;
|
||
|
}
|
||
|
|
||
|
/* Get altitude */
|
||
|
|
||
|
if (coords_from_file && !arg_err && (alt < minalt || alt > maxalt))
|
||
|
{printf("\nError: unrecognized altitude %s in coordinate file line %1d\n\n",args[4],iline); arg_err = 1;}
|
||
|
|
||
|
while ((alt<minalt)||(alt>maxalt))
|
||
|
{
|
||
|
if (igdgc==2) printf("\n\nEnter geocentric altitude in km (%.2f to %.2f): ", minalt, maxalt);
|
||
|
if (igdgc==1 && units==1) printf("\n\nEnter geodetic altitude above mean sea level in km (%.2f to %.2f): ", minalt, maxalt);
|
||
|
if (igdgc==1 && units==2) printf("\n\nEnter geodetic altitude above mean sea level in meters (%.2f to %.2f): ", minalt, maxalt);
|
||
|
if (igdgc==1 && units==3) printf("\n\nEnter geodetic altitude above mean sea level in feet (%.2f to %.2f): ", minalt, maxalt);
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
alt=atof(inbuff);
|
||
|
}
|
||
|
|
||
|
/* Convert altitude to km */
|
||
|
if (units==2)
|
||
|
{
|
||
|
alt *= 0.001;
|
||
|
}
|
||
|
else if (units==3)
|
||
|
{
|
||
|
alt /= FT2KM;
|
||
|
}
|
||
|
|
||
|
/* Get lat/long prefs */
|
||
|
|
||
|
if (coords_from_file && !arg_err && (decdeg != 1 && decdeg != 2))
|
||
|
{printf("\nError: unrecognized lat %s or lon %s in coordinate file line %1d\n\n",args[5],args[6],iline); arg_err = 1;}
|
||
|
|
||
|
while ((decdeg!=1)&&(decdeg!=2))
|
||
|
{
|
||
|
printf("\n\nHow would you like to enter the latitude and longitude?:");
|
||
|
printf("\n 1) In decimal degrees.");
|
||
|
printf("\n 2) In degrees, minutes, and seconds.\n");
|
||
|
printf("\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
decdeg=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Get lat/lon */
|
||
|
|
||
|
if (decdeg==1)
|
||
|
{
|
||
|
if (coords_from_file && !arg_err && (latitude < -90 || latitude > 90))
|
||
|
{printf("\nError: unrecognized latitude %s in coordinate file line %1d\n\n",args[6],iline); arg_err = 1;}
|
||
|
|
||
|
while ((latitude<-90)||(latitude>90))
|
||
|
{
|
||
|
printf("\n\nEnter the decimal latitude (-90 to 90) (- for Southern hemisphere).\n");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
latitude=atof(inbuff);
|
||
|
}
|
||
|
|
||
|
if (coords_from_file && !arg_err && (longitude < -180 || longitude > 180))
|
||
|
{printf("\nError: unrecognized longitude %s in coordinate file line %1d\n\n",args[6],iline); arg_err = 1;}
|
||
|
|
||
|
while ((longitude<-180)||(longitude>180))
|
||
|
{
|
||
|
printf("\n\nEnter the decimal longitude (-180 to 180) (- for Western hemisphere).\n");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
longitude=atof(inbuff);
|
||
|
}
|
||
|
} /* if (decdeg==1) */
|
||
|
else
|
||
|
{
|
||
|
latitude=degrees_to_decimal(ilat_deg,ilat_min,ilat_sec);
|
||
|
longitude=degrees_to_decimal(ilon_deg,ilon_min,ilon_sec);
|
||
|
|
||
|
if (coords_from_file && !arg_err && (latitude < -90 || latitude > 90))
|
||
|
{printf("\nError: unrecognized latitude %s in coordinate file line %1d\n\n",args[6],iline); arg_err = 1;}
|
||
|
|
||
|
while ((latitude<-90)||(latitude>90))
|
||
|
{
|
||
|
ilat_deg=ilat_min=ilat_sec=200;
|
||
|
printf("\n\nEnter the decimal latitude (-90 to 90) (- for Southern hemisphere).\n");
|
||
|
while ((ilat_deg<-90)||(ilat_deg>90))
|
||
|
{
|
||
|
printf("\nDegrees (-90 to 90): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilat_deg=atoi(inbuff);
|
||
|
}
|
||
|
while ((ilat_min<-59)||(ilat_min>59))
|
||
|
{
|
||
|
printf("\nMinutes (-59 to 59): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilat_min=atoi(inbuff);
|
||
|
}
|
||
|
while ((ilat_sec<-59)||(ilat_sec>59))
|
||
|
{
|
||
|
printf("\nSeconds (-59 to 59): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilat_sec=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
latitude=degrees_to_decimal(ilat_deg,ilat_min,ilat_sec);
|
||
|
|
||
|
if ((latitude<-90)||(latitude>90))
|
||
|
{
|
||
|
printf("\nThe latitude %3.2f is out of range", latitude);
|
||
|
}
|
||
|
} /* while ((latitude<-90)||(latitude>90)) */
|
||
|
|
||
|
if (coords_from_file && !arg_err && (longitude < -180 || longitude > 180))
|
||
|
{printf("\nError: unrecognized longitude %s in coordinate file line %1d\n\n",args[6],iline); arg_err = 1;}
|
||
|
|
||
|
while ((longitude<-180)||(longitude>180))
|
||
|
{
|
||
|
ilon_deg=ilon_min=ilon_sec=200;
|
||
|
printf("\n\nEnter the decimal longitude (-180 to 180) (- for Western hemisphere).\n");
|
||
|
while ((ilon_deg<-180)||(ilon_deg>180))
|
||
|
{
|
||
|
printf("\nDegrees (-180 to 180): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilon_deg=atoi(inbuff);
|
||
|
}
|
||
|
while ((ilon_min<-59)||(ilon_min>59))
|
||
|
{
|
||
|
printf("\nMinutes (0 to 59): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilon_min=atoi(inbuff);
|
||
|
}
|
||
|
while ((ilon_sec<-59)||(ilon_sec>59))
|
||
|
{
|
||
|
printf("\nSeconds (0 to 59): ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
ilon_sec=atoi(inbuff);
|
||
|
}
|
||
|
|
||
|
longitude=degrees_to_decimal(ilon_deg,ilon_min,ilon_sec);
|
||
|
|
||
|
if ((longitude<-180)||(longitude>180))
|
||
|
{
|
||
|
printf("\nThe longitude %3.2f is out of range", longitude);
|
||
|
}
|
||
|
} /* while ((longitude<-180)||(longitude>180)) */
|
||
|
} /* if (decdeg != 1) */
|
||
|
|
||
|
/** This will compute everything needed for 1 point in time. **/
|
||
|
|
||
|
|
||
|
if (max2[modelI] == 0)
|
||
|
{
|
||
|
getshc(mdfile, 1, irec_pos[modelI], max1[modelI], 1);
|
||
|
getshc(mdfile, 1, irec_pos[modelI+1], max1[modelI+1], 2);
|
||
|
nmax = interpsh(sdate, yrmin[modelI], max1[modelI],
|
||
|
yrmin[modelI+1], max1[modelI+1], 3);
|
||
|
nmax = interpsh(sdate+1, yrmin[modelI] , max1[modelI],
|
||
|
yrmin[modelI+1], max1[modelI+1],4);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
getshc(mdfile, 1, irec_pos[modelI], max1[modelI], 1);
|
||
|
getshc(mdfile, 0, irec_pos[modelI], max2[modelI], 2);
|
||
|
nmax = extrapsh(sdate, epoch[modelI], max1[modelI], max2[modelI], 3);
|
||
|
nmax = extrapsh(sdate+1, epoch[modelI], max1[modelI], max2[modelI], 4);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Do the first calculations */
|
||
|
shval3(igdgc, latitude, longitude, alt, nmax, 3,
|
||
|
IEXT, EXT_COEFF1, EXT_COEFF2, EXT_COEFF3);
|
||
|
dihf(3);
|
||
|
shval3(igdgc, latitude, longitude, alt, nmax, 4,
|
||
|
IEXT, EXT_COEFF1, EXT_COEFF2, EXT_COEFF3);
|
||
|
dihf(4);
|
||
|
|
||
|
|
||
|
ddot = ((dtemp - d)*RAD2DEG);
|
||
|
if (ddot > 180.0) ddot -= 360.0;
|
||
|
if (ddot <= -180.0) ddot += 360.0;
|
||
|
ddot *= 60.0;
|
||
|
|
||
|
idot = ((itemp - i)*RAD2DEG)*60;
|
||
|
d = d*(RAD2DEG); i = i*(RAD2DEG);
|
||
|
hdot = htemp - h; xdot = xtemp - x;
|
||
|
ydot = ytemp - y; zdot = ztemp - z;
|
||
|
fdot = ftemp - f;
|
||
|
|
||
|
/* deal with geographic and magnetic poles */
|
||
|
|
||
|
if (h < 100.0) /* at magnetic poles */
|
||
|
{
|
||
|
d = NaN;
|
||
|
ddot = NaN;
|
||
|
/* while rest is ok */
|
||
|
}
|
||
|
|
||
|
if (h < 1000.0)
|
||
|
{
|
||
|
warn_H = 0;
|
||
|
warn_H_strong = 1;
|
||
|
if (h<warn_H_strong_val) warn_H_strong_val = h;
|
||
|
}
|
||
|
else if (h < 5000.0 && !warn_H_strong)
|
||
|
{
|
||
|
warn_H = 1;
|
||
|
if (h<warn_H_val) warn_H_val = h;
|
||
|
}
|
||
|
|
||
|
if (90.0-fabs(latitude) <= 0.001) /* at geographic poles */
|
||
|
{
|
||
|
x = NaN;
|
||
|
y = NaN;
|
||
|
d = NaN;
|
||
|
xdot = NaN;
|
||
|
ydot = NaN;
|
||
|
ddot = NaN;
|
||
|
warn_P = 1;
|
||
|
warn_H = 0;
|
||
|
warn_H_strong = 0;
|
||
|
/* while rest is ok */
|
||
|
}
|
||
|
|
||
|
/** Above will compute everything for 1 point in time. **/
|
||
|
|
||
|
|
||
|
/* Output the final results. */
|
||
|
|
||
|
if (coords_from_file)
|
||
|
{
|
||
|
print_result_file(outfile, d, i, h, x, y, z, f,ddot,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("\n\n\n Model: %s \n", model[modelI]);
|
||
|
if (decdeg==1)
|
||
|
{
|
||
|
printf(" Latitude: %4.2f deg\n", latitude);
|
||
|
printf(" Longitude: %4.2f deg\n", longitude);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf(" Latitude: %d deg, %d min, %d sec\n",
|
||
|
ilat_deg,ilat_min, ilat_sec);
|
||
|
printf(" Longitude: %d deg, %d min, %d sec\n",
|
||
|
ilon_deg, ilon_min, ilon_sec);
|
||
|
}
|
||
|
printf(" Altitude: ");
|
||
|
if (units==1)
|
||
|
printf("%.2f km\n", alt);
|
||
|
else if (units==2)
|
||
|
printf("%.2f meters\n", alt*1000.0);
|
||
|
else
|
||
|
printf("%.2f ft\n", (alt*FT2KM));
|
||
|
|
||
|
if (range==1)
|
||
|
{
|
||
|
printf(" Date of Interest: ");
|
||
|
if (decyears==1)
|
||
|
printf(" %4.2f\n\n", sdate);
|
||
|
else
|
||
|
printf("%d-%d-%d (yyyy-mm-dd)\n\n", isyear, ismonth, isday);
|
||
|
|
||
|
print_header();
|
||
|
print_result(sdate,d, i, h, x, y, z, f);
|
||
|
print_long_dashed_line();
|
||
|
print_header_sv();
|
||
|
print_result_sv(sdate,ddot,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
print_dashed_line();
|
||
|
|
||
|
} /* if range == 1 */
|
||
|
else
|
||
|
{
|
||
|
printf(" Range of Interest: ");
|
||
|
if (decyears==1)
|
||
|
printf("%4.2f to %4.2f, step %4.2f\n\n",sdate, edate, step);
|
||
|
else
|
||
|
printf("%d-%d-%d to %d-%d-%d (yyyy-mm-dd), step %4.2f (years)\n\n", isyear, ismonth, isday, ieyear, iemonth, ieday, step);
|
||
|
|
||
|
print_header();
|
||
|
print_result(sdate,d, i, h, x, y, z, f);
|
||
|
|
||
|
for(syr=sdate+step;syr<(edate+step);syr+=step)
|
||
|
{
|
||
|
if ((syr>edate)&&(edate!=(syr-step)))
|
||
|
{
|
||
|
syr=edate;
|
||
|
print_long_dashed_line();
|
||
|
}
|
||
|
|
||
|
/* Do the calculations */
|
||
|
|
||
|
for (counter=0;counter<step;counter++)
|
||
|
{
|
||
|
if (max2[modelI] == 0){ /*If not last element in array */
|
||
|
if (syr>yrmin[modelI+1]){ /* And past model boundary */
|
||
|
modelI++; /* Get next model */
|
||
|
}
|
||
|
}
|
||
|
} /* for counter */
|
||
|
|
||
|
if (max2[modelI] == 0) /*If still not last element */
|
||
|
{
|
||
|
getshc(mdfile, 1, irec_pos[modelI], max1[modelI], 1);
|
||
|
getshc(mdfile, 1, irec_pos[modelI+1], max1[modelI+1], 2);
|
||
|
nmax = interpsh(syr, yrmin[modelI], max1[modelI],
|
||
|
yrmin[modelI+1], max1[modelI+1], 3);
|
||
|
nmax = interpsh(syr+1, yrmin[modelI] , max1[modelI],
|
||
|
yrmin[modelI+1], max1[modelI+1],4);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
getshc(mdfile, 1, irec_pos[modelI], max1[modelI], 1);
|
||
|
getshc(mdfile, 0, irec_pos[modelI], max2[modelI], 2);
|
||
|
nmax = extrapsh(syr, epoch[modelI], max1[modelI],
|
||
|
max2[modelI], 3);
|
||
|
nmax = extrapsh(syr+1, epoch[modelI], max1[modelI],
|
||
|
max2[modelI], 4);
|
||
|
}
|
||
|
shval3(igdgc, latitude, longitude, alt, nmax, 3,
|
||
|
IEXT, EXT_COEFF1, EXT_COEFF2, EXT_COEFF3);
|
||
|
dihf(3);
|
||
|
shval3(igdgc, latitude, longitude, alt, nmax, 4,
|
||
|
IEXT, EXT_COEFF1, EXT_COEFF2, EXT_COEFF3);
|
||
|
dihf(4);
|
||
|
|
||
|
ddot = ((dtemp - d)*RAD2DEG);
|
||
|
if (ddot > 180.0) ddot -= 360.0;
|
||
|
if (ddot <= -180.0) ddot += 360.0;
|
||
|
ddot *= 60.0;
|
||
|
|
||
|
idot = ((itemp - i)*RAD2DEG)*60.;
|
||
|
d = d*(RAD2DEG); i = i*(RAD2DEG);
|
||
|
hdot = htemp - h; xdot = xtemp - x;
|
||
|
ydot = ytemp - y; zdot = ztemp - z;
|
||
|
fdot = ftemp - f;
|
||
|
|
||
|
/* deal with geographic and magnetic poles */
|
||
|
|
||
|
if (h < 100.0) /* at magnetic poles */
|
||
|
{
|
||
|
d = NaN;
|
||
|
ddot = NaN;
|
||
|
/* while rest is ok */
|
||
|
}
|
||
|
|
||
|
if (90.0-fabs(latitude) <= 0.001) /* at geographic poles */
|
||
|
{
|
||
|
x = NaN;
|
||
|
y = NaN;
|
||
|
d = NaN;
|
||
|
xdot = NaN;
|
||
|
ydot = NaN;
|
||
|
ddot = NaN;
|
||
|
warn_P = 1;
|
||
|
warn_H = 0;
|
||
|
warn_H_strong = 0;
|
||
|
/* while rest is ok */
|
||
|
}
|
||
|
|
||
|
print_result(syr, d, i, h, x, y, z, f);
|
||
|
} /* for syr */
|
||
|
|
||
|
print_long_dashed_line();
|
||
|
print_header_sv();
|
||
|
print_result_sv(edate,ddot,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
print_dashed_line();
|
||
|
} /* if range > 1 */
|
||
|
|
||
|
if (warn_H)
|
||
|
{
|
||
|
printf("\nWarning: The horizontal field strength at this location is only %6.1f nT\n",warn_H_val);
|
||
|
printf(" Compass readings have large uncertainties in areas where H is\n");
|
||
|
printf(" smaller than 5000 nT\n\n");
|
||
|
}
|
||
|
if (warn_H_strong)
|
||
|
{
|
||
|
printf("\nWarning: The horizontal field strength at this location is only %6.1f nT\n",warn_H_strong_val);
|
||
|
printf(" Compass readings have VERY LARGE uncertainties in areas where H is\n");
|
||
|
printf(" smaller than 1000 nT\n\n");
|
||
|
}
|
||
|
if (warn_P)
|
||
|
{
|
||
|
printf("\nWarning: Location is at geographic pole where X, Y, and declination are not computed\n\n");
|
||
|
}
|
||
|
} /* if not coords_from_file */
|
||
|
|
||
|
if (coords_from_file)
|
||
|
again = !feof(coordfile) && !arg_err;
|
||
|
else
|
||
|
{
|
||
|
if (argc==7) again = 0; /* run command line only once */
|
||
|
else
|
||
|
do
|
||
|
{
|
||
|
printf("\n Enter");
|
||
|
printf("\n 0) to quit.");
|
||
|
printf("\n 1) to select a new model input file.");
|
||
|
printf("\n 2) to compute for a new point using same data file.");
|
||
|
printf("\n\n ==> ");
|
||
|
safegets(inbuff, MAXREAD);
|
||
|
again=atoi(inbuff);
|
||
|
if (again == 1) { need_to_read_model = 1; stream = NULL;}
|
||
|
if (again == 2) { need_to_read_model = 0; again = 1;}
|
||
|
}
|
||
|
while (again != 0 && again != 1);
|
||
|
} /* if not coords_from_file */
|
||
|
|
||
|
if (again == 1)
|
||
|
{
|
||
|
/* Reset defaults to catch on all while loops */
|
||
|
igdgc=decyears=units=decdeg=-1;
|
||
|
ismonth=isday=isyear=sdate=edate=range=step=-1;
|
||
|
latitude=ilat_deg=ilat_min=ilat_sec=200;
|
||
|
longitude=ilon_deg=ilon_min=ilon_sec=200;
|
||
|
alt=-9999999;
|
||
|
argc = 1;
|
||
|
}
|
||
|
} /* while (again == 1) */
|
||
|
|
||
|
reached_EOF:
|
||
|
if (coords_from_file) printf("\n Processed %1d lines\n\n",iline);
|
||
|
|
||
|
if (coords_from_file && !feof(coordfile) && arg_err) printf("Terminated prematurely due to argument error in coordinate file\n\n");
|
||
|
|
||
|
if (argc<7)
|
||
|
{
|
||
|
printf("\nThe same result could have been generated with the following command:\n");
|
||
|
printf("%s %s ", args[0], mdfile);
|
||
|
if (range == 1)
|
||
|
{
|
||
|
if (decyears==1)
|
||
|
{
|
||
|
printf("%4.2f ", sdate);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("%d,%d,%d ", isyear,ismonth,isday);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (decyears==1)
|
||
|
{
|
||
|
printf("%4.2f-%4.2f-%4.2f ", sdate,edate,step);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("%d,%d,%d-%d,%d,%d-%4.2f ", isyear,ismonth,isday,ieyear,iemonth,ieday,step);
|
||
|
}
|
||
|
}
|
||
|
if (igdgc==1)
|
||
|
{
|
||
|
printf("D ");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("C ");
|
||
|
}
|
||
|
if (units==1)
|
||
|
{
|
||
|
printf("K%.2f ", alt);
|
||
|
}
|
||
|
else if (units==2)
|
||
|
{
|
||
|
printf("M%.2f ", alt*1000.0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("F%.2f ", (alt*FT2KM));
|
||
|
}
|
||
|
if (decdeg==1)
|
||
|
{
|
||
|
printf("%3.2f %4.2f\n\n", latitude, longitude);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("%d,%d,%d %d,%d,%d\n\n", ilat_deg, ilat_min, ilat_sec,
|
||
|
ilon_deg, ilon_min, ilon_sec);
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void print_dashed_line(void)
|
||
|
{
|
||
|
printf(" -------------------------------------------------------------------------------\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void print_long_dashed_line(void)
|
||
|
{
|
||
|
printf(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void print_header(void)
|
||
|
{
|
||
|
print_dashed_line();
|
||
|
printf(" Date D I H X Y Z F\n");
|
||
|
printf(" (yr) (deg min) (deg min) (nT) (nT) (nT) (nT) (nT)\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void print_result(double date, double d, double i, double h, double x, double y, double z, double f)
|
||
|
{
|
||
|
int ddeg,ideg;
|
||
|
double dmin,imin;
|
||
|
|
||
|
/* Change d and i to deg and min */
|
||
|
|
||
|
ddeg=(int)d;
|
||
|
dmin=(d-(double)ddeg)*60;
|
||
|
if (d > 0 && dmin >= 59.5)
|
||
|
{
|
||
|
dmin -= 60.0;
|
||
|
ddeg++;
|
||
|
}
|
||
|
if (d < 0 && dmin <= -59.5)
|
||
|
{
|
||
|
dmin += 60.0;
|
||
|
ddeg--;
|
||
|
}
|
||
|
|
||
|
if (ddeg!=0) dmin=fabs(dmin);
|
||
|
ideg=(int)i;
|
||
|
imin=(i-(double)ideg)*60;
|
||
|
if (i > 0 && imin >= 59.5)
|
||
|
{
|
||
|
imin -= 60.0;
|
||
|
ideg++;
|
||
|
}
|
||
|
if (i < 0 && imin <= -59.5)
|
||
|
{
|
||
|
imin += 60.0;
|
||
|
ideg--;
|
||
|
}
|
||
|
if (ideg!=0) imin=fabs(imin);
|
||
|
|
||
|
|
||
|
if (my_isnan(d))
|
||
|
{
|
||
|
if (my_isnan(x))
|
||
|
printf(" %4.2f NaN %4dd %3.0fm %8.1f NaN NaN %8.1f %8.1f\n",date,ideg,imin,h,z,f);
|
||
|
else
|
||
|
printf(" %4.2f NaN %4dd %3.0fm %8.1f %8.1f %8.1f %8.1f %8.1f\n",date,ideg,imin,h,x,y,z,f);
|
||
|
}
|
||
|
else
|
||
|
printf(" %4.2f %4dd %3.0fm %4dd %3.0fm %8.1f %8.1f %8.1f %8.1f %8.1f\n",date,ddeg,dmin,ideg,imin,h,x,y,z,f);
|
||
|
return;
|
||
|
} /* print_result */
|
||
|
|
||
|
void print_header_sv(void)
|
||
|
{
|
||
|
printf(" Date dD dI dH dX dY dZ dF\n");
|
||
|
printf(" (yr) (min/yr) (min/yr) (nT/yr) (nT/yr) (nT/yr) (nT/yr) (nT/yr)\n");
|
||
|
} /* print_header_sv */
|
||
|
|
||
|
void print_result_sv(double date, double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot)
|
||
|
{
|
||
|
if (my_isnan(ddot))
|
||
|
{
|
||
|
if (my_isnan(xdot))
|
||
|
printf(" %4.2f NaN %7.1f %8.1f NaN NaN %8.1f %8.1f\n",date,idot,hdot,zdot,fdot);
|
||
|
else
|
||
|
printf(" %4.2f NaN %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n",date,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
}
|
||
|
else
|
||
|
printf(" %4.2f %7.1f %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n",date,ddot,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
return;
|
||
|
} /* print_result_sv */
|
||
|
|
||
|
void print_result_file(FILE *outf, double d, double i, double h, double x, double y, double z, double f,
|
||
|
double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot)
|
||
|
{
|
||
|
int ddeg,ideg;
|
||
|
double dmin,imin;
|
||
|
|
||
|
/* Change d and i to deg and min */
|
||
|
|
||
|
ddeg=(int)d;
|
||
|
dmin=(d-(double)ddeg)*60;
|
||
|
if (ddeg!=0) dmin=fabs(dmin);
|
||
|
ideg=(int)i;
|
||
|
imin=(i-(double)ideg)*60;
|
||
|
if (ideg!=0) imin=fabs(imin);
|
||
|
|
||
|
if (my_isnan(d))
|
||
|
{
|
||
|
if (my_isnan(x))
|
||
|
fprintf(outf," NaN %4dd %2.0fm %8.1f NaN NaN %8.1f %8.1f",ideg,imin,h,z,f);
|
||
|
else
|
||
|
fprintf(outf," NaN %4dd %2.0fm %8.1f %8.1f %8.1f %8.1f %8.1f",ideg,imin,h,x,y,z,f);
|
||
|
}
|
||
|
else
|
||
|
fprintf(outf," %4dd %2.0fm %4dd %2.0fm %8.1f %8.1f %8.1f %8.1f %8.1f",ddeg,dmin,ideg,imin,h,x,y,z,f);
|
||
|
|
||
|
if (my_isnan(ddot))
|
||
|
{
|
||
|
if (my_isnan(xdot))
|
||
|
fprintf(outf," NaN %7.1f %8.1f NaN NaN %8.1f %8.1f\n",idot,hdot,zdot,fdot);
|
||
|
else
|
||
|
fprintf(outf," NaN %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n",idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
}
|
||
|
else
|
||
|
fprintf(outf," %7.1f %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n",ddot,idot,hdot,xdot,ydot,zdot,fdot);
|
||
|
return;
|
||
|
} /* print_result_file */
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine safegets */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Gets characters from stdin untill it has reached n characters or \n, */
|
||
|
/* whichever comes first. \n is converted to \0. */
|
||
|
/* */
|
||
|
/* Input: n - Integer number of chars */
|
||
|
/* *buffer - Character array ptr which can contain n+1 characters */
|
||
|
/* */
|
||
|
/* Output: size - integer size of sting in buffer */
|
||
|
/* */
|
||
|
/* Note: All strings will be null terminated. */
|
||
|
/* */
|
||
|
/* By: David Owens */
|
||
|
/* dio@ngdc.noaa.gov */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
int safegets(char *buffer,int n){
|
||
|
char *ptr; /** ptr used for finding '\n' **/
|
||
|
|
||
|
buffer[0] = '\0';
|
||
|
fgets(buffer,n,stdin); /** Get n chars **/
|
||
|
buffer[n+1]='\0'; /** Set last char to null **/
|
||
|
ptr=strchr(buffer,'\n'); /** If string contains '\n' **/
|
||
|
if (ptr!=NULL){ /** If string contains '\n' **/
|
||
|
ptr[0]='\0'; /** Change char to '\0' **/
|
||
|
if (buffer[0] == '\0') printf("\n ... no entry ...\n");
|
||
|
}
|
||
|
|
||
|
return strlen(buffer); /** Return the length **/
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine degrees_to_decimal */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Converts degrees,minutes, seconds to decimal degrees. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* degrees - Integer degrees */
|
||
|
/* minutes - Integer minutes */
|
||
|
/* seconds - Integer seconds */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* decimal - degrees in decimal degrees */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 12, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
double degrees_to_decimal(int degrees,int minutes,int seconds)
|
||
|
{
|
||
|
double deg;
|
||
|
double min;
|
||
|
double sec;
|
||
|
double decimal;
|
||
|
|
||
|
deg = degrees;
|
||
|
min = minutes/60.0;
|
||
|
sec = seconds/3600.0;
|
||
|
|
||
|
decimal = fabs(sec) + fabs(min) + fabs(deg);
|
||
|
|
||
|
if (deg < 0) {
|
||
|
decimal = -decimal;
|
||
|
} else if (deg == 0){
|
||
|
if (min < 0){
|
||
|
decimal = -decimal;
|
||
|
} else if (min == 0){
|
||
|
if (sec<0){
|
||
|
decimal = -decimal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(decimal);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine julday */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Computes the decimal day of year from month, day, year. */
|
||
|
/* Supplied by Daniel Bergstrom */
|
||
|
/* */
|
||
|
/* References: */
|
||
|
/* */
|
||
|
/* 1. Nachum Dershowitz and Edward M. Reingold, Calendrical Calculations, */
|
||
|
/* Cambridge University Press, 3rd edition, ISBN 978-0-521-88540-9. */
|
||
|
/* */
|
||
|
/* 2. Claus Tøndering, Frequently Asked Questions about Calendars, */
|
||
|
/* Version 2.9, http://www.tondering.dk/claus/calendar.html */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
double julday(month, day, year)
|
||
|
int month;
|
||
|
int day;
|
||
|
int year;
|
||
|
{
|
||
|
int days[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||
|
|
||
|
int leap_year = (((year % 4) == 0) &&
|
||
|
(((year % 100) != 0) || ((year % 400) == 0)));
|
||
|
|
||
|
double day_in_year = (days[month - 1] + day + (month > 2 ? leap_year : 0));
|
||
|
|
||
|
return ((double)year + (day_in_year / (365.0 + leap_year)));
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine getshc */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Reads spherical harmonic coefficients from the specified */
|
||
|
/* model into an array. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* stream - Logical unit number */
|
||
|
/* iflag - Flag for SV equal to ) or not equal to 0 */
|
||
|
/* for designated read statements */
|
||
|
/* strec - Starting record number to read from model */
|
||
|
/* nmax_of_gh - Maximum degree and order of model */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* gh1 or 2 - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients */
|
||
|
/* */
|
||
|
/* FORTRAN */
|
||
|
/* Bill Flanagan */
|
||
|
/* NOAA CORPS, DESDIS, NGDC, 325 Broadway, Boulder CO. 80301 */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 15, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
int getshc(file, iflag, strec, nmax_of_gh, gh)
|
||
|
char file[PATH];
|
||
|
int iflag;
|
||
|
long int strec;
|
||
|
int nmax_of_gh;
|
||
|
int gh;
|
||
|
{
|
||
|
char inbuff[MAXINBUFF];
|
||
|
char irat[9];
|
||
|
int ii,m,n,mm,nn;
|
||
|
int ios;
|
||
|
int line_num;
|
||
|
double g,hh;
|
||
|
double trash;
|
||
|
|
||
|
stream = fopen(file, "rt");
|
||
|
if (stream == NULL)
|
||
|
{
|
||
|
printf("\nError on opening file %s", file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ii = 0;
|
||
|
ios = 0;
|
||
|
fseek(stream,strec,SEEK_SET);
|
||
|
for ( nn = 1; nn <= nmax_of_gh; ++nn)
|
||
|
{
|
||
|
for (mm = 0; mm <= nn; ++mm)
|
||
|
{
|
||
|
if (iflag == 1)
|
||
|
{
|
||
|
fgets(inbuff, MAXREAD, stream);
|
||
|
sscanf(inbuff, "%d%d%lg%lg%lg%lg%s%d",
|
||
|
&n, &m, &g, &hh, &trash, &trash, irat, &line_num);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fgets(inbuff, MAXREAD, stream);
|
||
|
sscanf(inbuff, "%d%d%lg%lg%lg%lg%s%d",
|
||
|
&n, &m, &trash, &trash, &g, &hh, irat, &line_num);
|
||
|
}
|
||
|
if ((nn != n) || (mm != m))
|
||
|
{
|
||
|
ios = -2;
|
||
|
fclose(stream);
|
||
|
return(ios);
|
||
|
}
|
||
|
ii = ii + 1;
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 1: gh1[ii] = g;
|
||
|
break;
|
||
|
case 2: gh2[ii] = g;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine getshc");
|
||
|
break;
|
||
|
}
|
||
|
if (m != 0)
|
||
|
{
|
||
|
ii = ii+ 1;
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 1: gh1[ii] = hh;
|
||
|
break;
|
||
|
case 2: gh2[ii] = hh;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine getshc");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(stream);
|
||
|
return(ios);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine extrapsh */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Extrapolates linearly a spherical harmonic model with a */
|
||
|
/* rate-of-change model. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* date - date of resulting model (in decimal year) */
|
||
|
/* dte1 - date of base model */
|
||
|
/* nmax1 - maximum degree and order of base model */
|
||
|
/* gh1 - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients of base model */
|
||
|
/* nmax2 - maximum degree and order of rate-of-change model */
|
||
|
/* gh2 - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients of rate-of-change model */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* gha or b - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients */
|
||
|
/* nmax - maximum degree and order of resulting model */
|
||
|
/* */
|
||
|
/* FORTRAN */
|
||
|
/* A. Zunde */
|
||
|
/* USGS, MS 964, box 25046 Federal Center, Denver, CO. 80225 */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 16, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
int extrapsh(date, dte1, nmax1, nmax2, gh)
|
||
|
double date;
|
||
|
double dte1;
|
||
|
int nmax1;
|
||
|
int nmax2;
|
||
|
int gh;
|
||
|
{
|
||
|
int nmax;
|
||
|
int k, l;
|
||
|
int ii;
|
||
|
double factor;
|
||
|
|
||
|
factor = date - dte1;
|
||
|
if (nmax1 == nmax2)
|
||
|
{
|
||
|
k = nmax1 * (nmax1 + 2);
|
||
|
nmax = nmax1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (nmax1 > nmax2)
|
||
|
{
|
||
|
k = nmax2 * (nmax2 + 2);
|
||
|
l = nmax1 * (nmax1 + 2);
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
gha[ii] = gh1[ii];
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
ghb[ii] = gh1[ii];
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
nmax = nmax1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
k = nmax1 * (nmax1 + 2);
|
||
|
l = nmax2 * (nmax2 + 2);
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
gha[ii] = factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
ghb[ii] = factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
nmax = nmax2;
|
||
|
}
|
||
|
}
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = 1; ii <= k; ++ii)
|
||
|
{
|
||
|
gha[ii] = gh1[ii] + factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = 1; ii <= k; ++ii)
|
||
|
{
|
||
|
ghb[ii] = gh1[ii] + factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
return(nmax);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine interpsh */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Interpolates linearly, in time, between two spherical harmonic */
|
||
|
/* models. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* date - date of resulting model (in decimal year) */
|
||
|
/* dte1 - date of earlier model */
|
||
|
/* nmax1 - maximum degree and order of earlier model */
|
||
|
/* gh1 - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients of earlier model */
|
||
|
/* dte2 - date of later model */
|
||
|
/* nmax2 - maximum degree and order of later model */
|
||
|
/* gh2 - Schmidt quasi-normal internal spherical */
|
||
|
/* harmonic coefficients of internal model */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* gha or b - coefficients of resulting model */
|
||
|
/* nmax - maximum degree and order of resulting model */
|
||
|
/* */
|
||
|
/* FORTRAN */
|
||
|
/* A. Zunde */
|
||
|
/* USGS, MS 964, box 25046 Federal Center, Denver, CO. 80225 */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 17, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
int interpsh(date, dte1, nmax1, dte2, nmax2, gh)
|
||
|
double date;
|
||
|
double dte1;
|
||
|
int nmax1;
|
||
|
double dte2;
|
||
|
int nmax2;
|
||
|
int gh;
|
||
|
{
|
||
|
int nmax;
|
||
|
int k, l;
|
||
|
int ii;
|
||
|
double factor;
|
||
|
|
||
|
factor = (date - dte1) / (dte2 - dte1);
|
||
|
if (nmax1 == nmax2)
|
||
|
{
|
||
|
k = nmax1 * (nmax1 + 2);
|
||
|
nmax = nmax1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (nmax1 > nmax2)
|
||
|
{
|
||
|
k = nmax2 * (nmax2 + 2);
|
||
|
l = nmax1 * (nmax1 + 2);
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
gha[ii] = gh1[ii] + factor * (-gh1[ii]);
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
ghb[ii] = gh1[ii] + factor * (-gh1[ii]);
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
nmax = nmax1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
k = nmax1 * (nmax1 + 2);
|
||
|
l = nmax2 * (nmax2 + 2);
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
gha[ii] = factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = k + 1; ii <= l; ++ii)
|
||
|
{
|
||
|
ghb[ii] = factor * gh2[ii];
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
nmax = nmax2;
|
||
|
}
|
||
|
}
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for ( ii = 1; ii <= k; ++ii)
|
||
|
{
|
||
|
gha[ii] = gh1[ii] + factor * (gh2[ii] - gh1[ii]);
|
||
|
}
|
||
|
break;
|
||
|
case 4: for ( ii = 1; ii <= k; ++ii)
|
||
|
{
|
||
|
ghb[ii] = gh1[ii] + factor * (gh2[ii] - gh1[ii]);
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine extrapsh");
|
||
|
break;
|
||
|
}
|
||
|
return(nmax);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine shval3 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Calculates field components from spherical harmonic (sh) */
|
||
|
/* models. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* igdgc - indicates coordinate system used; set equal */
|
||
|
/* to 1 if geodetic, 2 if geocentric */
|
||
|
/* latitude - north latitude, in degrees */
|
||
|
/* longitude - east longitude, in degrees */
|
||
|
/* elev - WGS84 altitude above ellipsoid (igdgc=1), or */
|
||
|
/* radial distance from earth's center (igdgc=2) */
|
||
|
/* a2,b2 - squares of semi-major and semi-minor axes of */
|
||
|
/* the reference spheroid used for transforming */
|
||
|
/* between geodetic and geocentric coordinates */
|
||
|
/* or components */
|
||
|
/* nmax - maximum degree and order of coefficients */
|
||
|
/* iext - external coefficients flag (=0 if none) */
|
||
|
/* ext1,2,3 - the three 1st-degree external coefficients */
|
||
|
/* (not used if iext = 0) */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* x - northward component */
|
||
|
/* y - eastward component */
|
||
|
/* z - vertically-downward component */
|
||
|
/* */
|
||
|
/* based on subroutine 'igrf' by D. R. Barraclough and S. R. C. Malin, */
|
||
|
/* report no. 71/1, institute of geological sciences, U.K. */
|
||
|
/* */
|
||
|
/* FORTRAN */
|
||
|
/* Norman W. Peddie */
|
||
|
/* USGS, MS 964, box 25046 Federal Center, Denver, CO. 80225 */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 17, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
int shval3(igdgc, flat, flon, elev, nmax, gh, iext, ext1, ext2, ext3)
|
||
|
int igdgc;
|
||
|
double flat;
|
||
|
double flon;
|
||
|
double elev;
|
||
|
int nmax;
|
||
|
int gh;
|
||
|
int iext;
|
||
|
double ext1;
|
||
|
double ext2;
|
||
|
double ext3;
|
||
|
{
|
||
|
double earths_radius = 6371.2;
|
||
|
double dtr = 0.01745329;
|
||
|
double slat;
|
||
|
double clat;
|
||
|
double ratio;
|
||
|
double aa, bb, cc, dd;
|
||
|
double sd;
|
||
|
double cd;
|
||
|
double r;
|
||
|
double a2;
|
||
|
double b2;
|
||
|
double rr;
|
||
|
double fm,fn;
|
||
|
double sl[14];
|
||
|
double cl[14];
|
||
|
double p[119];
|
||
|
double q[119];
|
||
|
int ii,j,k,l,m,n;
|
||
|
int npq;
|
||
|
int ios;
|
||
|
double argument;
|
||
|
double power;
|
||
|
a2 = 40680631.59; /* WGS84 */
|
||
|
b2 = 40408299.98; /* WGS84 */
|
||
|
ios = 0;
|
||
|
r = elev;
|
||
|
argument = flat * dtr;
|
||
|
slat = sin( argument );
|
||
|
if ((90.0 - flat) < 0.001)
|
||
|
{
|
||
|
aa = 89.999; /* 300 ft. from North pole */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((90.0 + flat) < 0.001)
|
||
|
{
|
||
|
aa = -89.999; /* 300 ft. from South pole */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aa = flat;
|
||
|
}
|
||
|
}
|
||
|
argument = aa * dtr;
|
||
|
clat = cos( argument );
|
||
|
argument = flon * dtr;
|
||
|
sl[1] = sin( argument );
|
||
|
cl[1] = cos( argument );
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: x = 0;
|
||
|
y = 0;
|
||
|
z = 0;
|
||
|
break;
|
||
|
case 4: xtemp = 0;
|
||
|
ytemp = 0;
|
||
|
ztemp = 0;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
sd = 0.0;
|
||
|
cd = 1.0;
|
||
|
l = 1;
|
||
|
n = 0;
|
||
|
m = 1;
|
||
|
npq = (nmax * (nmax + 3)) / 2;
|
||
|
if (igdgc == 1)
|
||
|
{
|
||
|
aa = a2 * clat * clat;
|
||
|
bb = b2 * slat * slat;
|
||
|
cc = aa + bb;
|
||
|
argument = cc;
|
||
|
dd = sqrt( argument );
|
||
|
argument = elev * (elev + 2.0 * dd) + (a2 * aa + b2 * bb) / cc;
|
||
|
r = sqrt( argument );
|
||
|
cd = (elev + dd) / r;
|
||
|
sd = (a2 - b2) / dd * slat * clat / r;
|
||
|
aa = slat;
|
||
|
slat = slat * cd - clat * sd;
|
||
|
clat = clat * cd + aa * sd;
|
||
|
}
|
||
|
ratio = earths_radius / r;
|
||
|
argument = 3.0;
|
||
|
aa = sqrt( argument );
|
||
|
p[1] = 2.0 * slat;
|
||
|
p[2] = 2.0 * clat;
|
||
|
p[3] = 4.5 * slat * slat - 1.5;
|
||
|
p[4] = 3.0 * aa * clat * slat;
|
||
|
q[1] = -clat;
|
||
|
q[2] = slat;
|
||
|
q[3] = -3.0 * clat * slat;
|
||
|
q[4] = aa * (slat * slat - clat * clat);
|
||
|
for ( k = 1; k <= npq; ++k)
|
||
|
{
|
||
|
if (n < m)
|
||
|
{
|
||
|
m = 0;
|
||
|
n = n + 1;
|
||
|
argument = ratio;
|
||
|
power = n + 2;
|
||
|
rr = pow(argument,power);
|
||
|
fn = n;
|
||
|
}
|
||
|
fm = m;
|
||
|
if (k >= 5)
|
||
|
{
|
||
|
if (m == n)
|
||
|
{
|
||
|
argument = (1.0 - 0.5/fm);
|
||
|
aa = sqrt( argument );
|
||
|
j = k - n - 1;
|
||
|
p[k] = (1.0 + 1.0/fm) * aa * clat * p[j];
|
||
|
q[k] = aa * (clat * q[j] + slat/fm * p[j]);
|
||
|
sl[m] = sl[m-1] * cl[1] + cl[m-1] * sl[1];
|
||
|
cl[m] = cl[m-1] * cl[1] - sl[m-1] * sl[1];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
argument = fn*fn - fm*fm;
|
||
|
aa = sqrt( argument );
|
||
|
argument = ((fn - 1.0)*(fn-1.0)) - (fm * fm);
|
||
|
bb = sqrt( argument )/aa;
|
||
|
cc = (2.0 * fn - 1.0)/aa;
|
||
|
ii = k - n;
|
||
|
j = k - 2 * n + 1;
|
||
|
p[k] = (fn + 1.0) * (cc * slat/fn * p[ii] - bb/(fn - 1.0) * p[j]);
|
||
|
q[k] = cc * (slat * q[ii] - clat/fn * p[ii]) - bb * q[j];
|
||
|
}
|
||
|
}
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: aa = rr * gha[l];
|
||
|
break;
|
||
|
case 4: aa = rr * ghb[l];
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
if (m == 0)
|
||
|
{
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: x = x + aa * q[k];
|
||
|
z = z - aa * p[k];
|
||
|
break;
|
||
|
case 4: xtemp = xtemp + aa * q[k];
|
||
|
ztemp = ztemp - aa * p[k];
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
l = l + 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: bb = rr * gha[l+1];
|
||
|
cc = aa * cl[m] + bb * sl[m];
|
||
|
x = x + cc * q[k];
|
||
|
z = z - cc * p[k];
|
||
|
if (clat > 0)
|
||
|
{
|
||
|
y = y + (aa * sl[m] - bb * cl[m]) *
|
||
|
fm * p[k]/((fn + 1.0) * clat);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
y = y + (aa * sl[m] - bb * cl[m]) * q[k] * slat;
|
||
|
}
|
||
|
l = l + 2;
|
||
|
break;
|
||
|
case 4: bb = rr * ghb[l+1];
|
||
|
cc = aa * cl[m] + bb * sl[m];
|
||
|
xtemp = xtemp + cc * q[k];
|
||
|
ztemp = ztemp - cc * p[k];
|
||
|
if (clat > 0)
|
||
|
{
|
||
|
ytemp = ytemp + (aa * sl[m] - bb * cl[m]) *
|
||
|
fm * p[k]/((fn + 1.0) * clat);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ytemp = ytemp + (aa * sl[m] - bb * cl[m]) *
|
||
|
q[k] * slat;
|
||
|
}
|
||
|
l = l + 2;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
m = m + 1;
|
||
|
}
|
||
|
if (iext != 0)
|
||
|
{
|
||
|
aa = ext2 * cl[1] + ext3 * sl[1];
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: x = x - ext1 * clat + aa * slat;
|
||
|
y = y + ext2 * sl[1] - ext3 * cl[1];
|
||
|
z = z + ext1 * slat + aa * clat;
|
||
|
break;
|
||
|
case 4: xtemp = xtemp - ext1 * clat + aa * slat;
|
||
|
ytemp = ytemp + ext2 * sl[1] - ext3 * cl[1];
|
||
|
ztemp = ztemp + ext1 * slat + aa * clat;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: aa = x;
|
||
|
x = x * cd + z * sd;
|
||
|
z = z * cd - aa * sd;
|
||
|
break;
|
||
|
case 4: aa = xtemp;
|
||
|
xtemp = xtemp * cd + ztemp * sd;
|
||
|
ztemp = ztemp * cd - aa * sd;
|
||
|
break;
|
||
|
default: printf("\nError in subroutine shval3");
|
||
|
break;
|
||
|
}
|
||
|
return(ios);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Subroutine dihf */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* Computes the geomagnetic d, i, h, and f from x, y, and z. */
|
||
|
/* */
|
||
|
/* Input: */
|
||
|
/* x - northward component */
|
||
|
/* y - eastward component */
|
||
|
/* z - vertically-downward component */
|
||
|
/* */
|
||
|
/* Output: */
|
||
|
/* d - declination */
|
||
|
/* i - inclination */
|
||
|
/* h - horizontal intensity */
|
||
|
/* f - total intensity */
|
||
|
/* */
|
||
|
/* FORTRAN */
|
||
|
/* A. Zunde */
|
||
|
/* USGS, MS 964, box 25046 Federal Center, Denver, CO. 80225 */
|
||
|
/* */
|
||
|
/* C */
|
||
|
/* C. H. Shaffer */
|
||
|
/* Lockheed Missiles and Space Company, Sunnyvale CA */
|
||
|
/* August 22, 1988 */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
int dihf (gh)
|
||
|
int gh;
|
||
|
{
|
||
|
int ios;
|
||
|
int j;
|
||
|
double sn;
|
||
|
double h2;
|
||
|
double hpx;
|
||
|
double argument, argument2;
|
||
|
|
||
|
ios = gh;
|
||
|
sn = 0.0001;
|
||
|
|
||
|
switch(gh)
|
||
|
{
|
||
|
case 3: for (j = 1; j <= 1; ++j)
|
||
|
{
|
||
|
h2 = x*x + y*y;
|
||
|
argument = h2;
|
||
|
h = sqrt(argument); /* calculate horizontal intensity */
|
||
|
argument = h2 + z*z;
|
||
|
f = sqrt(argument); /* calculate total intensity */
|
||
|
if (f < sn)
|
||
|
{
|
||
|
d = NaN; /* If d and i cannot be determined, */
|
||
|
i = NaN; /* set equal to NaN */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
argument = z;
|
||
|
argument2 = h;
|
||
|
i = atan2(argument,argument2);
|
||
|
if (h < sn)
|
||
|
{
|
||
|
d = NaN;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hpx = h + x;
|
||
|
if (hpx < sn)
|
||
|
{
|
||
|
d = PI;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
argument = y;
|
||
|
argument2 = hpx;
|
||
|
d = 2.0 * atan2(argument,argument2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 4: for (j = 1; j <= 1; ++j)
|
||
|
{
|
||
|
h2 = xtemp*xtemp + ytemp*ytemp;
|
||
|
argument = h2;
|
||
|
htemp = sqrt(argument);
|
||
|
argument = h2 + ztemp*ztemp;
|
||
|
ftemp = sqrt(argument);
|
||
|
if (ftemp < sn)
|
||
|
{
|
||
|
dtemp = NaN; /* If d and i cannot be determined, */
|
||
|
itemp = NaN; /* set equal to 999.0 */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
argument = ztemp;
|
||
|
argument2 = htemp;
|
||
|
itemp = atan2(argument,argument2);
|
||
|
if (htemp < sn)
|
||
|
{
|
||
|
dtemp = NaN;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hpx = htemp + xtemp;
|
||
|
if (hpx < sn)
|
||
|
{
|
||
|
dtemp = PI;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
argument = ytemp;
|
||
|
argument2 = hpx;
|
||
|
dtemp = 2.0 * atan2(argument,argument2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default: printf("\nError in subroutine dihf");
|
||
|
break;
|
||
|
}
|
||
|
return(ios);
|
||
|
}
|