initial upload
This commit is contained in:
49
lib/CMakeLists.txt
Normal file
49
lib/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lopenblas -lm -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lopenblas -lm -O2")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -framework Accelerate -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework Accelerate -O2")
|
||||
endif()
|
||||
|
||||
# 设置库文件的输出地址
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||
|
||||
# 设定库源文件
|
||||
aux_source_directory(. LIBMAGTESS_SRC)
|
||||
|
||||
# 以下部分为库的编译
|
||||
# 注意目标名必须唯一 所以不能直接生成相同名称的动态库与静态库
|
||||
# 注意此处不必为目标名称添加lib前缀和相应后缀,cmake会自行添加
|
||||
add_library(magtess SHARED ${LIBMAGTESS_SRC})
|
||||
# 首先添加静态库的生成命令
|
||||
add_library(magtess_static STATIC ${LIBMAGTESS_SRC})
|
||||
# 设置静态库的输出名称从而获得与动态库名称相同的静态库
|
||||
set_target_properties(magtess_static PROPERTIES OUTPUT_NAME "magtess")
|
||||
# 设置输出目标属性以同时输出动态库与静态库
|
||||
set_target_properties(magtess PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
set_target_properties(magtess_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
# 设置动态库的版本号
|
||||
set_target_properties(magtess PROPERTIES VERSION 1.0 SOVERSION 1.0)
|
||||
|
||||
# 库的安装命令
|
||||
if(WIN32)
|
||||
install(TARGETS magtess DESTINATION lib)
|
||||
install(TARGETS magtess_static DESTINATION lib)
|
||||
else()
|
||||
install(TARGETS magtess magtess_static
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
endif()
|
||||
|
||||
# 头文件安装命令
|
||||
file(GLOB LIBMEGTESS_HEAD *.h)
|
||||
|
||||
install(FILES ${LIBMEGTESS_HEAD} DESTINATION include/magtess)
|
60
lib/constants.h
Executable file
60
lib/constants.h
Executable file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Define constants used, like the gravitational constant and unit conversions.
|
||||
|
||||
Values are assigned in file constants.c
|
||||
|
||||
All values are in SI units!
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_CONSTANTS_H_
|
||||
#define _TESSEROIDS_CONSTANTS_H_
|
||||
|
||||
/* Mean Earth radius [\f$ m \f$] */
|
||||
const double MEAN_EARTH_RADIUS = 6378137.0;
|
||||
const double EARTH_RADIUS_IGRF_KM = 6371.2;
|
||||
|
||||
/* The gravitational constant [\f$ m^3*kg^{-1}*s^{-1} \f$] */
|
||||
const double G = 0.00000000006673;
|
||||
|
||||
|
||||
|
||||
/* Conversion factor from SI units to Eotvos
|
||||
[\f$ \frac{1}{s^2} = 10^9\ Eotvos \f$] */
|
||||
const double SI2EOTVOS = 1000000000.0;
|
||||
const double EOTVOS2SI = 0.000000001;
|
||||
|
||||
/* Conversion factor from SI units to mGal
|
||||
[\f$ 1 \frac{m}{s^2} = 10^5\ mGal \f$] */
|
||||
const double SI2MGAL = 100000.0;
|
||||
|
||||
/* Pi */
|
||||
#ifdef __cplusplus
|
||||
const double PI = 3.1415926535897932384626433832795;
|
||||
#else
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
|
||||
/* minimum distance-to-size ratio for potential computations to be accurate */
|
||||
const double TESSEROID_POT_SIZE_RATIO = 1.5;
|
||||
/* Minimum distance-to-size ratio for gravity computations to be accurate */
|
||||
const double TESSEROID_GX_SIZE_RATIO = 3;
|
||||
const double TESSEROID_GY_SIZE_RATIO = 3;
|
||||
const double TESSEROID_GZ_SIZE_RATIO = 2;
|
||||
/* Minimum distance-to-size ratio for gravity gradient computations to be
|
||||
accurate */
|
||||
const double TESSEROID_GXX_SIZE_RATIO = 3;
|
||||
const double TESSEROID_GXY_SIZE_RATIO = 4.5;
|
||||
const double TESSEROID_GXZ_SIZE_RATIO = 4;
|
||||
const double TESSEROID_GYY_SIZE_RATIO = 3;
|
||||
const double TESSEROID_GYZ_SIZE_RATIO = 4;
|
||||
const double TESSEROID_GZZ_SIZE_RATIO = 3;
|
||||
|
||||
const double M_0 = 4 * (PI) * 0.0000001;
|
||||
|
||||
const double DEG2RAD = (PI)/180.0;
|
||||
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#endif
|
48
lib/geometry.cpp
Executable file
48
lib/geometry.cpp
Executable file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Data structures for geometric elements and functions that operate on them.
|
||||
Defines the TESSEROID, SPHERE, and PRISM structures.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "constants.h"
|
||||
#include "logger.h"
|
||||
#include "geometry.h"
|
||||
|
||||
|
||||
/* Split a tesseroid into 8. */
|
||||
void split_tess(TESSEROID tess, TESSEROID *split)
|
||||
{
|
||||
double dlon = 0.5*(tess.e - tess.w),
|
||||
dlat = 0.5*(tess.n - tess.s),
|
||||
dr = 0.5*(tess.r2 - tess.r1),
|
||||
ws[2], ss[2], r1s[2];
|
||||
int i, j, k, t = 0;
|
||||
|
||||
ws[0] = tess.w;
|
||||
ws[1] = tess.w + dlon;
|
||||
ss[0] = tess.s;
|
||||
ss[1] = tess.s + dlat;
|
||||
r1s[0] = tess.r1;
|
||||
r1s[1] = tess.r1 + dr;
|
||||
for(k = 0; k < 2; k++)
|
||||
{
|
||||
for(j = 0; j < 2; j++)
|
||||
{
|
||||
for(i = 0; i < 2; i++)
|
||||
{
|
||||
split[t].w = ws[i];
|
||||
split[t].e = ws[i] + dlon;
|
||||
split[t].s = ss[j];
|
||||
split[t].n = ss[j] + dlat;
|
||||
split[t].r1 = r1s[k];
|
||||
split[t].r2 = r1s[k] + dr;
|
||||
split[t].density = tess.density;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
lib/geometry.h
Executable file
37
lib/geometry.h
Executable file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Data structures for geometric elements and functions that operate on them.
|
||||
Defines the TESSEROID, SPHERE, and PRISM structures.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_GEOMETRY_H_
|
||||
#define _TESSEROIDS_GEOMETRY_H_
|
||||
|
||||
|
||||
/* Store information on a tesseroid */
|
||||
typedef struct tess_struct {
|
||||
/* s, n, w, e in degrees. r1 and r2 are the smaller and larger radius */
|
||||
double density; /* in SI units */
|
||||
double w; /* western longitude border in degrees */
|
||||
double e; /* eastern longitude border in degrees */
|
||||
double s; /* southern latitude border in degrees */
|
||||
double n; /* northern latitude border in degrees */
|
||||
double r1; /* smallest radius border in SI units */
|
||||
double r2; /* largest radius border in SI units */
|
||||
double suscept; /* magnetic susceptibility */
|
||||
double Bx; /* x-component of ambient magnetic field */
|
||||
double By; /* y-component of ambient magnetic field */
|
||||
double Bz; /* z-component of ambient magnetic field */
|
||||
|
||||
double cos_a1;
|
||||
double sin_a1;
|
||||
double cos_b1;
|
||||
double sin_b1;
|
||||
//double Rx;
|
||||
//double Ry;
|
||||
//double Rz;
|
||||
} TESSEROID;
|
||||
|
||||
|
||||
void split_tess(TESSEROID tess, TESSEROID *split);
|
||||
|
||||
#endif
|
265
lib/glq.cpp
Executable file
265
lib/glq.cpp
Executable file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
Functions for implementing a Gauss-Legendre Quadrature numerical integration.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "constants.h"
|
||||
#include "logger.h"
|
||||
#include "glq.h"
|
||||
|
||||
|
||||
/* Make a new GLQ structure and set all the parameters needed */
|
||||
GLQ * glq_new(int order, double lower, double upper)
|
||||
{
|
||||
GLQ *glq;
|
||||
int rc;
|
||||
|
||||
glq = (GLQ *)malloc(sizeof(GLQ));
|
||||
if(glq == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
glq->order = order;
|
||||
glq->nodes = (double *)malloc(sizeof(double)*order);
|
||||
if(glq->nodes == NULL)
|
||||
{
|
||||
free(glq);
|
||||
return NULL;
|
||||
}
|
||||
glq->nodes_unscaled = (double *)malloc(sizeof(double)*order);
|
||||
if(glq->nodes_unscaled == NULL)
|
||||
{
|
||||
free(glq);
|
||||
free(glq->nodes);
|
||||
return NULL;
|
||||
}
|
||||
glq->weights = (double *)malloc(sizeof(double)*order);
|
||||
if(glq->weights == NULL)
|
||||
{
|
||||
free(glq);
|
||||
free(glq->nodes);
|
||||
free(glq->nodes_unscaled);
|
||||
return NULL;
|
||||
}
|
||||
rc = glq_nodes(order, glq->nodes_unscaled);
|
||||
if(rc != 0 && rc != 3)
|
||||
{
|
||||
switch(rc)
|
||||
{
|
||||
case 1:
|
||||
log_error("glq_nodes invalid GLQ order %d. Should be >= 2.",
|
||||
order);
|
||||
break;
|
||||
case 2:
|
||||
log_error("glq_nodes NULL pointer for nodes");
|
||||
break;
|
||||
default:
|
||||
log_error("glq_nodes unknown error code %g", rc);
|
||||
break;
|
||||
}
|
||||
glq_free(glq);
|
||||
return NULL;
|
||||
}
|
||||
else if(rc == 3)
|
||||
{
|
||||
log_warning("glq_nodes max iterations reached in root finder");
|
||||
log_warning("nodes might not have desired accuracy %g", GLQ_MAXERROR);
|
||||
}
|
||||
rc = glq_weights(order, glq->nodes_unscaled, glq->weights);
|
||||
if(rc != 0)
|
||||
{
|
||||
switch(rc)
|
||||
{
|
||||
case 1:
|
||||
log_error("glq_weights invalid GLQ order %d. Should be >= 2.",
|
||||
order);
|
||||
break;
|
||||
case 2:
|
||||
log_error("glq_weights NULL pointer for nodes");
|
||||
break;
|
||||
case 3:
|
||||
log_error("glq_weights NULL pointer for weights");
|
||||
break;
|
||||
default:
|
||||
log_error("glq_weights unknown error code %d\n", rc);
|
||||
break;
|
||||
}
|
||||
glq_free(glq);
|
||||
return NULL;
|
||||
}
|
||||
if(glq_set_limits(lower, upper, glq) != 0)
|
||||
{
|
||||
glq_free(glq);
|
||||
return NULL;
|
||||
}
|
||||
return glq;
|
||||
}
|
||||
|
||||
|
||||
/* Free the memory allocated to make a GLQ structure */
|
||||
void glq_free(GLQ *glq)
|
||||
{
|
||||
free(glq->nodes);
|
||||
|
||||
free(glq->nodes_unscaled);
|
||||
free(glq->weights);
|
||||
free(glq);
|
||||
}
|
||||
|
||||
|
||||
/* Calculates the GLQ nodes using glq_next_root. */
|
||||
int glq_nodes(int order, double *nodes)
|
||||
{
|
||||
register int i;
|
||||
int rc = 0;
|
||||
double initial;
|
||||
|
||||
if(order < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(nodes == NULL)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
for(i = 0; i < order; i++)
|
||||
{
|
||||
initial = cos(PI*(order - i - 0.25)/(order + 0.5));
|
||||
if(glq_next_root(initial, i, order, nodes) == 3)
|
||||
{
|
||||
rc = 3;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Put the GLQ nodes to the integration limits IN PLACE. */
|
||||
int glq_set_limits(double lower, double upper, GLQ *glq)
|
||||
{
|
||||
/* Only calculate once to optimize the code */
|
||||
double tmpplus = 0.5*(upper + lower), tmpminus = 0.5*(upper - lower);
|
||||
register int i;
|
||||
|
||||
if(glq->order < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(glq->nodes == NULL)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if(glq->nodes_unscaled == NULL)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
for(i = 0; i < glq->order; i++)
|
||||
{
|
||||
glq->nodes[i] = tmpminus*glq->nodes_unscaled[i] + tmpplus;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the next Legendre polynomial root given the previous root found. */
|
||||
int glq_next_root(double initial, int root_index, int order, double *roots)
|
||||
{
|
||||
double x1, x0, pn, pn_2, pn_1, pn_line, sum;
|
||||
int it = 0;
|
||||
register int n;
|
||||
|
||||
if(order < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(root_index < 0 || root_index >= order)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
x1 = initial;
|
||||
do
|
||||
{
|
||||
x0 = x1;
|
||||
|
||||
/* Calculate Pn(x0) */
|
||||
/* Starting from P0(x) and P1(x), */
|
||||
/* find the others using the recursive relation: */
|
||||
/* Pn(x)=(2n-1)xPn_1(x)/n - (n-1)Pn_2(x)/n */
|
||||
pn_1 = 1.; /* This is Po(x) */
|
||||
pn = x0; /* and this P1(x) */
|
||||
for(n = 2; n <= order; n++)
|
||||
{
|
||||
pn_2 = pn_1;
|
||||
pn_1 = pn;
|
||||
pn = ( ((2*n - 1)*x0*pn_1) - ((n - 1)*pn_2) )/n;
|
||||
}
|
||||
/* Now calculate Pn'(x0) using another recursive relation: */
|
||||
/* Pn'(x)=n(xPn(x)-Pn_1(x))/(x*x-1) */
|
||||
pn_line = order*(x0*pn - pn_1)/(x0*x0 - 1);
|
||||
/* Sum the roots found so far */
|
||||
for(n = 0, sum = 0; n < root_index; n++)
|
||||
{
|
||||
sum += 1./(x0 - roots[n]);
|
||||
}
|
||||
/* Update the estimate for the root */
|
||||
x1 = x0 - (double)pn/(pn_line - pn*sum);
|
||||
|
||||
/** Compute the absolute value of x */
|
||||
#define GLQ_ABS(x) ((x) < 0 ? -1*(x) : (x))
|
||||
} while(GLQ_ABS(x1 - x0) > GLQ_MAXERROR && ++it <= GLQ_MAXIT);
|
||||
#undef GLQ_ABS
|
||||
|
||||
roots[root_index] = x1;
|
||||
|
||||
/* Tell the user if stagnation occurred */
|
||||
if(it > GLQ_MAXIT)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates the weighting coefficients for the GLQ integration. */
|
||||
int glq_weights(int order, double *nodes, double *weights)
|
||||
{
|
||||
register int i, n;
|
||||
double xi, pn, pn_2, pn_1, pn_line;
|
||||
|
||||
if(order < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(nodes == NULL)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if(weights == NULL)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
for(i = 0; i < order; i++){
|
||||
|
||||
xi = nodes[i];
|
||||
|
||||
/* Find Pn'(xi) with the recursive relation to find Pn and Pn-1: */
|
||||
/* Pn(x)=(2n-1)xPn_1(x)/n - (n-1)Pn_2(x)/n */
|
||||
/* Then use: Pn'(x)=n(xPn(x)-Pn_1(x))/(x*x-1) */
|
||||
|
||||
/* Find Pn and Pn-1 stating from P0 and P1 */
|
||||
pn_1 = 1; /* This is Po(x) */
|
||||
pn = xi; /* and this P1(x) */
|
||||
for(n = 2; n <= order; n++)
|
||||
{
|
||||
pn_2 = pn_1;
|
||||
pn_1 = pn;
|
||||
pn = ((2*n - 1)*xi*pn_1 - (n - 1)*pn_2)/n;
|
||||
}
|
||||
pn_line = order*(xi*pn - pn_1)/(xi*xi - 1.);
|
||||
/* ith weight is: wi = 2/(1 - xi^2)(Pn'(xi)^2) */
|
||||
weights[i] = 2./((1 - xi*xi)*pn_line*pn_line);
|
||||
}
|
||||
return 0;
|
||||
}
|
182
lib/glq.h
Executable file
182
lib/glq.h
Executable file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
Functions for implementing a Gauss-Legendre Quadrature numerical integration
|
||||
(Hildebrand, 1987).
|
||||
|
||||
Usage example
|
||||
-------------
|
||||
|
||||
To integrate the cossine function from 0 to 90 degrees:
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "src/c/glq.h"
|
||||
|
||||
int main(){
|
||||
// Create a new glq structure
|
||||
GLQ *glq;
|
||||
double result = 0, a = 0, b = 0.5*3.14;
|
||||
int i;
|
||||
|
||||
glq = glq_new(5, a, b);
|
||||
|
||||
if(glq == NULL){
|
||||
printf("malloc error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Calculate the integral
|
||||
for(i = 0; i < glq->order; i++)
|
||||
result += glq->weights[i]*cos(glq->nodes[i]);
|
||||
|
||||
// Need to multiply by a scale factor of the integration limits
|
||||
result *= 0.5*(b - a);
|
||||
|
||||
printf("Integral of cossine from 0 to 90 degrees = %lf\n", result);
|
||||
|
||||
// Free allocated memory
|
||||
glq_free(glq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
* Hildebrand, F.B (1987): Introduction to numerical analysis.
|
||||
Courier Dover Publications, 2. ed.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_GLQ_H_
|
||||
#define _TESSEROIDS_GLQ_H_
|
||||
|
||||
|
||||
/** \var GLQ_MAXIT
|
||||
Max iterations of the root-finder algorithm */
|
||||
const int GLQ_MAXIT = 1000;
|
||||
|
||||
|
||||
/** \var GLQ_MAXERROR
|
||||
Max error allowed for the root-finder algorithm */
|
||||
const double GLQ_MAXERROR = 0.000000000000001;
|
||||
|
||||
|
||||
/** Store the nodes and weights needed for a GLQ integration */
|
||||
typedef struct glq_struct
|
||||
{
|
||||
int order; /**< order of the quadrature, ie number of nodes */
|
||||
double *nodes; /**< abscissas or discretization points of the quadrature */
|
||||
double *weights; /**< weighting coefficients of the quadrature */
|
||||
double *nodes_unscaled; /**< nodes in [-1,1] interval */
|
||||
} GLQ;
|
||||
|
||||
|
||||
/** Make a new GLQ structure and set all the parameters needed
|
||||
|
||||
<b>WARNING</b>: Don't forget to free the memory malloced by this function using
|
||||
glq_free()!
|
||||
|
||||
Prints error and warning messages using the logging.h module.
|
||||
|
||||
@param order order of the quadrature, ie number of nodes
|
||||
@param lower lower integration limit
|
||||
@param upper upper integration limit
|
||||
|
||||
@return GLQ data structure with the nodes and weights calculated. NULL if there
|
||||
was an error with allocation.
|
||||
*/
|
||||
GLQ * glq_new(int order, double lower, double upper);
|
||||
|
||||
|
||||
/** Free the memory allocated to make a GLQ structure
|
||||
|
||||
@param glq pointer to the allocated memory
|
||||
*/
|
||||
void glq_free(GLQ *glq);
|
||||
|
||||
|
||||
/** Put the GLQ nodes to the integration limits <b>IN PLACE</b>.
|
||||
|
||||
Will replace the values of glq.nodes with ones in the specified integration
|
||||
limits.
|
||||
|
||||
In case the GLQ structure was created with glq_new(), the integration limits can
|
||||
be reset using this function.
|
||||
|
||||
@param lower lower integration limit
|
||||
@param upper upper integration limit
|
||||
@param glq pointer to a GLQ structure created with glq_new() and with all
|
||||
necessary memory allocated
|
||||
|
||||
@return Return code:
|
||||
- 0: if everything went OK
|
||||
- 1: if invalid order
|
||||
- 2: if NULL pointer for nodes or nodes_unscaled
|
||||
*/
|
||||
int glq_set_limits(double lower, double upper, GLQ *glq);
|
||||
/** Calculates the GLQ nodes using glq_next_root.
|
||||
|
||||
Nodes will be in the [-1,1] interval. To convert them to the integration limits
|
||||
use glq_scale_nodes
|
||||
|
||||
@param order order of the quadrature, ie how many nodes. Must be >= 2.
|
||||
@param nodes pre-allocated array to return the nodes.
|
||||
|
||||
@return Return code:
|
||||
- 0: if everything went OK
|
||||
- 1: if invalid order
|
||||
- 2: if NULL pointer for nodes
|
||||
- 3: if number of maximum iterations was reached when calculating the root.
|
||||
This usually means that the desired accuracy was not achieved. Default
|
||||
desired accuracy is GLQ_MAXERROR. Default maximum iterations is
|
||||
GLQ_MAXIT.
|
||||
*/
|
||||
int glq_nodes(int order, double *nodes);
|
||||
|
||||
|
||||
/** Calculate the next Legendre polynomial root given the previous root found.
|
||||
|
||||
Uses the root-finder algorithm of:
|
||||
|
||||
Barrera-Figueroa, V., Sosa-Pedroza, J. and López-Bonilla, J., 2006,
|
||||
"Multiple root finder algorithm for Legendre and Chebyshev polynomials via
|
||||
Newton's method", 2006, Annales mathematicae et Informaticae, 33, pp 3-13
|
||||
|
||||
@param initial initial estimate of the next root. I recommend the use of
|
||||
\f$ \cos\left(\pi\frac{(N - i - 0.25)}{N + 0.5}\right) \f$,
|
||||
where \f$ i \f$ is the index of the desired root
|
||||
@param root_index index of the desired root, starting from 0
|
||||
@param order order of the Legendre polynomial, ie number of roots.
|
||||
@param roots array with the roots found so far. Will return the next root in
|
||||
roots[root_index], so make sure to malloc enough space.
|
||||
|
||||
@return Return code:
|
||||
- 0: if everything went OK
|
||||
- 1: if order is not valid
|
||||
- 2: if root_index is not valid (negative)
|
||||
- 3: if number of maximum iterations was reached when calculating the root.
|
||||
This usually means that the desired accuracy was not achieved. Default
|
||||
desired accuracy is GLQ_MAXERROR. Default maximum iterations is
|
||||
GLQ_MAXIT.
|
||||
*/
|
||||
int glq_next_root(double initial, int root_index, int order,
|
||||
double *roots);
|
||||
|
||||
|
||||
/** Calculates the weighting coefficients for the GLQ integration.
|
||||
|
||||
@param order order of the quadrature, ie number of nodes and weights.
|
||||
@param nodes array containing the GLQ nodes calculated by glq_nodes.
|
||||
<b>IMPORTANT</b>: needs the nodes in [-1,1] interval! Scaled nodes
|
||||
will result in wrong weights!
|
||||
@param weights pre-allocated array to return the weights
|
||||
|
||||
@return Return code:
|
||||
- 0: if everything went OK
|
||||
- 1: if order is not valid
|
||||
- 2: if nodes is a NULL pointer
|
||||
- 3: if weights is a NULL pointer
|
||||
*/
|
||||
int glq_weights(int order, double *nodes, double *weights);
|
||||
|
||||
#endif
|
628
lib/grav_tess.cpp
Executable file
628
lib/grav_tess.cpp
Executable file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
Functions that calculate the gravitational potential and its first and second
|
||||
derivatives for the tesseroid.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
* Grombein, T.; Seitz, K.; Heck, B. (2010): Untersuchungen zur effizienten
|
||||
Berechnung topographischer Effekte auf den Gradiententensor am Fallbeispiel der
|
||||
Satellitengradiometriemission GOCE.
|
||||
KIT Scientific Reports 7547, ISBN 978-3-86644-510-9, KIT Scientific Publishing,
|
||||
Karlsruhe, Germany.
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include "logger.h"
|
||||
#include "geometry.h"
|
||||
#include "glq.h"
|
||||
#include "constants.h"
|
||||
#include "grav_tess.h"
|
||||
|
||||
|
||||
/* Calculates the field of a tesseroid model at a given point. */
|
||||
double calc_tess_model(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ))
|
||||
{
|
||||
double res;
|
||||
int tess;
|
||||
|
||||
res = 0;
|
||||
for(tess = 0; tess < size; tess++)
|
||||
{
|
||||
if(lonp >= model[tess].w && lonp <= model[tess].e &&
|
||||
latp >= model[tess].s && latp <= model[tess].n &&
|
||||
rp >= model[tess].r1 && rp <= model[tess].r2)
|
||||
{
|
||||
log_warning("Point (%g %g %g) is on tesseroid %d: %g %g %g %g %g %g %g. Can't guarantee accuracy.",
|
||||
lonp, latp, rp - MEAN_EARTH_RADIUS, tess,
|
||||
model[tess].w, model[tess].e, model[tess].s,
|
||||
model[tess].n, model[tess].r2 - MEAN_EARTH_RADIUS,
|
||||
model[tess].r1 - MEAN_EARTH_RADIUS,
|
||||
model[tess].density);
|
||||
}
|
||||
glq_set_limits(model[tess].w, model[tess].e, glq_lon);
|
||||
glq_set_limits(model[tess].s, model[tess].n, glq_lat);
|
||||
glq_set_limits(model[tess].r1, model[tess].r2, glq_r);
|
||||
res += field(model[tess], lonp, latp, rp, *glq_lon, *glq_lat, *glq_r);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void calc_tess_model_triple(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, void (*field_triple)(TESSEROID, double, double, double, GLQ, GLQ, GLQ, double*), double *res)
|
||||
{
|
||||
double r1, r2, r3, ri[3];
|
||||
int tess;
|
||||
|
||||
res[0] = 0;
|
||||
res[1] = 0;
|
||||
res[2] = 0;
|
||||
for(tess = 0; tess < size; tess++)
|
||||
{
|
||||
ri[0] = 0;
|
||||
ri[1] = 0;
|
||||
ri[2] = 0;
|
||||
|
||||
if(lonp >= model[tess].w && lonp <= model[tess].e &&
|
||||
latp >= model[tess].s && latp <= model[tess].n &&
|
||||
rp >= model[tess].r1 && rp <= model[tess].r2)
|
||||
{
|
||||
log_warning("Point (%g %g %g) is on tesseroid %d: %g %g %g %g %g %g %g. Can't guarantee accuracy.",
|
||||
lonp, latp, rp - MEAN_EARTH_RADIUS, tess,
|
||||
model[tess].w, model[tess].e, model[tess].s,
|
||||
model[tess].n, model[tess].r2 - MEAN_EARTH_RADIUS,
|
||||
model[tess].r1 - MEAN_EARTH_RADIUS,
|
||||
model[tess].density);
|
||||
}
|
||||
glq_set_limits(model[tess].w, model[tess].e, glq_lon);
|
||||
glq_set_limits(model[tess].s, model[tess].n, glq_lat);
|
||||
glq_set_limits(model[tess].r1, model[tess].r2, glq_r);
|
||||
field_triple(model[tess], lonp, latp, rp, *glq_lon, *glq_lat, *glq_r, ri);
|
||||
|
||||
res[0] += ri[0];
|
||||
res[1] += ri[1];
|
||||
res[2] += ri[2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Adaptatively calculate the field of a tesseroid model at a given point */
|
||||
double calc_tess_model_adapt(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ), double ratio)
|
||||
{
|
||||
double res, dist, lont, latt, rt, d2r = PI/180.;
|
||||
int tess;
|
||||
TESSEROID split[8];
|
||||
|
||||
res = 0;
|
||||
for(tess = 0; tess < size; tess++)
|
||||
{
|
||||
rt = model[tess].r2;
|
||||
lont = 0.5*(model[tess].w + model[tess].e);
|
||||
latt = 0.5*(model[tess].s + model[tess].n);
|
||||
dist = sqrt(rp*rp + rt*rt - 2*rp*rt*(sin(d2r*latp)*sin(d2r*latt) +
|
||||
cos(d2r*latp)*cos(d2r*latt)*cos(d2r*(lonp - lont))));
|
||||
|
||||
/* Would get stuck in infinite loop if dist = 0 and get wrong results if
|
||||
inside de tesseroid. Still do the calculation but warn user that it's
|
||||
probably wrong. */
|
||||
if(lonp >= model[tess].w && lonp <= model[tess].e &&
|
||||
latp >= model[tess].s && latp <= model[tess].n &&
|
||||
rp >= model[tess].r1 && rp <= model[tess].r2)
|
||||
{
|
||||
log_warning("Point (%g %g %g) is on top of tesseroid %d: %g %g %g %g %g %g %g. Can't guarantee accuracy.",
|
||||
lonp, latp, rp - MEAN_EARTH_RADIUS, tess,
|
||||
model[tess].w, model[tess].e, model[tess].s,
|
||||
model[tess].n, model[tess].r2 - MEAN_EARTH_RADIUS,
|
||||
model[tess].r1 - MEAN_EARTH_RADIUS,
|
||||
model[tess].density);
|
||||
glq_set_limits(model[tess].w, model[tess].e, glq_lon);
|
||||
glq_set_limits(model[tess].s, model[tess].n, glq_lat);
|
||||
glq_set_limits(model[tess].r1, model[tess].r2, glq_r);
|
||||
res += field(model[tess], lonp, latp, rp, *glq_lon, *glq_lat,
|
||||
*glq_r);
|
||||
}
|
||||
/* Check if the computation point is at an acceptable distance. If not
|
||||
split the tesseroid using the given ratio */
|
||||
else if(
|
||||
dist < ratio*MEAN_EARTH_RADIUS*d2r*(model[tess].e - model[tess].w) ||
|
||||
dist < ratio*MEAN_EARTH_RADIUS*d2r*(model[tess].n - model[tess].s) ||
|
||||
dist < ratio*(model[tess].r2 - model[tess].r1))
|
||||
{
|
||||
log_debug("Splitting tesseroid %d (%g %g %g %g %g %g %g) at point (%g %g %g) using ratio %g",
|
||||
tess, model[tess].w, model[tess].e, model[tess].s,
|
||||
model[tess].n, model[tess].r2 - MEAN_EARTH_RADIUS,
|
||||
model[tess].r1 - MEAN_EARTH_RADIUS, model[tess].density,
|
||||
lonp, latp, rp - MEAN_EARTH_RADIUS, ratio);
|
||||
/* Do it recursively until ratio*size is smaller than distance */
|
||||
split_tess(model[tess], split);
|
||||
res += calc_tess_model_adapt(split, 8, lonp, latp, rp, glq_lon,
|
||||
glq_lat, glq_r, field, ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
glq_set_limits(model[tess].w, model[tess].e, glq_lon);
|
||||
glq_set_limits(model[tess].s, model[tess].n, glq_lat);
|
||||
glq_set_limits(model[tess].r1, model[tess].r2, glq_r);
|
||||
res += field(model[tess], lonp, latp, rp, *glq_lon, *glq_lat,
|
||||
*glq_r);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Calculates gxx caused by a tesseroid. */
|
||||
double tess_gxx(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, kphi, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, rc, kappa, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*(sinlatp*sinlatc +
|
||||
coslatp*coslatc*coslon);
|
||||
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*rc*kphi*rc*kphi - l_sqr)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gxy caused by a tesseroid. */
|
||||
double tess_gxy(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, kphi, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, sinlon, rc, kappa, deltax, deltay, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*(sinlatp*sinlatc +
|
||||
coslatp*coslatc*coslon);
|
||||
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltax = rc*kphi;
|
||||
|
||||
deltay = rc*coslatc*sinlon;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltay)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gxz caused by a tesseroid. */
|
||||
double tess_gxz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, kphi, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, cospsi, rc, kappa, deltax, deltaz, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltax = rc*kphi;
|
||||
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltaz)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gyy caused by a tesseroid. */
|
||||
double tess_gyy(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, sinlon, rc, kappa, deltay, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*(sinlatp*sinlatc +
|
||||
coslatp*coslatc*coslon);
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltay = rc*coslatc*sinlon;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltay*deltay - l_sqr)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gyz caused by a tesseroid. */
|
||||
double tess_gyz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, sinlon, cospsi, rc, kappa, deltay, deltaz, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltay = rc*coslatc*sinlon;
|
||||
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltay*deltaz)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gzz caused by a tesseroid. */
|
||||
double tess_gzz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc,
|
||||
coslon, cospsi, rc, kappa, deltaz, res;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltaz*deltaz - l_sqr)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*Calculate three gravity gradient components simultaneously*/
|
||||
void tess_gxz_gyz_gzz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r, double *res)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc, sinlon,
|
||||
coslon, cospsi, rc, kappa, deltaz, deltax, deltay, kphi,
|
||||
res_gxz, res_gyz, res_gzz;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res_gxz = 0;
|
||||
res_gyz = 0;
|
||||
res_gzz = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltax = rc*kphi;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res_gxz += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltaz)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gyz += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltay*deltaz)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gzz += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltaz*deltaz - l_sqr)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res_gxz *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gyz *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gzz *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res[0] = res_gxz;
|
||||
res[1] = res_gyz;
|
||||
res[2] = res_gzz;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void tess_gxx_gxy_gxz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r, double *res)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc, sinlon,
|
||||
coslon, cospsi, rc, kappa, deltaz, deltax, deltay, kphi,
|
||||
res_gxx, res_gxy, res_gxz;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res_gxx = 0;
|
||||
res_gxy = 0;
|
||||
res_gxz = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltax = rc*kphi;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res_gxx += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*rc*kphi*rc*kphi - l_sqr)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gxy += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltay)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gxz += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltaz)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res_gxx *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gxy *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gxz *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res[0] = res_gxx;
|
||||
res[1] = res_gxy;
|
||||
res[2] = res_gxz;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tess_gxy_gyy_gyz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon,
|
||||
GLQ glq_lat, GLQ glq_r, double *res)
|
||||
{
|
||||
double d2r = PI/180., l_sqr, coslatp, coslatc, sinlatp, sinlatc, sinlon,
|
||||
coslon, cospsi, rc, kappa, deltaz, deltax, deltay, kphi,
|
||||
res_gxy, res_gyy, res_gyz;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res_gxy = 0;
|
||||
res_gyy = 0;
|
||||
res_gyz = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
rc = glq_r.nodes[i];
|
||||
sinlatc = sin(d2r*glq_lat.nodes[j]);
|
||||
coslatc = cos(d2r*glq_lat.nodes[j]);
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
kappa = rc*rc*coslatc;
|
||||
|
||||
deltax = rc*kphi;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
deltaz = rc*cospsi - rp;
|
||||
|
||||
res_gxy += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltax*deltay)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gyy += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltay*deltay - l_sqr)/pow(l_sqr, 2.5);
|
||||
|
||||
res_gyz += glq_lon.weights[k]*glq_lat.weights[j]*glq_r.weights[i]*
|
||||
kappa*(3*deltay*deltaz)/pow(l_sqr, 2.5);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res_gxy *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gyy *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res_gyz *= SI2EOTVOS*G*tess.density*d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*
|
||||
(tess.r2 - tess.r1)*0.125;
|
||||
|
||||
res[0] = res_gxy;
|
||||
res[1] = res_gyy;
|
||||
res[2] = res_gyz;
|
||||
|
||||
return;
|
||||
}
|
93
lib/grav_tess.h
Executable file
93
lib/grav_tess.h
Executable file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Functions that calculate the gravitational potential and its first and second
|
||||
derivatives for the tesseroid.
|
||||
|
||||
The gravity gradients can be calculated using the general formula of
|
||||
Grombein et al. (2010).
|
||||
The integrals are solved using the Gauss-Legendre Quadrature rule
|
||||
(Asgharzadeh et al., 2007).
|
||||
|
||||
The derivatives of the potential are made with respect to the local coordinate
|
||||
system x->North, y->East, z->Up (away from center of the Earth).
|
||||
|
||||
To maintain the standard convention, only for component gz the z axis is
|
||||
inverted, so a positive density results in positive gz.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
To calculate the gzz component due to a tesseroid on a regular grid:
|
||||
|
||||
#include <stdio.h>
|
||||
#include "glq.h"r
|
||||
#include "constants.h"
|
||||
#include "grav_tess.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
TESSEROID tess = {1000, 44, 46, -1, 1, MEAN_EARTH_RADIUS - 100000,
|
||||
MEAN_EARTH_RADIUS};
|
||||
GLQ *glqlon, *glqlat, *glqr;
|
||||
double lon, lat, r = MEAN_EARTH_RADIUS + 1500000, res;
|
||||
int order = 8;
|
||||
|
||||
glqlon = glq_new(order, tess.w, tess.e);
|
||||
glqlat = glq_new(order, tess.s, tess.n);
|
||||
glqr = glq_new(order, tess.r1, tess.r2);
|
||||
|
||||
for(lat = 20; lat <= 70; lat += 0.5)
|
||||
{
|
||||
for(lon = -25; lon <= 25; lon += 0.5)
|
||||
{
|
||||
res = tess_gzz(tess, lon, lat, r, *glqlon, *glqlat, *glqr);
|
||||
printf("%g %g %g\n", lon, lat, res);
|
||||
}
|
||||
}
|
||||
|
||||
glq_free(glqlon);
|
||||
glq_free(glqlat);
|
||||
glq_free(glqr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
Asgharzadeh, M.F., von Frese, R.R.B., Kim, H.R., Leftwich, T.E. & Kim, J.W.
|
||||
(2007): Spherical prism gravity effects by Gauss-Legendre quadrature integration.
|
||||
Geophysical Journal International, 169, 1-11.
|
||||
|
||||
Grombein, T.; Seitz, K.; Heck, B. (2010): Untersuchungen zur effizienten
|
||||
Berechnung topographischer Effekte auf den Gradiententensor am Fallbeispiel der
|
||||
Satellitengradiometriemission GOCE.
|
||||
KIT Scientific Reports 7547, ISBN 978-3-86644-510-9, KIT Scientific Publishing,
|
||||
Karlsruhe, Germany.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_GRAV_TESS_H_
|
||||
#define _TESSEROIDS_GRAV_TESS_H_
|
||||
|
||||
|
||||
/* Needed for definition of TESSEROID */
|
||||
#include "geometry.h"
|
||||
/* Needed for definition of GLQ */
|
||||
#include "glq.h"
|
||||
|
||||
double calc_tess_model(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ));
|
||||
void calc_tess_model_triple(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r,
|
||||
void (*field_triple)(TESSEROID, double, double, double, GLQ, GLQ, GLQ, double*), double *res);
|
||||
double calc_tess_model_adapt(TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ), double ratio);
|
||||
|
||||
double tess_gxx(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
double tess_gxy(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
double tess_gxz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
double tess_gyy(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
double tess_gyz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
double tess_gzz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r);
|
||||
|
||||
void tess_gxz_gyz_gzz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r, double *res);
|
||||
void tess_gxx_gxy_gxz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r, double *res);
|
||||
void tess_gxy_gyy_gyz(TESSEROID tess, double lonp, double latp, double rp, GLQ glq_lon, GLQ glq_lat, GLQ glq_r, double *res);
|
||||
|
||||
#endif
|
142
lib/linalg.cpp
Executable file
142
lib/linalg.cpp
Executable file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Functions matrix and vector multiplications.
|
||||
|
||||
*/
|
||||
|
||||
#include "linalg.h"
|
||||
#include "constants.h"
|
||||
#include <math.h>
|
||||
|
||||
//macOS only!
|
||||
//#include <Accelerate/Accelerate.h>
|
||||
|
||||
#ifdef __linux__ // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
|
||||
#include <cblas.h>
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <Accelerate/Accelerate.h>
|
||||
#else
|
||||
//
|
||||
#endif
|
||||
|
||||
/* Calculate magnetization vector in a coordinate system of a given point */
|
||||
void conv_vect_cblas(double *vect, double lon1, double lat1, double lon2, double lat2, double *res)
|
||||
{
|
||||
double a1 = DEG2RAD*lat1;
|
||||
double b1 = DEG2RAD*lon1;
|
||||
double a2 = DEG2RAD*lat2;
|
||||
double b2 = DEG2RAD*lon2;
|
||||
|
||||
double cos_a1 = cos(PI/2.0-a1);
|
||||
double sin_a1 = sin(PI/2.0-a1);
|
||||
double cos_a2 = cos(PI/2.0-a2);
|
||||
double sin_a2 = sin(PI/2.0-a2);
|
||||
|
||||
double cos_b1 = cos(b1);
|
||||
double sin_b1 = sin(b1);
|
||||
double cos_b2 = cos(b2);
|
||||
double sin_b2 = sin(b2);
|
||||
|
||||
double Z1Y1[9] = {cos_a1*cos_b1, -sin_b1, cos_b1*sin_a1, cos_a1*sin_b1, cos_b1, sin_a1*sin_b1, -sin_a1, 0, cos_a1};
|
||||
double Z2Y2t[9] = {-cos_a2*cos_b2, -cos_a2*sin_b2, sin_a2, -sin_b2, cos_b2, 0, cos_b2*sin_a2, sin_a2*sin_b2, cos_a2};
|
||||
double R[9];
|
||||
|
||||
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3, 1.0, Z1Y1, 3, Z2Y2t, 3, 0.0, R, 3);
|
||||
|
||||
R[0] = -R[0];
|
||||
R[3] = -R[3];
|
||||
R[6] = -R[6];
|
||||
|
||||
cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, R, 3, vect, 1, 0.0, res, 1);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void conv_vect_cblas_precalc(double *vect, double cos_a1, double sin_a1, double cos_b1, double sin_b1, double cos_a2, double sin_a2, double cos_b2, double sin_b2, double *res)
|
||||
{
|
||||
// double a1 = DEG2RAD*lat1;
|
||||
// double b1 = DEG2RAD*lon1;
|
||||
// double a2 = DEG2RAD*lat2;
|
||||
// double b2 = DEG2RAD*lon2;
|
||||
|
||||
// double cos_a1 = cos(PI/2.0-a1);
|
||||
// double sin_a1 = sin(PI/2.0-a1);
|
||||
// double cos_a2 = cos(PI/2.0-a2);
|
||||
// double sin_a2 = sin(PI/2.0-a2);
|
||||
|
||||
// double cos_b1 = cos(b1);
|
||||
// double sin_b1 = sin(b1);
|
||||
// double cos_b2 = cos(b2);
|
||||
// double sin_b2 = sin(b2);
|
||||
|
||||
double Z1Y1[9] = {cos_a1*cos_b1, -sin_b1, cos_b1*sin_a1, cos_a1*sin_b1, cos_b1, sin_a1*sin_b1, -sin_a1, 0, cos_a1};
|
||||
double Z2Y2t[9] = {-cos_a2*cos_b2, -cos_a2*sin_b2, sin_a2, -sin_b2, cos_b2, 0, cos_b2*sin_a2, sin_a2*sin_b2, cos_a2};
|
||||
double R[9];
|
||||
|
||||
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3, 1.0, Z1Y1, 3, Z2Y2t, 3, 0.0, R, 3);
|
||||
|
||||
R[0] = -R[0];
|
||||
R[3] = -R[3];
|
||||
R[6] = -R[6];
|
||||
|
||||
cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, R, 3, vect, 1, 0.0, res, 1);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void from_loc_sphr_to_cart(double* columnvect_xyzloc, double colatitude, double longitude, double* columnvect_res)
|
||||
{
|
||||
/*IMPORTANT: this subroutine is in the coordinate system NED*/
|
||||
|
||||
double phi = colatitude*DEG2RAD;
|
||||
double lambda = longitude*DEG2RAD;
|
||||
|
||||
double cos_phi = cos(phi);
|
||||
double sin_phi = sin(phi);
|
||||
double cos_lambda = cos(lambda);
|
||||
double sin_lambda = sin(lambda);
|
||||
|
||||
double columnvect_phi_unit[3] = {-sin_phi*cos_lambda, -sin_phi*sin_lambda, cos_phi};
|
||||
double columnvect_lambda_unit[3] = {-sin_lambda, cos_lambda, 0};
|
||||
double columnvect_r_unit[3] = {cos_phi*cos_lambda, cos_phi*sin_lambda, sin_phi};
|
||||
|
||||
columnvect_res[0] = columnvect_phi_unit[0]*columnvect_xyzloc[0]+columnvect_lambda_unit[0]*columnvect_xyzloc[1]+columnvect_r_unit[0]*columnvect_xyzloc[2];
|
||||
columnvect_res[1] = columnvect_phi_unit[1]*columnvect_xyzloc[0]+columnvect_lambda_unit[1]*columnvect_xyzloc[1]+columnvect_r_unit[1]*columnvect_xyzloc[2];
|
||||
columnvect_res[2] = columnvect_phi_unit[2]*columnvect_xyzloc[0]+columnvect_lambda_unit[2]*columnvect_xyzloc[1]+columnvect_r_unit[2]*columnvect_xyzloc[2];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void from_cart_to_loc_sphr(double* columnvect_xyzglob, double colatitude, double longitude, double* columnvect_res)
|
||||
{
|
||||
/*IMPORTANT: this subroutine is in the coordinate system NED*/
|
||||
|
||||
double phi = colatitude*DEG2RAD;
|
||||
double lambda = longitude*DEG2RAD;
|
||||
|
||||
double cos_phi = cos(phi);
|
||||
double sin_phi = sin(phi);
|
||||
double cos_lambda = cos(lambda);
|
||||
double sin_lambda = sin(lambda);
|
||||
|
||||
double rowvect_phi_unit[3] = {-sin_phi*cos_lambda, -sin_phi*sin_lambda, cos_phi};
|
||||
double rowvect_lambda_unit[3] = {-sin_lambda, cos_lambda, 0};
|
||||
double rowvect_r_unit[3] = {cos_phi*cos_lambda, cos_phi*sin_lambda, sin_phi};
|
||||
|
||||
columnvect_res[0] = rowvect_phi_unit[0]*columnvect_xyzglob[0]+rowvect_phi_unit[1]*columnvect_xyzglob[1]+rowvect_phi_unit[2]*columnvect_xyzglob[2];
|
||||
columnvect_res[1] = rowvect_lambda_unit[0]*columnvect_xyzglob[0]+rowvect_lambda_unit[1]*columnvect_xyzglob[1]+rowvect_lambda_unit[2]*columnvect_xyzglob[2];
|
||||
columnvect_res[2] = rowvect_r_unit[0]*columnvect_xyzglob[0]+rowvect_r_unit[1]*columnvect_xyzglob[1]+rowvect_r_unit[2]*columnvect_xyzglob[2];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void from_loc_sphr_to_loc_sphr(double* columnvect_xyzloc, double colatitude1, double longitude1, double colatitude2, double longitude2, double* columnvect_res)
|
||||
{
|
||||
double columnvect_xyzglob[3];
|
||||
from_loc_sphr_to_cart(columnvect_xyzloc, colatitude1, longitude1, columnvect_xyzglob);
|
||||
from_cart_to_loc_sphr(columnvect_xyzglob, colatitude2, longitude2, columnvect_res);
|
||||
return;
|
||||
|
||||
}
|
11
lib/linalg.h
Executable file
11
lib/linalg.h
Executable file
@@ -0,0 +1,11 @@
|
||||
#ifndef _LINALG_H_
|
||||
#define _LINALG_H_
|
||||
|
||||
void conv_vect_cblas(double *vect, double lon1, double lat1, double lon2, double lat2, double *res);
|
||||
void conv_vect_cblas_precalc(double *vect, double cos_a1, double sin_a1, double cos_b1, double sin_b1, double cos_a2, double sin_a2, double cos_b2, double sin_b2, double *res);
|
||||
|
||||
void from_loc_sphr_to_cart(double* columnvect_xyzloc, double colatitude, double longitude, double* columnvect_res);
|
||||
void from_cart_to_loc_sphr(double* columnvect_xyzglob, double colatitude, double longitude, double* columnvect_res);
|
||||
void from_loc_sphr_to_loc_sphr(double* columnvect_xyzloc, double colatitude1, double longitude1, double colatitude2, double longitude2, double* columnvect_res);
|
||||
|
||||
#endif
|
112
lib/logger.cpp
Executable file
112
lib/logger.cpp
Executable file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Functions to set up logging.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include "logger.h"
|
||||
|
||||
/* Initialize the logger so that it doesn't print by default */
|
||||
LOGGER logger = {100, 0, 100, NULL};
|
||||
|
||||
|
||||
/* Setup logging to stderr.*/
|
||||
void log_init(int level)
|
||||
{
|
||||
logger.level = level;
|
||||
}
|
||||
|
||||
|
||||
/* Set logging to a file. */
|
||||
void log_tofile(FILE *logfile, int level)
|
||||
{
|
||||
logger.filelogging = 1;
|
||||
logger.logfile = logfile;
|
||||
logger.file_level = level;
|
||||
}
|
||||
|
||||
|
||||
/* Log a message at debug level */
|
||||
void log_debug(const char *fmt, ...)
|
||||
{
|
||||
char msg[10000];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(msg, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(logger.level <= LOG_DEBUG)
|
||||
{
|
||||
fprintf(stderr, "DEBUG: %s\n", msg);
|
||||
}
|
||||
|
||||
if(logger.filelogging && (logger.file_level <= LOG_DEBUG))
|
||||
{
|
||||
fprintf(logger.logfile, "DEBUG: %s\n", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log a message at info level */
|
||||
void log_info(const char *fmt, ...)
|
||||
{
|
||||
char msg[10000];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(msg, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(logger.level <= LOG_INFO)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
}
|
||||
|
||||
if(logger.filelogging && logger.file_level <= LOG_INFO)
|
||||
{
|
||||
fprintf(logger.logfile, "%s\n", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log a message at warning level */
|
||||
void log_warning(const char *fmt, ...)
|
||||
{
|
||||
char msg[10000];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(msg, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(logger.level <= LOG_WARNING)
|
||||
{
|
||||
fprintf(stderr, "WARNING: %s\n", msg);
|
||||
}
|
||||
|
||||
if(logger.filelogging && logger.file_level <= LOG_WARNING)
|
||||
{
|
||||
fprintf(logger.logfile, "WARNING: %s\n", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log a message at error level */
|
||||
void log_error(const char *fmt, ...)
|
||||
{
|
||||
char msg[10000];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(msg, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(logger.level <= LOG_ERROR)
|
||||
{
|
||||
fprintf(stderr, "ERROR: %s\n", msg);
|
||||
}
|
||||
|
||||
if(logger.filelogging && logger.file_level <= LOG_ERROR)
|
||||
{
|
||||
fprintf(logger.logfile, "ERROR: %s\n", msg);
|
||||
}
|
||||
}
|
166
lib/logger.h
Executable file
166
lib/logger.h
Executable file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Functions to set up logging.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Logging to stderr:
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
void my_func(){
|
||||
log_info("From my_func!\n");
|
||||
}
|
||||
|
||||
int main(){
|
||||
// Enable logging to stderr in debug level
|
||||
// will only print messages of level DEBUG or higher
|
||||
log_init(LOG_DEBUG);
|
||||
log_debug("debug line. The code is %d", LOG_DEBUG);
|
||||
log_info("info line. The code is %d", LOG_INFO);
|
||||
log_warning("warning line. The code is %d", LOG_WARNING);
|
||||
log_error("error line. The code is %d", LOG_ERROR);
|
||||
my_func();
|
||||
return 0;
|
||||
}
|
||||
|
||||
will print:
|
||||
|
||||
DEBUG: debug line. The code is 0
|
||||
info line. The code is 1
|
||||
WARNING: warning line. The code is 2
|
||||
ERROR: error line. The code is 3
|
||||
From my_func!
|
||||
|
||||
If function log_init() is not called than logging to stderr is disabled and no
|
||||
messages will be printed.
|
||||
|
||||
Logging to a file:
|
||||
|
||||
#include <stdio.h>
|
||||
#include "logger.h"
|
||||
|
||||
void my_func(){
|
||||
log_info("From my_func!\n");
|
||||
log_debug("Should not appear in log file\n");
|
||||
}
|
||||
|
||||
int main(){
|
||||
// Enable logging to file "log.txt" in info level
|
||||
// will not print DEBUG level messages
|
||||
// since log_init was not called, there is no logging to stderr
|
||||
FILE *logfile = fopen("log.txt", "w");
|
||||
log_tofile(logfile, LOG_INFO);
|
||||
log_debug("debug line. The code is %d", LOG_DEBUG);
|
||||
log_info("info line. The code is %d", LOG_INFO);
|
||||
log_warning("warning line. The code is %d", LOG_WARNING);
|
||||
log_error("error line. The code is %d", LOG_ERROR);
|
||||
my_func();
|
||||
return 0;
|
||||
}
|
||||
|
||||
File log.txt will look like:
|
||||
|
||||
info line. The code is 1
|
||||
WARNING: warning line. The code is 2
|
||||
ERROR: error line. The code is 3
|
||||
From my_func!
|
||||
|
||||
Note that you can combine loggin to stderr and to a file with different
|
||||
levels in the same program.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_LOGGER_H_
|
||||
#define _TESSEROIDS_LOGGER_H_
|
||||
|
||||
/* Needed for definition of FILE */
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/** Logging level for debug messages */
|
||||
#define LOG_DEBUG 1
|
||||
/** Logging level for general information */
|
||||
#define LOG_INFO 2
|
||||
/** Logging level for warning messages */
|
||||
#define LOG_WARNING 3
|
||||
/** Logging level for error messages */
|
||||
#define LOG_ERROR 4
|
||||
|
||||
|
||||
/** Keep the information on the global logger */
|
||||
typedef struct logger_struct
|
||||
{
|
||||
int level; /**< level of logging */
|
||||
int filelogging; /**< flag to know wether loggint to a file is enabled */
|
||||
int file_level; /**< logging level for the file */
|
||||
FILE *logfile; /**< file to log to */
|
||||
|
||||
} LOGGER;
|
||||
|
||||
|
||||
/** Global logger struct. Only declare in the main program! */
|
||||
//LOGGER logger;
|
||||
|
||||
|
||||
/** Setup logging to stderr.
|
||||
|
||||
@param level level of logging to be made. Can be one of:
|
||||
- LOG_DEBUG
|
||||
- LOG_INFO
|
||||
- LOG_WARNING
|
||||
- LOG_ERROR
|
||||
*/
|
||||
void log_init(int level);
|
||||
|
||||
|
||||
/** Set logging to a file.
|
||||
|
||||
@param logfile FILE pointer to the already open file to log to.
|
||||
@param level level of logging to be made to the file. Can be one of:
|
||||
- LOG_DEBUG
|
||||
- LOG_INFO
|
||||
- LOG_WARNING
|
||||
- LOG_ERROR
|
||||
*/
|
||||
void log_tofile(FILE *logfile, int level);
|
||||
|
||||
|
||||
/** Log a message at debug level.
|
||||
|
||||
Pass parameters in the same format as printf()
|
||||
|
||||
Prints a newline at the end.
|
||||
*/
|
||||
void log_debug(const char *fmt, ...);
|
||||
|
||||
|
||||
/** Log a message at info level.
|
||||
|
||||
Pass parameters in the same format as printf()
|
||||
|
||||
Does not print "INFO: " in front of the message when logging
|
||||
|
||||
Prints a newline at the end.
|
||||
*/
|
||||
void log_info(const char *fmt, ...);
|
||||
|
||||
|
||||
/** Log a message at warning level.
|
||||
|
||||
Pass parameters in the same format as printf()
|
||||
|
||||
Prints a newline at the end.
|
||||
*/
|
||||
void log_warning(const char *fmt, ...);
|
||||
|
||||
|
||||
/** Log a message at error level.
|
||||
|
||||
Pass parameters in the same format as printf()
|
||||
|
||||
Prints a newline at the end.
|
||||
*/
|
||||
void log_error(const char *fmt, ...);
|
||||
|
||||
|
||||
#endif
|
678
lib/parsers.cpp
Executable file
678
lib/parsers.cpp
Executable file
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
Input and output parsing tools.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "logger.h"
|
||||
#include "version.h"
|
||||
#include "parsers.h"
|
||||
#include "constants.h"
|
||||
#include "geometry.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/* Parse basic command line arguments for programs */
|
||||
int parse_basic_args(int argc, char **argv, const char *progname,
|
||||
BASIC_ARGS *args, void (*print_help)(void))
|
||||
{
|
||||
int bad_args = 0, parsed_args = 0, total_args = 1, i;
|
||||
char *params;
|
||||
|
||||
/* Default values for options */
|
||||
args->verbose = 0;
|
||||
args->logtofile = 0;
|
||||
/* Parse arguments */
|
||||
for(i = 1; i < argc; i++)
|
||||
{
|
||||
if(argv[i][0] == '-')
|
||||
{
|
||||
switch(argv[i][1])
|
||||
{
|
||||
case 'h':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
print_help();
|
||||
return 2;
|
||||
case 'v':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
if(args->verbose)
|
||||
{
|
||||
log_error("repeated option -v");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
args->verbose = 1;
|
||||
break;
|
||||
case 'l':
|
||||
{
|
||||
if(args->logtofile)
|
||||
{
|
||||
log_error("repeated option -l");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][2];
|
||||
if(strlen(params) == 0)
|
||||
{
|
||||
log_error("bad input argument -l. Missing filename.");
|
||||
bad_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
args->logtofile = 1;
|
||||
args->logfname = params;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-':
|
||||
{
|
||||
params = &argv[i][2];
|
||||
if(strcmp(params, "version"))
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_version(progname);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(parsed_args == 0)
|
||||
{
|
||||
args->inputfname = argv[i];
|
||||
parsed_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("invalid argument '%s'. Already given model file %s",
|
||||
argv[i], args->inputfname);
|
||||
bad_args++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if parsing went well */
|
||||
if(parsed_args > total_args)
|
||||
{
|
||||
log_error("%s: too many input arguments. given %d, max %d.",
|
||||
progname, parsed_args, total_args);
|
||||
}
|
||||
if(bad_args > 0)
|
||||
{
|
||||
log_error("%d bad input argument(s)", bad_args);
|
||||
return 1;
|
||||
}
|
||||
if(parsed_args < total_args)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Parse command line arguments for tessh* programs */
|
||||
int parse_tessb_args(int argc, char **argv, const char *progname,
|
||||
TESSB_ARGS *args, void (*print_help)(const char *))
|
||||
{
|
||||
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_order = 0,
|
||||
parsed_ratio1 = 0, parsed_ratio2 = 0, parsed_ratio3 = 0, i, nchar, nread;
|
||||
char *params;
|
||||
|
||||
/* Default values for options */
|
||||
args->verbose = 0;
|
||||
args->logtofile = 0;
|
||||
args->lon_order = 2;
|
||||
args->lat_order = 2;
|
||||
args->r_order = 2;
|
||||
args->adaptative = 1;
|
||||
args->ratio1 = 0; /* zero means use the default for the program */
|
||||
args->ratio2 = 0;
|
||||
args->ratio3 = 0;
|
||||
/* Parse arguments */
|
||||
for(i = 1; i < argc; i++)
|
||||
{
|
||||
if(argv[i][0] == '-')
|
||||
{
|
||||
switch(argv[i][1])
|
||||
{
|
||||
case 'h':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
print_help(progname);
|
||||
return 2;
|
||||
case 'v':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
if(args->verbose)
|
||||
{
|
||||
log_error("repeated option -v");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
args->verbose = 1;
|
||||
break;
|
||||
case 'l':
|
||||
{
|
||||
if(args->logtofile)
|
||||
{
|
||||
log_error("repeated option -l");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][2];
|
||||
if(strlen(params) == 0)
|
||||
{
|
||||
log_error("bad input argument -l. Missing filename.");
|
||||
bad_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
args->logtofile = 1;
|
||||
args->logfname = params;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-':
|
||||
{
|
||||
params = &argv[i][2];
|
||||
if(strcmp(params, "version"))
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_version(progname);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
if(!args->adaptative)
|
||||
{
|
||||
log_error("repeated option -a");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
args->adaptative = 0;
|
||||
break;
|
||||
case 'o':
|
||||
{
|
||||
if(parsed_order)
|
||||
{
|
||||
log_error("repeated option -o");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][2];
|
||||
nchar = 0;
|
||||
nread = sscanf(params, "%d/%d/%d%n", &(args->lon_order),
|
||||
&(args->lat_order), &(args->r_order), &nchar);
|
||||
if(nread != 3 || *(params + nchar) != '\0')
|
||||
{
|
||||
log_error("bad input argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
parsed_order = 1;
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
{
|
||||
//ELDAR BAYKIEV///////////////////////////////////////////////////////////////////
|
||||
switch(argv[i][2])
|
||||
{
|
||||
case '1':
|
||||
{
|
||||
if(parsed_ratio1)
|
||||
{
|
||||
log_error("repeated option -t1");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][3];
|
||||
nchar = 0;
|
||||
nread = sscanf(params, "%lf%n", &(args->ratio1), &nchar);
|
||||
if(nread != 1 || *(params + nchar) != '\0')
|
||||
{
|
||||
log_error("bad input argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
parsed_ratio1 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case '2':
|
||||
{
|
||||
if(parsed_ratio2)
|
||||
{
|
||||
log_error("repeated option -t2");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][3];
|
||||
nchar = 0;
|
||||
nread = sscanf(params, "%lf%n", &(args->ratio2), &nchar);
|
||||
if(nread != 1 || *(params + nchar) != '\0')
|
||||
{
|
||||
log_error("bad input argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
parsed_ratio2 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case '3':
|
||||
{
|
||||
if(parsed_ratio3)
|
||||
{
|
||||
log_error("repeated option -t3");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
params = &argv[i][3];
|
||||
nchar = 0;
|
||||
nread = sscanf(params, "%lf%n", &(args->ratio3), &nchar);
|
||||
if(nread != 1 || *(params + nchar) != '\0')
|
||||
{
|
||||
log_error("bad input argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
parsed_ratio3 = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//ELDAR BAYKIEV///////////////////////////////////////////////////////////////////
|
||||
}
|
||||
default:
|
||||
log_error("invalid argument '%s'", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(parsed_args == 0)
|
||||
{
|
||||
args->modelfname = argv[i];
|
||||
parsed_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("invalid argument '%s'. Already given model file %s",
|
||||
argv[i], args->modelfname);
|
||||
bad_args++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if parsing went well */
|
||||
if(bad_args > 0 || parsed_args != total_args)
|
||||
{
|
||||
if(parsed_args < total_args)
|
||||
{
|
||||
log_error("%s: missing input file.",
|
||||
progname, parsed_args, total_args);
|
||||
}
|
||||
if(parsed_args > total_args)
|
||||
{
|
||||
log_error("%s: too many input arguments. given %d, max %d.",
|
||||
progname, parsed_args, total_args);
|
||||
}
|
||||
if(bad_args > 0)
|
||||
{
|
||||
log_error("%d bad input argument(s)", bad_args);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//parse arguments for gradient calculator
|
||||
int parse_gradcalc_args(int argc, char **argv, const char *progname, GRADCALC_ARGS *args, void (*print_help)(const char *))
|
||||
{
|
||||
int bad_args = 0, parsed_args = 0, total_args = 5, i;
|
||||
char *params;
|
||||
|
||||
/* Default values for options */
|
||||
args->verbose = 0;
|
||||
args->logtofile = 0;
|
||||
|
||||
args->gridbx_set = FALSE;
|
||||
args->gridby_set = FALSE;
|
||||
args->gridbz_set = FALSE;
|
||||
args->out_set = -1;
|
||||
|
||||
args->bz_NEU_NED = -1;
|
||||
args->bz_NEU_NED_set = FALSE;
|
||||
|
||||
|
||||
/* Parse arguments */
|
||||
for(i = 1; i < argc; i++)
|
||||
{
|
||||
if(argv[i][0] == '-')
|
||||
{
|
||||
switch(argv[i][1])
|
||||
{
|
||||
case 'h':
|
||||
if(argv[i][2] != '\0')
|
||||
{
|
||||
//log_error("invalid argument '%s'", argv[i]);
|
||||
printf("invalid argument '%s'\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
print_help(progname);
|
||||
return 2;
|
||||
case '-':
|
||||
{
|
||||
params = &argv[i][2];
|
||||
if(strcmp(params, "version"))
|
||||
{
|
||||
printf("invalid argument '%s'\n", argv[i]);
|
||||
bad_args++;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_version(progname);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
params = &argv[i][2];
|
||||
if(strlen(params) <= 1)
|
||||
{
|
||||
printf("bad input argument -b. Missing component and filename\n");
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(argv[i][2])
|
||||
{
|
||||
case 'x':
|
||||
if(args->gridbx_set)
|
||||
{
|
||||
printf("invalid argument '%s', gridfile bx already set\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
args->gridbx_set = 1;
|
||||
args->gridbx_fn = &argv[i][3];
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
if(args->gridby_set)
|
||||
{
|
||||
printf("invalid argument '%s', gridfile by already set\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
args->gridby_set = 1;
|
||||
args->gridby_fn = &argv[i][3];
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
if(args->gridbz_set)
|
||||
{
|
||||
printf("invalid argument '%s', gridfile by already set\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
args->gridbz_set = 1;
|
||||
args->gridbz_fn = &argv[i][3];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("invalid argument '%s', wrong component\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
params = &argv[i][2];
|
||||
|
||||
if(args->bz_NEU_NED_set)
|
||||
{
|
||||
printf("invalid argument '%s', coordinate system is already set\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
if(strlen(params) > 1)
|
||||
{
|
||||
printf("invalid argument '%s', specify coordinate system in the input grids\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
if(argv[i][2] == '1')
|
||||
{
|
||||
args->bz_NEU_NED_set = 1;
|
||||
args->bz_NEU_NED = 1;
|
||||
break;
|
||||
}
|
||||
else if(argv[i][2] == '2')
|
||||
{
|
||||
args->bz_NEU_NED_set = 1;
|
||||
args->bz_NEU_NED = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("invalid argument '%s', there are only NED (1) and NEU (2, default) coordinate systems\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
params = &argv[i][2];
|
||||
|
||||
if(args->out_set>=0)
|
||||
{
|
||||
printf("invalid argument '%s', output format is already set\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(strlen(params) != 1)
|
||||
{
|
||||
printf("invalid argument '%s', specify output format\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
//TODO Add check if it is integer
|
||||
args->out_set = atoi(params);
|
||||
break;
|
||||
default:
|
||||
printf("invalid argument '%s'\n", argv[i]);
|
||||
bad_args++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(parsed_args > total_args)
|
||||
{
|
||||
//log_error("%s: too many input arguments. given %d, max %d.", progname, parsed_args, total_args);
|
||||
}
|
||||
if(bad_args > 0)
|
||||
{
|
||||
//log_error("%d bad input argument(s)", bad_args);
|
||||
return 1;
|
||||
}
|
||||
if(parsed_args < total_args)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Strip trailing spaces and newlines from the end of a string */
|
||||
void strstrip(char *str)
|
||||
{
|
||||
int i;
|
||||
for(i = strlen(str) - 1; i >= 0; i--)
|
||||
{
|
||||
if(str[i] != ' ' && str[i] != '\n' && str[i] != '\r' && str[i] != '\0')
|
||||
break;
|
||||
}
|
||||
str[i + 1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* Read a single tesseroid from a string */
|
||||
int gets_mag_tess(const char *str, TESSEROID *tess)
|
||||
{
|
||||
double w, e, s, n, top, bot, dens, suscept, Bx, By, Bz, Rx, Ry, Rz;
|
||||
int nread, nchars;
|
||||
|
||||
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf%n", &w, &e, &s,
|
||||
&n, &top, &bot, &dens, &suscept, &Bx, &By, &Bz, &nchars);
|
||||
if(nread != 11 || str[nchars] != '\0')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
tess->w = w;
|
||||
tess->e = e;
|
||||
tess->s = s;
|
||||
tess->n = n;
|
||||
tess->r1 = MEAN_EARTH_RADIUS + bot;
|
||||
tess->r2 = MEAN_EARTH_RADIUS + top;
|
||||
tess->density = dens;
|
||||
tess->suscept = suscept;
|
||||
tess->Bx = Bx;
|
||||
tess->By = By;
|
||||
tess->Bz = Bz;
|
||||
|
||||
tess->cos_a1 = cos(PI/2.0-DEG2RAD*(w+e)*0.5);
|
||||
tess->sin_a1 = sin(PI/2.0-DEG2RAD*(w+e)*0.5);
|
||||
tess->cos_b1 = cos(DEG2RAD*(s+n)*0.5);
|
||||
tess->sin_b1 = sin(DEG2RAD*(s+n)*0.5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//ELDAR BAYKIEV////////////////////////////////
|
||||
TESSEROID * read_mag_tess_model(FILE *modelfile, int *size)
|
||||
{
|
||||
TESSEROID *model, *tmp;
|
||||
int buffsize = 300, line, badinput = 0, error_exit = 0;
|
||||
char sbuff[10000];
|
||||
|
||||
/* Start with a single buffer allocation and expand later if necessary */
|
||||
model = (TESSEROID *)malloc(buffsize*sizeof(TESSEROID));
|
||||
if(model == NULL)
|
||||
{
|
||||
log_error("problem allocating initial memory to load tesseroid model.");
|
||||
return NULL;
|
||||
}
|
||||
*size = 0;
|
||||
for(line = 1; !feof(modelfile); line++)
|
||||
{
|
||||
if(fgets(sbuff, 10000, modelfile) == NULL)
|
||||
{
|
||||
if(ferror(modelfile))
|
||||
{
|
||||
log_error("problem encountered reading line %d.", line);
|
||||
error_exit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for comments and blank lines */
|
||||
if(sbuff[0] == '#' || sbuff[0] == '\r' || sbuff[0] == '\n')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(*size == buffsize)
|
||||
{
|
||||
buffsize += buffsize;
|
||||
tmp = (TESSEROID *)realloc(model, buffsize*sizeof(TESSEROID));
|
||||
if(tmp == NULL)
|
||||
{
|
||||
/* Need to free because realloc leaves unchanged in case of
|
||||
error */
|
||||
free(model);
|
||||
log_error("problem expanding memory for tesseroid model.\nModel is too big.");
|
||||
return NULL;
|
||||
}
|
||||
model = tmp;
|
||||
}
|
||||
/* Remove any trailing spaces or newlines */
|
||||
strstrip(sbuff);
|
||||
if(gets_mag_tess(sbuff, &model[*size]))
|
||||
{
|
||||
log_warning("bad/invalid tesseroid at line %d.", line);
|
||||
badinput = 1;
|
||||
continue;
|
||||
}
|
||||
(*size)++;
|
||||
}
|
||||
}
|
||||
if(badinput || error_exit)
|
||||
{
|
||||
free(model);
|
||||
return NULL;
|
||||
}
|
||||
/* Adjust the size of the model */
|
||||
if(*size != 0)
|
||||
{
|
||||
tmp = (TESSEROID *)realloc(model, (*size)*sizeof(TESSEROID));
|
||||
if(tmp == NULL)
|
||||
{
|
||||
/* Need to free because realloc leaves unchanged in case of
|
||||
error */
|
||||
free(model);
|
||||
log_error("problem freeing excess memory for tesseroid model.");
|
||||
return NULL;
|
||||
}
|
||||
model = tmp;
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
/* Read a single rectangular prism from a string */
|
75
lib/parsers.h
Executable file
75
lib/parsers.h
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Input and output parsing tools.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TESSEROIDS_PARSERS_H_
|
||||
#define _TESSEROIDS_PARSERS_H_
|
||||
|
||||
/* Needed for definition of TESSEROID and PRISM */
|
||||
#include "geometry.h"
|
||||
/* Need for the definition of FILE */
|
||||
#include <stdio.h>
|
||||
|
||||
/** Store basic input arguments and option flags */
|
||||
typedef struct basic_args
|
||||
{
|
||||
char *inputfname; /**< name of the input file */
|
||||
int verbose; /**< flag to indicate if verbose printing is enabled */
|
||||
int logtofile; /**< flag to indicate if logging to a file is enabled */
|
||||
char *logfname; /**< name of the log file */
|
||||
} BASIC_ARGS;
|
||||
|
||||
typedef struct tessh_args
|
||||
{
|
||||
int lon_order; /**< glq order in longitude integration */
|
||||
int lat_order; /**< glq order in latitude integration */
|
||||
int r_order; /**< glq order in radial integration */
|
||||
char *modelfname; /**< name of the file with the tesseroid model */
|
||||
int verbose; /**< flag to indicate if verbose printing is enabled */
|
||||
int logtofile; /**< flag to indicate if logging to a file is enabled */
|
||||
char *logfname; /**< name of the log file */
|
||||
int adaptative; /**< flat to indicate wether to use the adaptative size
|
||||
of tesseroid algorithm */
|
||||
double ratio1; /**< distance-size ratio used for recusive division */
|
||||
double ratio2; /**< distance-size ratio used for recusive division */
|
||||
double ratio3; /**< distance-size ratio used for recusive division */
|
||||
} TESSB_ARGS;
|
||||
|
||||
|
||||
typedef struct gradcalc_args
|
||||
{
|
||||
int gridbx_set;
|
||||
int gridby_set;
|
||||
int gridbz_set;
|
||||
|
||||
char* gridbx_fn;
|
||||
char* gridby_fn;
|
||||
char* gridbz_fn;
|
||||
|
||||
int out_set;
|
||||
|
||||
|
||||
int bz_NEU_NED;
|
||||
int bz_NEU_NED_set;
|
||||
|
||||
int verbose; /**< flag to indicate if verbose printing is enabled */
|
||||
int logtofile; /**< flag to indicate if logging to a file is enabled */
|
||||
|
||||
|
||||
|
||||
|
||||
} GRADCALC_ARGS;
|
||||
|
||||
int parse_basic_args(int argc, char **argv, const char *progname, BASIC_ARGS *args, void (*print_help)(void));
|
||||
int parse_tessb_args(int argc, char **argv, const char *progname, TESSB_ARGS *args, void (*print_help)(const char *));
|
||||
|
||||
int parse_gradcalc_args(int argc, char **argv, const char *progname, GRADCALC_ARGS *args, void (*print_help)(const char *));
|
||||
|
||||
void strstrip(char *str);
|
||||
|
||||
int gets_mag_tess(const char *str, TESSEROID *tess);
|
||||
TESSEROID * read_mag_tess_model(FILE *modelfile, int *size);
|
||||
|
||||
|
||||
#endif
|
385
lib/tessb_main.cpp
Executable file
385
lib/tessb_main.cpp
Executable file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
Generic main function for the tessb* programs.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "logger.h"
|
||||
#include "version.h"
|
||||
#include "grav_tess.h"
|
||||
#include "glq.h"
|
||||
#include "constants.h"
|
||||
#include "geometry.h"
|
||||
#include "parsers.h"
|
||||
#include "tessb_main.h"
|
||||
#include "linalg.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* Print the help message for tessh* programs */
|
||||
void print_tessb_help(const char *progname)
|
||||
{
|
||||
printf("MAGNETIC TESSEROIDS\n");
|
||||
printf("Usage: %s MODELFILE [OPTIONS]\n\n", progname);
|
||||
if(strcmp(progname + 4, "pot") == 0)
|
||||
{
|
||||
printf("Calculate the potential due to a tesseroid model on\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Calculate the %s component due to a tesseroid model on\n",
|
||||
progname + 4);
|
||||
}
|
||||
printf("TODO\n");
|
||||
}
|
||||
|
||||
|
||||
/* Run the main for a generic tessh* program */
|
||||
int run_tessb_main(int argc, char **argv, const char *progname,
|
||||
double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ),
|
||||
double ratio1, double ratio2, double ratio3)
|
||||
{
|
||||
TESSB_ARGS args;
|
||||
GLQ *glq_lon, *glq_lat, *glq_r;
|
||||
TESSEROID *model;
|
||||
|
||||
int modelsize, rc, line, points = 0, error_exit = 0, bad_input = 0;
|
||||
char buff[10000];
|
||||
|
||||
double lon, lat, height, res;
|
||||
|
||||
/*variables for precalculation of trigonometrical functions for tesseroid centers*/
|
||||
double cos_a2, sin_a2, cos_b2, sin_b2;
|
||||
|
||||
/*variables for precalculation of trigonometrical functions for grid points*/
|
||||
double lon_prev, lat_prev;
|
||||
double cos_a2_prev, sin_a2_prev, cos_b2_prev, sin_b2_prev;
|
||||
|
||||
FILE *logfile = NULL, *modelfile = NULL;
|
||||
time_t rawtime;
|
||||
clock_t tstart;
|
||||
struct tm * timeinfo;
|
||||
|
||||
double (*field1)(TESSEROID, double, double, double, GLQ, GLQ, GLQ);
|
||||
double (*field2)(TESSEROID, double, double, double, GLQ, GLQ, GLQ);
|
||||
double (*field3)(TESSEROID, double, double, double, GLQ, GLQ, GLQ);
|
||||
void (*field_triple)(TESSEROID, double, double, double, GLQ, GLQ, GLQ, double*);
|
||||
double ggt_1, ggt_2, ggt_3;
|
||||
double gtt_v[3];
|
||||
int n_tesseroid;
|
||||
|
||||
|
||||
log_init(LOG_INFO);
|
||||
|
||||
rc = parse_tessb_args(argc, argv, progname, &args, &print_tessb_help);
|
||||
if(rc == 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(rc == 1)
|
||||
{
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set the appropriate logging level and log to file if necessary */
|
||||
if(!args.verbose)
|
||||
{
|
||||
log_init(LOG_WARNING);
|
||||
}
|
||||
if(args.logtofile)
|
||||
{
|
||||
logfile = fopen(args.logfname, "w");
|
||||
if(logfile == NULL)
|
||||
{
|
||||
log_error("unable to create log file %s", args.logfname);
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
return 1;
|
||||
}
|
||||
log_tofile(logfile, LOG_DEBUG);
|
||||
}
|
||||
|
||||
/* Check if a custom distance-size ratio is given */
|
||||
if(args.ratio1 != 0)
|
||||
{
|
||||
ratio1 = args.ratio1;
|
||||
}
|
||||
if(args.ratio2 != 0)
|
||||
{
|
||||
ratio2 = args.ratio2;
|
||||
}
|
||||
if(args.ratio3 != 0)
|
||||
{
|
||||
ratio3 = args.ratio3;
|
||||
}
|
||||
|
||||
/* Print standard verbose */
|
||||
log_info("%s (Tesseroids project) %s", progname, tesseroids_version);
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
log_info("(local time) %s", asctime(timeinfo));
|
||||
log_info("Use recursive division of tesseroids: %s",
|
||||
args.adaptative ? "True" : "False");
|
||||
log_info("Distance-size ratio1 for recusive division: %g", ratio1);
|
||||
log_info("Distance-size ratio2 for recusive division: %g", ratio2);
|
||||
log_info("Distance-size ratio3 for recusive division: %g", ratio3);
|
||||
|
||||
/* Make the necessary GLQ structures */
|
||||
log_info("Using GLQ orders: %d lon / %d lat / %d r", args.lon_order,
|
||||
args.lat_order, args.r_order);
|
||||
glq_lon = glq_new(args.lon_order, -1, 1);
|
||||
glq_lat = glq_new(args.lat_order, -1, 1);
|
||||
glq_r = glq_new(args.r_order, -1, 1);
|
||||
if(glq_lon == NULL || glq_lat == NULL || glq_r == NULL)
|
||||
{
|
||||
log_error("failed to create required GLQ structures");
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
if(args.logtofile)
|
||||
fclose(logfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read the tesseroid model file */
|
||||
log_info("Reading magnetic tesseroid model from file %s", args.modelfname);
|
||||
modelfile = fopen(args.modelfname, "r");
|
||||
if(modelfile == NULL)
|
||||
{
|
||||
log_error("failed to open model file %s", args.modelfname);
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
if(args.logtofile)
|
||||
fclose(logfile);
|
||||
return 1;
|
||||
}
|
||||
model = read_mag_tess_model(modelfile, &modelsize);
|
||||
fclose(modelfile);
|
||||
if(modelsize == 0)
|
||||
{
|
||||
log_error("tesseroid file %s is empty", args.modelfname);
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
if(args.logtofile)
|
||||
fclose(logfile);
|
||||
return 1;
|
||||
}
|
||||
if(model == NULL)
|
||||
{
|
||||
log_error("failed to read model from file %s", args.modelfname);
|
||||
log_warning("Terminating due to bad input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
if(args.logtofile)
|
||||
fclose(logfile);
|
||||
return 1;
|
||||
}
|
||||
log_info("Total of %d tesseroid(s) read", modelsize);
|
||||
|
||||
/* Print a header on the output with provenance information */
|
||||
if(strcmp(progname + 4, "pot") == 0)
|
||||
{
|
||||
printf("# Potential calculated with %s %s:\n", progname,
|
||||
tesseroids_version);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("# %s component calculated with %s %s:\n", progname+4, progname,
|
||||
tesseroids_version);
|
||||
}
|
||||
printf("# local time: %s", asctime(timeinfo));
|
||||
printf("# model file: %s (%d tesseroids)\n", args.modelfname, modelsize);
|
||||
printf("# GLQ order: %d lon / %d lat / %d r\n", args.lon_order,
|
||||
args.lat_order, args.r_order);
|
||||
printf("# Use recursive division of tesseroids: %s\n",
|
||||
args.adaptative ? "True" : "False");
|
||||
printf("# Distance-size ratio1 for recusive division: %g\n", ratio1);
|
||||
printf("# Distance-size ratio2 for recusive division: %g\n", ratio2);
|
||||
printf("# Distance-size ratio3 for recusive division: %g\n", ratio3);
|
||||
|
||||
/////////////ELDAR BAYKIEV//////////////
|
||||
/* Assign pointers to functions that calculate gravity gradient tensor components */
|
||||
if (!strcmp("tessbx", progname))
|
||||
{
|
||||
field1 = &tess_gxx;
|
||||
field2 = &tess_gxy;
|
||||
field3 = &tess_gxz;
|
||||
|
||||
field_triple = &tess_gxx_gxy_gxz;
|
||||
}
|
||||
|
||||
if (!strcmp("tessby", progname))
|
||||
{
|
||||
field1 = &tess_gxy;
|
||||
field2 = &tess_gyy;
|
||||
field3 = &tess_gyz;
|
||||
|
||||
field_triple = &tess_gxy_gyy_gyz;
|
||||
}
|
||||
|
||||
if (!strcmp("tessbz", progname))
|
||||
{
|
||||
field1 = &tess_gxz;
|
||||
field2 = &tess_gyz;
|
||||
field3 = &tess_gzz;
|
||||
|
||||
field_triple = &tess_gxz_gyz_gzz;
|
||||
}
|
||||
/////////////ELDAR BAYKIEV//////////////
|
||||
|
||||
/* Read each computation point from stdin and calculate */
|
||||
log_info("Calculating (this may take a while)...");
|
||||
tstart = clock();
|
||||
|
||||
///////////////
|
||||
lon_prev = 0;
|
||||
lat_prev = 0;
|
||||
|
||||
for(line = 1; !feof(stdin); line++)
|
||||
{
|
||||
if(fgets(buff, 10000, stdin) == NULL)
|
||||
{
|
||||
if(ferror(stdin))
|
||||
{
|
||||
log_error("problem encountered reading line %d", line);
|
||||
error_exit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for comments and blank lines */
|
||||
if(buff[0] == '#' || buff[0] == '\r' || buff[0] == '\n')
|
||||
{
|
||||
printf("%s", buff);
|
||||
continue;
|
||||
}
|
||||
if(sscanf(buff, "%lf %lf %lf", &lon, &lat, &height) != 3)
|
||||
{
|
||||
log_warning("bad/invalid computation point at line %d", line);
|
||||
log_warning("skipping this line and continuing");
|
||||
bad_input++;
|
||||
continue;
|
||||
}
|
||||
/* Need to remove \n and \r from end of buff first to print the
|
||||
result in the end */
|
||||
strstrip(buff);
|
||||
|
||||
|
||||
|
||||
/////////////ELDAR BAYKIEV//////////////
|
||||
res = 0;
|
||||
if(args.adaptative)
|
||||
{
|
||||
for(n_tesseroid = 0; n_tesseroid < modelsize; n_tesseroid++)
|
||||
{
|
||||
gtt_v[0] = 0;
|
||||
gtt_v[1] = 0;
|
||||
gtt_v[2] = 0;
|
||||
double B_to_H = model[n_tesseroid].suscept/(M_0);//IMPORTANT
|
||||
double M_vect[3] = {model[n_tesseroid].Bx * B_to_H, model[n_tesseroid].By * B_to_H, model[n_tesseroid].Bz * B_to_H};
|
||||
double M_vect_p[3] = {0, 0, 0};
|
||||
|
||||
conv_vect_cblas(M_vect, (model[n_tesseroid].w + model[n_tesseroid].e)*0.5, (model[n_tesseroid].s + model[n_tesseroid].n)*0.5, lon, lat, M_vect_p);
|
||||
|
||||
ggt_1 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field1, ratio1);
|
||||
ggt_2 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field2, ratio2);
|
||||
ggt_3 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field3, ratio3);
|
||||
|
||||
res = res + M_0*EOTVOS2SI*(ggt_1 * M_vect_p[0] + ggt_2 * M_vect_p[1] + ggt_3 * M_vect_p[2]) /(G*model[n_tesseroid].density*4*PI);
|
||||
|
||||
//printf("res %g\n", res);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
else
|
||||
{
|
||||
//precalculate trigonometrical functions
|
||||
|
||||
if(lon == lon_prev)
|
||||
{
|
||||
cos_b2 = cos_b2_prev;
|
||||
sin_b2 = sin_b2_prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
cos_b2 = cos(DEG2RAD*lon);
|
||||
sin_b2 = sin(DEG2RAD*lon);
|
||||
}
|
||||
|
||||
if(lat == lat_prev)
|
||||
{
|
||||
cos_a2 = cos_a2_prev;
|
||||
sin_a2 = sin_a2_prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
cos_a2 = cos(PI/2.0-DEG2RAD*lat);
|
||||
sin_a2 = sin(PI/2.0-DEG2RAD*lat);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
for(n_tesseroid = 0; n_tesseroid < modelsize; n_tesseroid++)
|
||||
{
|
||||
gtt_v[0] = 0;
|
||||
gtt_v[1] = 0;
|
||||
gtt_v[2] = 0;
|
||||
//ELDAR: TODO: PRECALCULATE SIC COSINE TABLES
|
||||
double B_to_H = model[n_tesseroid].suscept/(M_0);//IMPORTANT
|
||||
double M_vect[3] = {model[n_tesseroid].Bx * B_to_H, model[n_tesseroid].By * B_to_H, model[n_tesseroid].Bz * B_to_H};
|
||||
double M_vect_p[3] = {0, 0, 0};
|
||||
|
||||
//conv_vect_cblas(M_vect, (model[n_tesseroid].w + model[n_tesseroid].e)*0.5, (model[n_tesseroid].s + model[n_tesseroid].n)*0.5, lon, lat, M_vect_p);
|
||||
conv_vect_cblas_precalc(M_vect, model[n_tesseroid].cos_a1, model[n_tesseroid].sin_a1, model[n_tesseroid].cos_b1, model[n_tesseroid].sin_b1, cos_a2, sin_a2, cos_b2, sin_b2, M_vect_p);
|
||||
|
||||
calc_tess_model_triple(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field_triple, gtt_v);
|
||||
|
||||
res = res + M_0*EOTVOS2SI*(gtt_v[0] * M_vect_p[0] + gtt_v[1] * M_vect_p[1] + gtt_v[2] * M_vect_p[2]) /(G*model[n_tesseroid].density*4*PI);
|
||||
|
||||
}
|
||||
|
||||
lon_prev = lon;
|
||||
lat_prev = lat;
|
||||
|
||||
cos_a2_prev = cos_a2;
|
||||
sin_a2_prev = sin_a2;
|
||||
|
||||
cos_b2_prev = cos_b2;
|
||||
sin_b2_prev = sin_b2;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
printf("%s %.15g\n", buff, res);
|
||||
points++;
|
||||
}
|
||||
}
|
||||
if(bad_input)
|
||||
{
|
||||
log_warning("Encountered %d bad computation points which were skipped",
|
||||
bad_input);
|
||||
}
|
||||
if(error_exit)
|
||||
{
|
||||
log_warning("Terminating due to error in input");
|
||||
log_warning("Try '%s -h' for instructions", progname);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("Calculated on %d points in %.5g seconds", points,
|
||||
(double)(clock() - tstart)/CLOCKS_PER_SEC);
|
||||
}
|
||||
/* Clean up */
|
||||
free(model);
|
||||
glq_free(glq_lon);
|
||||
glq_free(glq_lat);
|
||||
glq_free(glq_r);
|
||||
log_info("Done");
|
||||
if(args.logtofile)
|
||||
fclose(logfile);
|
||||
return 0;
|
||||
}
|
14
lib/tessb_main.h
Executable file
14
lib/tessb_main.h
Executable file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Generic main function for the tessb* programs.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_TESSH_MAIN_H_
|
||||
#define _TESSEROIDS_TESSH_MAIN_H_
|
||||
|
||||
#include "glq.h"
|
||||
#include "geometry.h"
|
||||
|
||||
void print_tessb_help(const char *progname);
|
||||
int run_tessb_main(int argc, char **argv, const char *progname, double (*field)(TESSEROID, double, double, double, GLQ, GLQ, GLQ), double ratio1, double ratio2, double ratio3);
|
||||
|
||||
#endif
|
17
lib/version.cpp
Executable file
17
lib/version.cpp
Executable file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Hold the version number of the project.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "version.h"
|
||||
|
||||
|
||||
/* Print version and license information */
|
||||
void print_version(const char *progname)
|
||||
{
|
||||
printf("%s (Magnetic Tesseroids) %s\n\n", progname, tesseroids_version);
|
||||
printf("Copyright (C) 2015, Eldar Baykiev.\n");
|
||||
printf("This program is based on the code of Leonardo Uieda.\n");
|
||||
printf("<http://tesseroids.readthedocs.org/>\n");
|
||||
printf("Developed by Eldar Baykiev.\n");
|
||||
}
|
18
lib/version.h
Executable file
18
lib/version.h
Executable file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Hold the version number of the project.
|
||||
*/
|
||||
|
||||
#ifndef _TESSEROIDS_VERSION_H_
|
||||
#define _TESSEROIDS_VERSION_H_
|
||||
|
||||
/** Current project version number */
|
||||
const char tesseroids_version[] = "1.1";
|
||||
|
||||
|
||||
/** Print version and license information
|
||||
|
||||
@param progname name of the program
|
||||
*/
|
||||
void print_version(const char *progname);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user