gctl/dep/magnetic_tesseroids/toolkits/tessutil_gradient_calculator.cpp

367 lines
9.8 KiB
C++
Raw Normal View History

2024-09-10 15:45:07 +08:00
#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;
}
}