initial upload
This commit is contained in:
580
lib/grav_tess.c
Normal file
580
lib/grav_tess.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#define STKSIZE 10000
|
||||
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
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);
|
||||
glq_precompute_sincos(glq_lat);
|
||||
res += field(model[tess], lonp, latp, rp, *glq_lon, *glq_lat, *glq_r);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* 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, distance, lont, latt, rt, d2r = PI/180.,
|
||||
coslatp, sinlatp, rp_sqr, rlonp,
|
||||
Llon, Llat, Lr,
|
||||
sinlatt, coslatt;
|
||||
int t, n, nlon, nlat, nr, stktop = 0;
|
||||
TESSEROID stack[STKSIZE], tess;
|
||||
|
||||
#define SQ(x) (x)*(x)
|
||||
/* Pre-compute these things out of the loop */
|
||||
rlonp = d2r*lonp;
|
||||
rp_sqr = SQ(rp);
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
res = 0;
|
||||
for(t = 0; t < size; t++)
|
||||
{
|
||||
/* Initialize the tesseroid division stack (a LIFO structure) */
|
||||
stack[0] = model[t];
|
||||
stktop = 0;
|
||||
while(stktop >= 0)
|
||||
{
|
||||
/* Pop the stack */
|
||||
tess = stack[stktop];
|
||||
stktop--;
|
||||
/* Compute the distance from the computation point to the
|
||||
* geometric center of the tesseroid. */
|
||||
rt = 0.5*(tess.r2 + tess.r1);
|
||||
lont = d2r*0.5*(tess.w + tess.e);
|
||||
latt = d2r*0.5*(tess.s + tess.n);
|
||||
sinlatt = sin(latt);
|
||||
coslatt = cos(latt);
|
||||
distance = sqrt(rp_sqr + SQ(rt) - 2*rp*rt*(
|
||||
sinlatp*sinlatt + coslatp*coslatt*cos(rlonp - lont)));
|
||||
/* Get the size of each dimension of the tesseroid in meters */
|
||||
Llon = tess.r2*acos(
|
||||
SQ(sinlatt) + SQ(coslatt)*cos(d2r*(tess.e - tess.w)));
|
||||
Llat = tess.r2*acos(
|
||||
sin(d2r*tess.n)*sin(d2r*tess.s) +
|
||||
cos(d2r*tess.n)*cos(d2r*tess.s));
|
||||
Lr = tess.r2 - tess.r1;
|
||||
/* Number of times to split the tesseroid in each dimension */
|
||||
nlon = 1;
|
||||
nlat = 1;
|
||||
nr = 1;
|
||||
/* Check if the tesseroid is at a suitable distance (defined
|
||||
* the value of "ratio"). If not, mark that dimension for
|
||||
* division. */
|
||||
if(distance < ratio*Llon)
|
||||
{
|
||||
nlon = 2;
|
||||
}
|
||||
if(distance < ratio*Llat)
|
||||
{
|
||||
nlat = 2;
|
||||
}
|
||||
if(distance < ratio*Lr)
|
||||
{
|
||||
nr = 2;
|
||||
}
|
||||
/* In case none of the dimensions need dividing,
|
||||
* put the GLQ roots in the proper scale and compute the
|
||||
* gravitational field of the tesseroid. */
|
||||
/* Also compute the effect if the tesseroid stack if full
|
||||
* (but warn the user that the computation might not be very
|
||||
* precise). */
|
||||
if((nlon == 1 && nlat == 1 && nr == 1)
|
||||
|| (nlon*nlat*nr + stktop >= STKSIZE))
|
||||
{
|
||||
if(nlon*nlat*nr + stktop >= STKSIZE)
|
||||
{
|
||||
log_error(
|
||||
"Stack overflow: "
|
||||
"tesseroid %d in the model file on "
|
||||
"lon=%lf lat=%lf height=%lf."
|
||||
"\n Calculated without fully dividing the tesseroid. "
|
||||
"Accuracy of the solution cannot be guaranteed."
|
||||
"\n This is probably caused by a computation point "
|
||||
"too close to the tesseroid."
|
||||
"\n Try increasing the computation height."
|
||||
"\n *Expert users* can try modifying the "
|
||||
"distance-size ratio."
|
||||
"\n *Beware* that this might affect "
|
||||
"the accuracy of the solution.",
|
||||
t + 1, lonp, latp, rp);
|
||||
}
|
||||
glq_set_limits(tess.w, tess.e, glq_lon);
|
||||
glq_set_limits(tess.s, tess.n, glq_lat);
|
||||
glq_set_limits(tess.r1, tess.r2, glq_r);
|
||||
glq_precompute_sincos(glq_lat);
|
||||
res += field(tess, lonp, latp, rp, *glq_lon, *glq_lat, *glq_r);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Divide the tesseroid in each dimension that needs dividing
|
||||
* Put each of the smaller tesseroids on the stack for
|
||||
* computing in the next iteration. */
|
||||
n = split_tess(tess, nlon, nlat, nr, &stack[stktop + 1]);
|
||||
stktop += n;
|
||||
/* Sanity check */
|
||||
if(n != nlon*nlat*nr)
|
||||
{
|
||||
log_error("Splitting into %d instead of %d", n,
|
||||
nlon*nlat*nr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef SQ
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates potential caused by a tesseroid. */
|
||||
double tess_pot(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, rc, kappa, res,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
res += wlon*wlat*wr*kappa/sqrt(l_sqr);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= G*tess.density*scale;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gx caused by a tesseroid. */
|
||||
double tess_gx(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,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
res += wlon*wlat*wr*kappa*(rc*kphi)/pow(l_sqr, 1.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2MGAL*G*tess.density*scale;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gy caused by a tesseroid. */
|
||||
double tess_gy(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, res,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
res += wlon*wlat*wr*kappa*(rc*coslatc*sinlon)/pow(l_sqr, 1.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2MGAL*G*tess.density*scale;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Calculates gz caused by a tesseroid. */
|
||||
double tess_gz(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, res,
|
||||
wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
res += wlon*wlat*wr*kappa*(rc*cospsi - rp)/pow(l_sqr, 1.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2MGAL*G*tess.density*scale;
|
||||
/* Used this to make z point down */
|
||||
return -1*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, l5,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
l5 = pow(l_sqr, 2.5);
|
||||
kappa = rc*rc*coslatc;
|
||||
res += wlon*wlat*wr*kappa*(3*rc*kphi*rc*kphi - l_sqr)/l5;
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
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,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
deltax = rc*kphi;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
res += wlon*wlat*wr*kappa*(3*deltax*deltay)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
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,
|
||||
wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
kphi = coslatp*sinlatc - sinlatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
deltax = rc*kphi;
|
||||
deltaz = rc*cospsi - rp;
|
||||
res += wlon*wlat*wr*kappa*(3*deltax*deltaz)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
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, l5,
|
||||
cospsi, wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
l5 = pow(l_sqr, 2.5);
|
||||
kappa = rc*rc*coslatc;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
res += wlon*wlat*wr*kappa*(3*deltay*deltay - l_sqr)/l5;
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
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,
|
||||
wlon, wlat, wr, scale;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
sinlon = sin(d2r*(glq_lon.nodes[k] - lonp));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
kappa = rc*rc*coslatc;
|
||||
deltay = rc*coslatc*sinlon;
|
||||
deltaz = rc*cospsi - rp;
|
||||
res += wlon*wlat*wr*kappa*(3*deltay*deltaz)/pow(l_sqr, 2.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
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,
|
||||
wlon, wlat, wr, scale, l5;
|
||||
register int i, j, k;
|
||||
|
||||
coslatp = cos(d2r*latp);
|
||||
sinlatp = sin(d2r*latp);
|
||||
|
||||
res = 0;
|
||||
|
||||
for(k = 0; k < glq_lon.order; k++)
|
||||
{
|
||||
coslon = cos(d2r*(lonp - glq_lon.nodes[k]));
|
||||
wlon = glq_lon.weights[k];
|
||||
for(j = 0; j < glq_lat.order; j++)
|
||||
{
|
||||
sinlatc = glq_lat.nodes_sin[j];
|
||||
coslatc = glq_lat.nodes_cos[j];
|
||||
cospsi = sinlatp*sinlatc + coslatp*coslatc*coslon;
|
||||
wlat = glq_lat.weights[j];
|
||||
for(i = 0; i < glq_r.order; i++)
|
||||
{
|
||||
wr = glq_r.weights[i];
|
||||
rc = glq_r.nodes[i];
|
||||
l_sqr = rp*rp + rc*rc - 2*rp*rc*cospsi;
|
||||
l5 = pow(l_sqr, 2.5);
|
||||
kappa = rc*rc*coslatc;
|
||||
deltaz = rc*cospsi - rp;
|
||||
res += wlon*wlat*wr*kappa*(3*deltaz*deltaz - l_sqr)/l5;
|
||||
}
|
||||
}
|
||||
}
|
||||
scale = d2r*(tess.e - tess.w)*d2r*(tess.n - tess.s)*(tess.r2 - tess.r1)/8.;
|
||||
res *= SI2EOTVOS*G*tess.density*scale;
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user