629 lines
21 KiB
C++
629 lines
21 KiB
C++
|
/*
|
||
|
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(MAG_TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(MAG_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(MAG_TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, void (*field_triple)(MAG_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(MAG_TESSEROID *model, int size, double lonp, double latp, double rp, GLQ *glq_lon, GLQ *glq_lat, GLQ *glq_r, double (*field)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ), double ratio)
|
||
|
{
|
||
|
double res, dist, lont, latt, rt, d2r = PI/180.;
|
||
|
int tess;
|
||
|
MAG_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(MAG_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(MAG_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(MAG_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(MAG_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(MAG_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(MAG_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(MAG_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(MAG_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(MAG_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;
|
||
|
}
|