367 lines
9.8 KiB
C++
367 lines
9.8 KiB
C++
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <math.h>
|
||
|
#include <fstream>
|
||
|
#include <iostream> // Added by Zhang Yi on 2021-08-26
|
||
|
#include <string>
|
||
|
|
||
|
#include "../lib/constants.h"
|
||
|
#include "../lib/parsers.h"
|
||
|
#include "../lib/linalg.h"
|
||
|
|
||
|
#define MAX_GRID_POINTS 50000
|
||
|
|
||
|
#define GRID_FORMAT "%lf %lf %f %lf"
|
||
|
|
||
|
#if defined(_MSC_VER) /* Added for windows by Yi Zhang on 2021-08-26*/
|
||
|
#include <BaseTsd.h>
|
||
|
typedef SSIZE_T ssize_t;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// TODO conversion of input/output units nT/km pT/km nT/m pT/m
|
||
|
|
||
|
|
||
|
void printcomp(double* longitudes, double* latitudes, double* values, int n_values)
|
||
|
{
|
||
|
|
||
|
|
||
|
for (int h = 0; h < n_values; h++)
|
||
|
printf("%lf %lf %lf\n", longitudes[h], latitudes[h], values[h]);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void printall(double* longitudes, double* latitudes, int n_values, double* values1, double* values2, double* values3, double* values4, double* values5, double* values6, double* values7)
|
||
|
{
|
||
|
|
||
|
|
||
|
for (int h = 0; h < n_values; h++)
|
||
|
printf("%lf %lf %lf %lf %lf %lf %lf %lf %lf\n", longitudes[h], latitudes[h], values1[h], values2[h], values3[h], values4[h], values5[h], values6[h], values7[h]);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void print_gradcalc_help(const char *progname)
|
||
|
{
|
||
|
printf("MAGNETIC TESSEROIDS: Gradient Calculator\n");
|
||
|
printf("Usage: %s [OPTIONS]\n\n", progname);
|
||
|
printf("Options:\n");
|
||
|
printf("\t-h\t\t\t Help\n\n");
|
||
|
|
||
|
printf("\t-bx[GRID FILENAME]\t Grid filename with Bx component\n");
|
||
|
printf("\t-by[GRID FILENAME]\t Grid filename with By component\n");
|
||
|
printf("\t-bz[GRID FILENAME]\t Grid filename with Bz component\n");
|
||
|
printf("\tNOTE:\tall grids must be in format LON LAT ALT B*,\n\t\tstart from West-South corner and longitudes must increment first.\n\t\tLON, LAT in [deg], B* in [nT] and ALT in [m].\n\n");
|
||
|
|
||
|
printf("\t-c[COORD SYSTEM]\t Coordinate system in input grids. 1 - North-East-Down, 2 - North-East-Up\n");
|
||
|
printf("\t-o[COMPONENT]\t\t If 0, then output format is LON LAT BXX BYX BZX BXY BYY BZY BZZ, if 1-7, then \n");
|
||
|
printf("\tonly corresponding component would be printed with format LON LAT B**.\n");
|
||
|
printf("\tNOTE: output is always in North-East-Down coordinate system.\n\t\tLON, LAT in [deg], B** in [nT/km].\n");
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//printf("TODO\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int main(int argc, char**argv)
|
||
|
{
|
||
|
const char * progname = "tessutil_gradient_calculator";
|
||
|
GRADCALC_ARGS args;
|
||
|
int rc;
|
||
|
|
||
|
|
||
|
//log_init(LOG_INFO);
|
||
|
|
||
|
rc = parse_gradcalc_args(argc, argv, progname, &args, &print_gradcalc_help);
|
||
|
if(rc == 2) //help
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
if(rc == 1)
|
||
|
{
|
||
|
printf("Terminating due to bad input\n");
|
||
|
printf("Try '%s -h' for instructions\n", progname);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if ((args.gridbx_set == 0) || (args.gridbx_set == 0) || (args.gridbx_set == 0))
|
||
|
{
|
||
|
printf("no input grids\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if (args.bz_NEU_NED == 1)
|
||
|
printf("#Coordinate system in input grids: North-East-Down\n");
|
||
|
else
|
||
|
printf("#Coordinate system in input grids: North-East-Up\n");
|
||
|
printf("#Coordinate system in output grid: North-East-Down\n");
|
||
|
|
||
|
|
||
|
double lons[MAX_GRID_POINTS];
|
||
|
double lats[MAX_GRID_POINTS];
|
||
|
float alts[MAX_GRID_POINTS];
|
||
|
|
||
|
double bx[MAX_GRID_POINTS];
|
||
|
double by[MAX_GRID_POINTS];
|
||
|
double bz[MAX_GRID_POINTS];
|
||
|
//read file with bx
|
||
|
|
||
|
//char * line = NULL;
|
||
|
std::string line;
|
||
|
size_t len = 0;
|
||
|
ssize_t read;
|
||
|
|
||
|
|
||
|
|
||
|
//FILE * bxfp = fopen(args.gridbx_fn, "r");
|
||
|
//if (bxfp == NULL)
|
||
|
std::ifstream bxfp(args.gridbx_fn, std::ios::in); // Updated by Yi Zhang on 2021-08-26
|
||
|
if (!bxfp)
|
||
|
{
|
||
|
printf("ERROR: Can not open file with Bx values.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
int n_lines = 0;
|
||
|
|
||
|
|
||
|
|
||
|
//while ((read = getline(&line, &len, bxfp )) != -1)
|
||
|
while (getline(bxfp, line))
|
||
|
{
|
||
|
|
||
|
//if ((line[0] != '#') && (strlen(line) > 2))
|
||
|
if ((line[0] != '#') && (line.length() > 2))
|
||
|
{
|
||
|
n_lines++;
|
||
|
if (n_lines>MAX_GRID_POINTS)
|
||
|
{
|
||
|
printf("ERROR: Too many grid points (> %d) in the input. Recompile program with a bigger value of MAX_GRID_POINTS.\n", n_lines);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
sscanf(line.c_str(), GRID_FORMAT, &lons[n_lines-1], &lats[n_lines-1], &alts[n_lines-1], &bx[n_lines-1]);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
//fclose(bxfp);
|
||
|
bxfp.close();
|
||
|
|
||
|
|
||
|
/*number of grid points*/
|
||
|
printf("#Number of grid points: %d\n", n_lines);
|
||
|
|
||
|
/*grid spacing*/
|
||
|
|
||
|
double lon_min = lons[0];
|
||
|
double lon_max = lons[n_lines-1];
|
||
|
|
||
|
double lon_step = lons[1]-lons[0];
|
||
|
if ((lon_step == 0) || (lon_step <= 0) || (lon_max < lon_min))
|
||
|
{
|
||
|
printf("ERROR: Wrong grid format. Longitudes must increment first. Use the format of tessgrd.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
int lon_n = 1;
|
||
|
while ((lats[lon_n] == lats[0]) && (lon_n < n_lines))
|
||
|
{
|
||
|
lon_n++;
|
||
|
}
|
||
|
double lat_step = lats[lon_n]-lats[0];
|
||
|
|
||
|
int lat_n = n_lines / lon_n;
|
||
|
|
||
|
double lat_min = lats[0];
|
||
|
double lat_max = lats[n_lines-1];
|
||
|
|
||
|
|
||
|
|
||
|
if ((lat_step <= 0) || (lat_step <= 0) || (lat_max < lat_min))
|
||
|
{
|
||
|
printf("ERROR: Wrong grid format. Latitudes must increment. Use the format of tessgrd.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
printf("#Longitudinal step: %lf, latitudinal step: %lf \n", lon_step, lat_step);
|
||
|
printf("#Longitudinal points: %d, latitudinal points: %d \n", lon_n, lat_n);
|
||
|
printf("#Edges: W %lf, E %lf, S %lf, N %lf \n", lon_min, lon_max, lat_min, lat_max);
|
||
|
|
||
|
/* read other grids */
|
||
|
// By
|
||
|
//FILE * byfp = fopen(args.gridby_fn, "r");
|
||
|
//if (byfp == NULL)
|
||
|
|
||
|
std::ifstream byfp(args.gridby_fn, std::ios::in);
|
||
|
if (!byfp)
|
||
|
{
|
||
|
printf("ERROR: Can not open file with Bx values.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
int n_lines2 = 0;
|
||
|
//while ((read = getline(&line, &len, byfp )) != -1)
|
||
|
while (getline(byfp, line))
|
||
|
{
|
||
|
|
||
|
//if ((line[0] != '#') && (strlen(line) > 2))
|
||
|
if ((line[0] != '#') && (line.length() > 2))
|
||
|
{
|
||
|
n_lines2++;
|
||
|
//printf("%s", line);
|
||
|
double dummy1, dummy2;
|
||
|
float dummy3;
|
||
|
sscanf(line.c_str(), GRID_FORMAT , &dummy1, &dummy2, &dummy3, &by[n_lines2-1]);
|
||
|
}
|
||
|
}
|
||
|
//fclose(byfp);
|
||
|
byfp.close();
|
||
|
|
||
|
if (n_lines2 != n_lines)
|
||
|
{
|
||
|
printf("ERROR: Grid points of Bx and By do not coincide.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
// Bz
|
||
|
//FILE * bzfp = fopen(args.gridbz_fn, "r");
|
||
|
//if (bzfp == NULL)
|
||
|
std::ifstream bzfp(args.gridbz_fn, std::ios::in);
|
||
|
if (!bzfp)
|
||
|
{
|
||
|
printf("ERROR: Can not open file with Bx values.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
n_lines2 = 0;
|
||
|
//while ((read = getline(&line, &len, bzfp )) != -1)
|
||
|
while (getline(bzfp, line))
|
||
|
{
|
||
|
if ((line[0] != '#') && (line.length() > 2))
|
||
|
{
|
||
|
n_lines2++;
|
||
|
//printf("%s", line);
|
||
|
double dummy1, dummy2;
|
||
|
float dummy3;
|
||
|
double bz_curr;
|
||
|
sscanf(line.c_str(), GRID_FORMAT, &dummy1, &dummy2, &dummy3,&bz_curr);
|
||
|
|
||
|
bz[n_lines2-1] = args.bz_NEU_NED* bz_curr; //COORDINATE SYSTEM NEU or NED
|
||
|
}
|
||
|
}
|
||
|
//fclose(byfp);
|
||
|
byfp.close();
|
||
|
|
||
|
if (n_lines2 != n_lines)
|
||
|
{
|
||
|
printf("ERROR: Grid points of Bx and Bz do not coincide.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* calculate gradients */
|
||
|
|
||
|
|
||
|
double bxx[MAX_GRID_POINTS];
|
||
|
double byx[MAX_GRID_POINTS];
|
||
|
double bzx[MAX_GRID_POINTS];
|
||
|
|
||
|
double bxy[MAX_GRID_POINTS];
|
||
|
double byy[MAX_GRID_POINTS];
|
||
|
double bzy[MAX_GRID_POINTS];
|
||
|
|
||
|
double bzz[MAX_GRID_POINTS];
|
||
|
|
||
|
int cent_ind, west_ind, east_ind, south_ind, north_ind;
|
||
|
|
||
|
for (int i = 1; i<lon_n-1; i++)
|
||
|
{
|
||
|
for (int j = 1; j<lat_n-1; j++)
|
||
|
{
|
||
|
cent_ind = (j) *lon_n + (i);
|
||
|
west_ind = (j) *lon_n + (i-1);
|
||
|
east_ind = (j) *lon_n + (i+1);
|
||
|
south_ind = (j-1) *lon_n + (i);
|
||
|
north_ind = (j+1) *lon_n + (i);
|
||
|
|
||
|
//double vect_cent[3] = {bx[cent_ind], by[cent_ind], bz[cent_ind]};
|
||
|
double vect_west[3] = {bx[west_ind], by[west_ind], bz[west_ind]};
|
||
|
double vect_east[3] = {bx[east_ind], by[east_ind], bz[east_ind]};
|
||
|
double vect_south[3] = {bx[south_ind], by[south_ind], bz[south_ind]};
|
||
|
double vect_north[3] = {bx[north_ind], by[north_ind], bz[north_ind]};
|
||
|
|
||
|
double vect_c_west[3];
|
||
|
double vect_c_east[3];
|
||
|
double vect_c_south[3];
|
||
|
double vect_c_north[3];
|
||
|
|
||
|
from_loc_sphr_to_loc_sphr(vect_west, lats[west_ind], lons[west_ind], lats[cent_ind], lons[cent_ind], vect_c_west);
|
||
|
from_loc_sphr_to_loc_sphr(vect_east, lats[east_ind], lons[east_ind], lats[cent_ind], lons[cent_ind], vect_c_east);
|
||
|
from_loc_sphr_to_loc_sphr(vect_south, lats[south_ind], lons[south_ind], lats[cent_ind], lons[cent_ind], vect_c_south);
|
||
|
from_loc_sphr_to_loc_sphr(vect_north, lats[north_ind], lons[north_ind], lats[cent_ind], lons[cent_ind], vect_c_north);
|
||
|
|
||
|
double cent_ang_sn = acos(sin(lats[south_ind]*DEG2RAD)*sin(lats[north_ind]*DEG2RAD) + cos(lats[south_ind]*DEG2RAD)*cos(lats[north_ind]*DEG2RAD)*cos(abs(lons[south_ind]-lons[north_ind])*DEG2RAD));
|
||
|
double cent_ang_we = acos(sin(lats[west_ind]*DEG2RAD)*sin(lats[east_ind]*DEG2RAD) + cos(lats[west_ind]*DEG2RAD)*cos(lats[east_ind]*DEG2RAD)*cos(abs(lons[west_ind]-lons[east_ind])*DEG2RAD));
|
||
|
|
||
|
double dist_sn = (MEAN_EARTH_RADIUS + alts[cent_ind])*cent_ang_sn;
|
||
|
double dist_we = (MEAN_EARTH_RADIUS + alts[cent_ind])*cent_ang_we;
|
||
|
|
||
|
bxx[cent_ind] = -(vect_c_south[0]-vect_c_north[0])/dist_sn*1000.0;
|
||
|
byx[cent_ind] = -(vect_c_south[1]-vect_c_north[1])/dist_sn*1000.0;
|
||
|
bzx[cent_ind] = -(vect_c_south[2]-vect_c_north[2])/dist_sn*1000.0;
|
||
|
|
||
|
bxy[cent_ind] = -(vect_c_west[0]-vect_c_east[0])/dist_we*1000.0;
|
||
|
byy[cent_ind] = -(vect_c_west[1]-vect_c_east[1])/dist_we*1000.0;
|
||
|
bzy[cent_ind] = -(vect_c_west[2]-vect_c_east[2])/dist_we*1000.0;
|
||
|
|
||
|
bzz[cent_ind] = -bxx[cent_ind] - byy[cent_ind];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
switch(args.out_set)
|
||
|
{
|
||
|
case 1:
|
||
|
printf("#Component Bxx\n");
|
||
|
printcomp(lons, lats, bxx, n_lines);
|
||
|
break;
|
||
|
case 2:
|
||
|
printf("#Component Byx\n");
|
||
|
printcomp(lons, lats, byx, n_lines);
|
||
|
break;
|
||
|
case 3:
|
||
|
printf("#Component Bzx\n");
|
||
|
printcomp(lons, lats, bzx, n_lines);
|
||
|
break;
|
||
|
case 4:
|
||
|
printf("#Component Bxy\n");
|
||
|
printcomp(lons, lats, bxy, n_lines);
|
||
|
break;
|
||
|
case 5:
|
||
|
printf("#Component Byy\n");
|
||
|
printcomp(lons, lats, byy, n_lines);
|
||
|
break;
|
||
|
case 6:
|
||
|
printf("#Component Bzy\n");
|
||
|
printcomp(lons, lats, bzy, n_lines);
|
||
|
break;
|
||
|
case 7:
|
||
|
printf("#Component Bzz\n");
|
||
|
printcomp(lons, lats, bzz, n_lines);
|
||
|
break;
|
||
|
default:
|
||
|
printf("#All components: Bxx, Byx, Bzx, Bxy, Byy, Bzy, Bzz\n");
|
||
|
printall(lons, lats, n_lines, bxx, byx, bzx, bxy, byy, bzy, bzz);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|