tesseroids/lib/grav_prism_sph.c
2021-05-05 10:58:03 +08:00

220 lines
6.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Functions that calculate the gravitational potential and its first and second
derivatives for the rectangular prism in spherical coordinates.
Uses the formulas in Nagy et al. (2000).
References
----------
* Nagy, D., Papp, G., Benedek, J. (2000): The gravitational potential and its
derivatives for the prism. Journal of Geodesy, 74, 552560.
*/
#include <math.h>
#include "geometry.h"
#include "constants.h"
#include "grav_prism_sph.h"
#include "grav_prism.h"
/* Transform spherical coordinates to local Cartesian coordinates of the prism*/
int global2local(double lon, double lat, double r, PRISM prism, double *x,
double *y, double *z)
{
double cosa, cosb, sina, sinb, d2r, X, Y, Z;
/* degrees to radians */
d2r = PI/180.;
X = r*cos(d2r*lat)*cos(d2r*lon) -
prism.r*cos(d2r*prism.lat)*cos(d2r*prism.lon);
Y = r*cos(d2r*lat)*sin(d2r*lon) -
prism.r*cos(d2r*prism.lat)*sin(d2r*prism.lon);
Z = r*sin(d2r*lat) - prism.r*sin(d2r*prism.lat);
cosa = cos(d2r*(90 - prism.lat));
sina = sin(d2r*(90 - prism.lat));
cosb = cos(d2r*(180 - prism.lon));
sinb = sin(d2r*(180 - prism.lon));
*x = X*cosa*cosb - Y*cosa*sinb + Z*sina;
*y = -X*sinb - Y*cosb;
/* -1 because Nagy et al. (2000) use z->down */
*z = -1*(-X*sina*cosb + Y*sina*sinb + Z*cosa);
return 0;
}
/* Rotate the gravity vector from the prisms coordinate system to the local
system of the computation point. */
int g_prism2point(double *atprism, PRISM prism, double lon, double lat,
double r, double *atpoint)
{
#define POS(x, y, cols) (((x)*(cols))+(y))
register int i, k;
double R[9], d2r, cosbeta, sinbeta, cosphi, sinphi, cosphil, sinphil;
/* degrees to radians */
d2r = PI/180.;
cosbeta = cos(d2r*(prism.lon - lon));
sinbeta = sin(d2r*(prism.lon - lon));
cosphi = cos(d2r*lat);
sinphi = sin(d2r*lat);
cosphil = cos(d2r*prism.lat);
sinphil = sin(d2r*prism.lat);
/* The transformation matrix */
R[0] = cosbeta*sinphi*sinphil + cosphi*cosphil;
R[1] = sinbeta*sinphi;
R[2] = -cosbeta*sinphi*cosphil + cosphi*sinphil;
R[3] = -sinbeta*sinphil;
R[4] = cosbeta;
R[5] = sinbeta*cosphil;
R[6] = -cosbeta*cosphi*sinphil + sinphi*cosphil;
R[7] = -sinbeta*cosphi;
R[8] = cosbeta*cosphi*cosphil + sinphi*sinphil;
/* Matrix-vector multiplication */
for(i = 0; i < 3; i++)
{
atpoint[i] = 0;
for(k = 0; k < 3; k++)
{
atpoint[i] += R[POS(i, k, 3)]*atprism[k];
}
}
#undef POS
return 0;
}
/* Rotate the gravity tensor from the prisms coordinate system to the local
system of the computation point. */
int ggt_prism2point(double *atprism, PRISM prism, double lon, double lat,
double r, double *atpoint)
{
#define POS(x, y, cols) (((x)*(cols))+(y))
register int i, j, k;
double R[9], tmp[9], d2r, cosbeta, sinbeta, cosphi, sinphi, cosphil, sinphil;
/* degrees to radians */
d2r = PI/180.;
cosbeta = cos(d2r*(prism.lon - lon));
sinbeta = sin(d2r*(prism.lon - lon));
cosphi = cos(d2r*lat);
sinphi = sin(d2r*lat);
cosphil = cos(d2r*prism.lat);
sinphil = sin(d2r*prism.lat);
/* The transformation matrix */
R[0] = cosbeta*sinphi*sinphil + cosphi*cosphil;
R[1] = sinbeta*sinphi;
R[2] = -cosbeta*sinphi*cosphil + cosphi*sinphil;
R[3] = -sinbeta*sinphil;
R[4] = cosbeta;
R[5] = sinbeta*cosphil;
R[6] = -cosbeta*cosphi*sinphil + sinphi*cosphil;
R[7] = -sinbeta*cosphi;
R[8] = cosbeta*cosphi*cosphil + sinphi*sinphil;
/* Multiply tmp = R*Tensor */
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
tmp[POS(i, j, 3)] = 0;
for(k = 0; k < 3; k++)
{
tmp[POS(i, j, 3)] += R[POS(i, k, 3)]*atprism[POS(k, j, 3)];
}
}
}
/* Multiply tmp*R^T */
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
atpoint[POS(i, j, 3)] = 0;
for(k = 0; k < 3; k++)
{
atpoint[POS(i, j, 3)] += tmp[POS(i, k, 3)]*R[POS(j, k, 3)];
}
}
}
#undef POS
return 0;
}
/* Calculates the gravity gradient tensor caused by a prism. */
int prism_ggt_sph(PRISM prism, double lonp, double latp, double rp, double *ggt)
{
double x = 0, y = 0, z = 0, ggtprism[9], ggtpoint[9];
global2local(lonp, latp, rp, prism, &x, &y, &z);
ggtprism[0] = prism_gxx(prism, x, y, z);
ggtprism[1] = prism_gxy(prism, x, y, z);
/* -1 because the prisms z is Down, but transformation assumes z is Up */
/* z -> Up is the system of the tesseroid */
ggtprism[2] = -1*prism_gxz(prism, x, y, z);
ggtprism[3] = ggtprism[1];
ggtprism[4] = prism_gyy(prism, x, y, z);
/* Same as xz */
ggtprism[5] = -1*prism_gyz(prism, x, y, z);
ggtprism[6] = ggtprism[2];
ggtprism[7] = ggtprism[5];
ggtprism[8] = -(ggtprism[0] + ggtprism[4]);
ggt_prism2point(ggtprism, prism, lonp, latp, rp, ggtpoint);
ggt[0] = ggtpoint[0];
ggt[1] = ggtpoint[1];
ggt[2] = ggtpoint[2];
ggt[3] = ggtpoint[4];
ggt[4] = ggtpoint[5];
ggt[5] = ggtpoint[8];
return 0;
}
/* Calculates the gravitational attraction caused by a prism. */
int prism_g_sph(PRISM prism, double lonp, double latp, double rp, double *gx,
double *gy, double *gz)
{
double x = 0, y = 0, z = 0, gprism[3], gpoint[3];
global2local(lonp, latp, rp, prism, &x, &y, &z);
gprism[0] = prism_gx(prism, x, y, z);
gprism[1] = prism_gy(prism, x, y, z);
/* Nagy wants z down, but the transformation assumes z up */
gprism[2] = -prism_gz(prism, x, y, z);
g_prism2point(gprism, prism, lonp, latp, rp, gpoint);
*gx = gpoint[0];
*gy = gpoint[1];
/* Put z back down again to maintain the normal convention for gz */
*gz = -gpoint[2];
return 0;
}
/* Calculates the potential caused by a prism. */
double prism_pot_sph(PRISM prism, double lonp, double latp, double rp)
{
double x = 0, y = 0, z = 0, res;
global2local(lonp, latp, rp, prism, &x, &y, &z);
res = prism_pot(prism, x, y, z);
return res;
}