-
Jan Willem Thorbecke authoredJan Willem Thorbecke authored
JespersRayTracer.c 25.89 KiB
//
// JespersRayTracer.c
//
//
// Written by Jesper Spetzler
//
// changed to C by Jan Thorbecke on 21/09/2017.
//
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "raytime.h"
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5))
static float H, L, W, iH, iL, iW;
int getnRay(icoord size, fcoord s, fcoord r, float dx, int nRayStep);
int traceTwoPoint(fcoord s, fcoord r, int nRay, fcoord *rayReference3D);
float takeOffAngle(fcoord s, fcoord r);
float referenceSlowness(float *slowness, icoord size, int nRay, fcoord r, fcoord s);
int xPointIndex(const float _x, int nx, float L);
int zPointIndex(const float _z, int nz, float H);
int yPointIndex(const float _y, int ny, float W);
fcoord getSlownessGradient(const float _x, const float _z, float *slowness, icoord size);
float qMulGradU1(const float _x, const float _z, const float _angle, float *slowness, icoord size);
float greenTwoP(const float _so, const float _slow, const float _sL, int nRay, fcoord s, fcoord r, float *slowness, icoord size);
float qatso(const float _so, const float _angle, int nRay, fcoord s, fcoord r, fcoord *rayReference3D, float *slowness, icoord size, float uo);
float slownessA(float *slowness, icoord size, float _x, float _y, float _z);
float getdT2(const float _x, const float _z, const float so, const float _angle, const float _ds, int nRay, fcoord s, fcoord r, fcoord *rayReference3D, float *slowness, icoord size, float uo);
float greenIntP(const float _so, const float _s, const float _sL, float *slowness, icoord size, int nRay, fcoord r, fcoord s);
float secondDerivativeU1(float *slowness, icoord size, const float _x, const float _z, const float _angle, fcoord s, fcoord r);
int calculatePerturbedRay(fcoord *rayPerturbed3D, fcoord s, fcoord r, int nRay, fcoord *rayReference3D, float *slowness, icoord size, float uo);
float angle2qx(const float _angle);
float angle2qz(const float _angle);
float ModelInterpolation_slowness2D(float *slowness, icoord size, const float _x, const float _z);
float ModelInterpolation_slowness3D(float *slowness, icoord size, const float _x, const float _z, const float _y);
void applyMovingAverageFilter(float *slowness, icoord size, int window, int dim, float *averageModel);
#define lGradient 1
#define EPSMIN 0.1
#define minValueGradient 1e-10
#define PI 3.1514926535
#define minValueSecondDerivativeU1 1e-6
#define DPHI_ANGLE 1.0 // 0.5
int getWaveParameter(float *slowness, icoord size, float dgrid, fcoord s, fcoord r, rayPar ray, fcoord *T, float *Jr)
{
static int first=1;
float *smooth;
float T0, T1, T2;
float uo, u1, lengthRefRay;
float x, y, z;
float dx, dy, dz, dl, so, ds;
float angle;
float dQdPhi, J, greentmp;
int nRayTmp, error, i;
fcoord *rayReference3D;
T0 = T1 = T2 = 0;
J = 1;
error = 0;
nRayTmp = getnRay(size, s, r, dgrid, ray.nray);
//fprintf(stderr,"Calling getnRay gives nRayTmp=%d nRayStep=%d\n", nRayTmp, nRayStep);
rayReference3D = (fcoord *)calloc(nRayTmp,sizeof(fcoord));
traceTwoPoint(s, r, nRayTmp, rayReference3D);
dx = rayReference3D[nRayTmp-1].x - rayReference3D[0].x;
dy = rayReference3D[nRayTmp-1].y - rayReference3D[0].y;
dz = rayReference3D[nRayTmp-1].z - rayReference3D[0].z;
lengthRefRay = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2));
angle = takeOffAngle(s, r);
if ((lengthRefRay <= 0) || (nRayTmp <= 1))
return(-1);
uo = referenceSlowness(slowness, size, nRayTmp, r, s);
T0 = lengthRefRay*uo;
ds = lengthRefRay/(nRayTmp-1);
J = lengthRefRay;
dQdPhi = 0;
for (i = 0; i < nRayTmp-1; i++)
{
x = 0.5*(rayReference3D[i+1].x + rayReference3D[i].x);
y = 0.5*(rayReference3D[i+1].y + rayReference3D[i].y);
z = 0.5*(rayReference3D[i+1].z + rayReference3D[i].z);
u1 = slownessA(slowness, size, x, z, y) - uo;
dx = rayReference3D[i+1].x - rayReference3D[i].x;
dy = rayReference3D[i+1].y - rayReference3D[i].y;
dz = rayReference3D[i+1].z - rayReference3D[i].z;
dl = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2));
T1 += dl*u1;
so = i*ds;
if (ray.useT2 != 0)
T2 += getdT2(x, z, so, angle, ds, nRayTmp, s, r, rayReference3D, slowness, size, uo);
/*if (ray.geomspread != 0) {
if (so <= 0) {
dQdPhi = 0;
}
else {
greentmp = 0;
if (so <= lengthRefRay) greentmp = (lengthRefRay - so)/uo;
dQdPhi += greentmp*secondDerivativeU1(slowness, size, x, z, angle, r, s)*ds/so;
}
}*/
}
if (ray.useT2)
T2 *= 0.5;
T->x = T0;
T->y = T1;
T->z = T2;
// The geometrical spreading factor
if (ray.geomspread)
{
J += dQdPhi;
if (J == 0)
J = 1;
if (J < 0)
{
error = -1; //snegativeGeometricalSpreadingFactor;
J = fabs(J);
}
}
if (size.y == 1) {
J = sqrt(J);
}
*Jr = J;
free(rayReference3D);
return(error);
}
int getnRay(icoord size, fcoord s, fcoord r, float dx, int nRayStep)
{
int dn, nRayTmp;
float dl, dr;
H = (size.z-1)*dx;
L = (size.x-1)*dx;
W = (size.y-1)*dx;
if (H!=0.0) iH = 1.0/H;
if (L!=0.0) iL = 1.0/L;
if (W!=0.0) iW = 1.0/W;
if (size.y == 1) { // 2D model
dn = (size.x + size.z)/2;
dl = sqrt(pow(L, 2) + pow(H, 2))/dn;
dr = sqrt(pow(r.x-s.x, 2) + pow(r.z-s.z, 2));
}
else { // 3D model
dn = (size.x + size.z + size.y)/3;
dl = sqrt(pow(L, 2) + pow(H, 2) + pow(W, 2))/dn;
dr = sqrt(pow(r.x-s.x, 2) + pow(r.z-s.z, 2) + pow(r.y-s.y, 2));
}
nRayTmp = MIN(300,dr*nRayStep/dl);
//fprintf(stderr,"getnRay: gives nRayTmp=%d dr=%f dl=%f\n", nRayTmp, dr, dl);
if (nRayTmp <= nRayStep)
nRayTmp = nRayStep;
return nRayTmp;
}
int traceTwoPoint(fcoord s, fcoord r, int nRay, fcoord *rayReference3D)
{
float x, y, z;
int i;
for (i = 0; i < nRay; i++)
{
x = s.x + (r.x - s.x)*i/(nRay-1);
y = s.y + (r.y - s.y)*i/(nRay-1);
z = s.z + (r.z - s.z)*i/(nRay-1);
rayReference3D[i].z=z;
rayReference3D[i].x=x;
rayReference3D[i].y=y;
}
return 0;
}
int calculatePerturbedRay(fcoord *rayPerturbed3D, fcoord s, fcoord r, int nRay, fcoord *rayReference3D, float *slowness, icoord size, float uo)
{
float si, sl, deltaS, gso, angle, qx, qz;
int i;
sl = sqrt(pow((r.x-s.x), 2) + pow((r.y-s.y), 2) + pow((r.z-s.z), 2));
if ((sl <= 0) || (nRay <= 1))
return 0;
deltaS = sl/(nRay-1);
angle = takeOffAngle(s, r);
qx = angle2qx(angle);
qz = angle2qz(angle);
for (i = 0; i < nRay; i++)
{
si = i*deltaS;
gso = qatso(si, angle, nRay, s, r, rayReference3D, slowness, size, uo);
rayPerturbed3D[i].x = rayReference3D[i].x + qx*gso;
rayPerturbed3D[i].z = rayReference3D[i].z + qz*gso;
rayPerturbed3D[i].y = rayReference3D[i].y;
}
return 0;
}
float takeOffAngle(fcoord s, fcoord r)
{
float angle = 0;
if ((s.x == r.x) && (s.z == r.z))
angle = PI/2;
else if ((s.x <= r.x) && (s.z < r.z))
angle = atan(fabs(r.x-s.x)/fabs(r.z-s.z));
else if ((s.x < r.x) && (s.z >= r.z))
angle = PI/2 + atan(fabs(r.z-s.z)/fabs(r.x-s.x));
else if ((s.x >= r.x) && (s.z > r.z))
angle = PI + atan(fabs(r.x-s.x)/fabs(r.z-s.z));
else if ((s.x > r.x) && (s.z <= r.z))
angle = 3*PI/2 + atan(fabs(r.z-s.z)/fabs(r.x-s.x));
return (angle);
}
float angle2qx(const float _angle)
{
float qx = 0;
if ((_angle >= 0) && (_angle < PI/2))
qx = -cos(_angle);
else if ((_angle >= PI/2) && (_angle < PI))
qx = sin(_angle - PI/2);
else if ((_angle >= PI) && (_angle < 3*PI/2))
qx = cos(_angle - PI);
else if ((_angle >= 3*PI/2) && (_angle <= 2*PI))
qx = -sin(_angle - 3*PI/2);
return (qx);
}
float angle2qz(const float _angle)
{
float qz = 0;
if ((_angle >= 0) && (_angle < PI/2))
qz = sin(_angle);
else if ((_angle >= PI/2) && (_angle < PI))
qz = cos(_angle - PI/2);
else if ((_angle >= PI) && (_angle < 3*PI/2))
qz = -sin(_angle - PI);
else if ((_angle >= 3*PI/2) && (_angle <= 2*PI))
qz = -cos(_angle - 3*PI/2);
return (qz);
}
// Sofar used in 2D only
float qatso(const float _so, const float _angle, int nRay, fcoord s, fcoord r, fcoord *rayReference3D, float *slowness, icoord size, float uo)
{
float slow, sl, deltaS, x, z;
float qatsol;
float greenTwoP = 0;
int i;
float qMulGradU1;
fcoord slownessGradient;
float gradu1x, gradu1z;
float qx, qz;
sl = sqrt(pow((r.x-s.x),2) + pow((r.z-s.z),2) + pow((r.y-s.y),2));
if ((sl <= 0) || (nRay <= 1))
{
return 0;
}
deltaS = sl/(nRay-1);
// uo = referenceSlowness(slowness, size, nRay, r, s);
qatsol = 0;
for (i = 0; i < nRay; i++)
{
slow = i*deltaS;
x = rayReference3D[i].x;
z = rayReference3D[i].z;
if (slow <= _so)
greenTwoP = -(1 - _so/sl)*slow/uo;
else
greenTwoP = -_so*(1-slow/sl)/uo;
slownessGradient = getSlownessGradient(x, z, slowness, size);
gradu1x = slownessGradient.x;
gradu1z = slownessGradient.z;
if ((_angle >= 0) && (_angle < PI/2)) {
qx = -cos(_angle);
qz = sin(_angle);
}
else if ((_angle >= PI/2) && (_angle < PI)) {
qx = sin(_angle - PI/2);
qz = cos(_angle - PI/2);
}
else if ((_angle >= PI) && (_angle < 3*PI/2)) {
qx = cos(_angle - PI);
qz = -sin(_angle - PI);
}
else if ((_angle >= 3*PI/2) && (_angle <= 2*PI)) {
qx = -sin(_angle - 3*PI/2);
qz = -cos(_angle - 3*PI/2);
}
qMulGradU1 = qx*gradu1x + qz*gradu1z;
qatsol += greenTwoP*qMulGradU1*deltaS;
}
return(qatsol);
}
float getdT2(const float _x, const float _z, const float _so, const float _angle, const float _ds, int nRay, fcoord s, fcoord r, fcoord *rayReference3D, float *slowness, icoord size, float uo)
{
float T2 = 0;
float qatsol;
float qMulGradU1l;
// fprintf(stderr,"getdT2: calling qatso nRay=%d\n",nRay);
qatsol = qatso(_so, _angle, nRay, s, r, rayReference3D, slowness, size, uo);
// fprintf(stderr,"getdT2: calling qMulGradU1\n");
qMulGradU1l = qMulGradU1(_x, _z, _angle, slowness, size);
T2 = qatsol*qMulGradU1l*_ds;
return(T2);
}
float greenTwoP(const float _so, const float _slow, const float _sL, int nRay, fcoord s, fcoord r, float *slowness, icoord size)
{
float greenTwoP = 0;
float uo = referenceSlowness(slowness, size, nRay, r, s);
// fprintf(stderr,"greenTwoP: slowness = %f nRay=%d\n",uo,nRay);
if (_sL <= 0)
{
return(0);
}
if (_slow <= _so)
greenTwoP = -(1 - _so/_sL)*_slow/uo;
else
greenTwoP = -_so*(1-_slow/_sL)/uo;
return(greenTwoP);
}
float qMulGradU1(const float _x, const float _z, const float _angle, float *slowness, icoord size)
{
float qMulGradU1;
float gradu1x, gradu1z;
float qx, qz;
fcoord slownessGradient;
slownessGradient = getSlownessGradient(_x, _z, slowness, size);
gradu1x = slownessGradient.x;
gradu1z = slownessGradient.z;
qx = angle2qx(_angle);
qz = angle2qz(_angle);
qMulGradU1 = qx*gradu1x + qz*gradu1z;
return(qMulGradU1);
}
float referenceSlowness(float *slowness, icoord size, int nRay, fcoord r, fcoord s)
{
float x, y, z;
float uo = 0;
int i;
for (i = 0; i < nRay; i++)
{
x = s.x + (r.x - s.x)*i/(nRay-1);
z = s.z + (r.z - s.z)*i/(nRay-1);
if (size.y == 1) // 2D
uo += ModelInterpolation_slowness2D(slowness, size, x, z);
else
{
y = s.y + (r.y - s.y)*i/(nRay-1);
uo += ModelInterpolation_slowness3D(slowness, size, x, z, y);
}
}
uo /= nRay;
return(uo);
}
fcoord getSlownessGradient(const float _x, const float _z, float *slowness, icoord size)
{
float dx, dz, x1, x2, z1, z2;
float slow2, slow1;
float gradu1x, gradu1z;
fcoord slownessGradient;
dx = lGradient*L/(size.x-1);
dz = lGradient*H/(size.z-1);
x1 = _x-dx;
x2 = _x+dx;
if (x1 <= 0)
x1 = EPSMIN;
if (x2 >= L)
x2 = L - EPSMIN;
if (size.y == 1)
{
slow1 = ModelInterpolation_slowness2D(slowness, size, x1, _z);
slow2 = ModelInterpolation_slowness2D(slowness, size, x2, _z);
}
else
{
slow1 = ModelInterpolation_slowness3D(slowness, size, x1, _z, 0);
slow2 = ModelInterpolation_slowness3D(slowness, size, x2, _z, 0);
}
if (fabs(slow2-slow1) < minValueGradient)
gradu1x = 0;
else
gradu1x = (slow2 - slow1)/(x2-x1);
z1 = _z-dz;
z2 = _z+dz;
if (z1 <= 0)
z1 = EPSMIN;
if (z2 >= H)
z2 = H - EPSMIN;
if (size.y == 1)
{
slow1 = ModelInterpolation_slowness2D(slowness, size, _x, z1);
slow2 = ModelInterpolation_slowness2D(slowness, size, _x, z2);
}
else
{
slow1 = ModelInterpolation_slowness3D(slowness, size, _x, z1, 0);
slow2 = ModelInterpolation_slowness3D(slowness, size, _x, z2, 0);
}
if (fabs(slow2-slow1) < minValueGradient)
gradu1z = 0;
else
gradu1z = (slow2 - slow1)/(z2-z1);
slownessGradient.x=gradu1x;
slownessGradient.z=gradu1z;
slownessGradient.y=0;
return(slownessGradient);
}
int xPointIndex(const float _x, int nx, float L)
{
int i;
if (_x <= 0)
return(0);
if (_x >= L)
i = nx - 1;
else
{
if (0 < L)
i = _x*nx*iL;
else
i = 0;
}
return(i);
}
int zPointIndex(const float _z, int nz, float H)
{
int i;
if (_z <= 0) return(0);
if (_z >= H)
i = nz - 1;
else
{
if (0 < H)
i = _z*nz*iH;
else
i = 0;
}
return(i);
}
int yPointIndex(const float _y, int ny, float W)
{
int i;
if (_y <= -0.5*W)
return(0);
if (_y >= 0.5*W)
i = ny - 1;
else
{
if (0 < W)
i = ny*(_y*iW + 0.5);
else
i = 0;
}
return(i);
}
float ModelInterpolation_slowness2D(float *slowness, icoord size, const float _x, const float _z)
{
float slow;
float f11, f12, f21, f22;
float t, j;
float x1, x2;
float z1, z2;
int nx, nz, ix, iz, ixMin, ixMax, izMin, izMax;
int ixCoordinate, izCoordinate;
slow = f11 = f12 = f21 = f22 = 0;
nx = size.x;
nz = size.z;
ixCoordinate = (int)(_x*nx)*iL;
if (ixCoordinate >= nx)
{
x1 = (float) L*(nx-1)/nx;
x2 = (float) L;
}
else if (ixCoordinate <= 0)
{
x1 = 0;
x2 = (float) L/nx;
}
else
{
x1 = (float) L*ixCoordinate/nx;
x2 = (float) L*(ixCoordinate+1)/nx;
}
izCoordinate = (int) _z*nz*iH;
if (izCoordinate >= nz)
{
z1 = (float) H*(nz-1)/nz;
z2 = (float) H;
}
else if (izCoordinate <= 0)
{
z1 = 0;
z2 = (float) H/nz;
}
else
{
z1 = (float) H*izCoordinate/nz;
z2 = (float) H*(izCoordinate+1)/nz;
}
ix = xPointIndex(_x, nx, L);
iz = zPointIndex(_z, nz, H);
if (ix == 0)
{
ixMin = 0;
ixMax = 1;
}
else if (ix == nx-1)
{
ixMin = nx-2;
ixMax = nx-1;
}
else
{
ixMin = ix-1;
ixMax = ix+1;
}
if (iz == 0)
{
izMin = 0;
izMax = 1;
}
else if (iz == nz-1)
{
izMin = nz-2;
izMax = nz-1;
}
else
{
izMin = iz-1;
izMax = iz+1;
}
f11 = slowness[ixMin*size.z+izMin];
f21 = slowness[ixMax*size.z+izMin];
f12 = slowness[ixMin*size.z+izMax];
f22 = slowness[ixMax*size.z+izMax];
t = (_x-x1)/(x2-x1);
j = (_z-z1)/(z2-z1);
slow = f11*(1-t)*(1-j) + f21*t*(1-j) + f12*(1-t)*j + f22*t*j;
return (slow);
}
float ModelInterpolation_slowness3D(float *slowness, icoord size, const float _x, const float _z, const float _y)
{
float slow;
float f111, f112, f212, f211;
float f121, f122, f222, f221;
float t, j, r;
float x1, x2;
float y1, y2;
float z1, z2;
int ix, iy, iz, ixMin, ixMax, iyMin, iyMax, izMin, izMax;
int nx, nz, ny, nxz;
int ixCoordinate, iyCoordinate, izCoordinate;
nx = size.x;
nz = size.z;
ny = size.y;
nxz = nx*nz;
slow = f111 = f112 = f212 = f211 = f121 = f122 = f222 = f221 = 0;
ixCoordinate = _x*nx*iL;
if (ixCoordinate >= nx)
ixCoordinate = nx;
if (ixCoordinate == nx)
{
x1 = (float) L*(ixCoordinate-1)/nx;
x2 = L;
}
else if (ixCoordinate <= 0)
{
x1 = 0;
x2 = (float) L/nx;
}
else
{
x1 = (float) L*ixCoordinate/nx;
x2 = (float) L*(ixCoordinate+1)/nx;
}
if (x1 < 0)
x1 = 0;
if (x1 > L)
x1 = L;
if (x2 < 0)
x2 = 0;
if (x2 > L)
x2 = L;
izCoordinate = _z*nz*iH;
if (izCoordinate >= nz)
izCoordinate = nz;
if (izCoordinate == nz)
{
z1 = H*(izCoordinate-1)/nz;
z2 = H;
}
else if (izCoordinate <= 0)
{
z1 = 0;
z2 = (float) H/nz;
}
else
{
z1 = (float) H*izCoordinate/nz;
z2 = (float) H*(izCoordinate+1)/nz;
}
if (z1 < 0)
z1 = 0;
if (z1 > H)
z1 = H;
if (z2 < 0)
z2 = 0;
if (z2 > H)
z2 = H;
iyCoordinate = ny*(_y*iW + 0.5);
if (iyCoordinate >= ny)
iyCoordinate = ny;
if (iyCoordinate == ny)
{
y1 = (float) W*(iyCoordinate-1-0.5*ny)/ny;
y2 = 0.5*W;
}
else if (iyCoordinate <= 0)
{
y1 = -0.5*W;
y2 = (float) W*(1-0.5*ny)/ny;
}
else
{
y1 = (float) W*(iyCoordinate-0.5*ny)/ny;
y2 = (float) W*(iyCoordinate+1-0.5*ny)/ny;
}
if (y1 < -0.5*W)
y1 = -0.5*W;
if (y1 > 0.5*W)
y1 = 0.5*W;
if (y2 < -0.5*W)
y2 = -0.5*W;
if (y2 > 0.5*W)
y2 = 0.5*W;
ix = xPointIndex(_x, size.x, L);
iy = yPointIndex(_y, size.y, W);
iz = zPointIndex(_z, size.z, H);
if (ix == 0)
{
ixMin = 0;
ixMax = 1;
}
else if (ix == nx-1)
{
ixMin = nx-2;
ixMax = nx-1;
}
else
{
ixMin = ix-1;
ixMax = ix+1;
}
if (iz == 0)
{
izMin = 0;
izMax = 1;
}
else if (iz == nz-1)
{
izMin = nz-2;
izMax = nz-1;
}
else
{
izMin = iz-1;
izMax = iz+1;
}
if (iy == 0)
{
iyMin = 0;
iyMax = 1;
}
else if (iy == ny-1)
{
iyMin = ny-2;
iyMax = ny-1;
}
else
{
iyMin = iy-1;
iyMax = iy+1;
}
nxz = nx*nz;
f111 = slowness[iyMin*nxz+ixMin*nz+izMin];
f211 = slowness[iyMax*nxz+ixMin*nz+izMin];
f121 = slowness[iyMin*nxz+ixMax*nz+izMin];
f221 = slowness[iyMax*nxz+ixMax*nz+izMin];
f112 = slowness[iyMin*nxz+ixMin*nz+izMax];
f212 = slowness[iyMax*nxz+ixMin*nz+izMax];
f122 = slowness[iyMin*nxz+ixMax*nz+izMax];
f222 = slowness[iyMax*nxz+ixMax*nz+izMax];
// cout << "slowness3D 6 " << endl;
r = (_z-z1)/(z2-z1);
t = (_x-x1)/(x2-x1);
j = (_y-y1)/(y2-y1);
slow = f111*(1-t)*(1-j)*(1-r) + f112*(1-t)*(1-j)*r + f211*t*(1-j)*(1-r) + f212*t*(1-j)*r + f121*(1-t)*j*(1-r) + f122*(1-t)*j*r + f222*t*j*r + f221*t*j*(1-r);
slow = f111*(1-r)*(1-t)*(1-j) + f112*(1-r)*(1-t)*j + f211*r*(1-t)*(1-j) + f212*r*(1-t)*j + f121*(1-r)*t*(1-j) + f122*(1-r)*t*j + f222*r*t*j + f221*r*t*(1-j);
// if (slow != slow)
/*
if (slow <= 0)
{
cout << " ModelInterpolation::slowness3D " << 1/slow << " " << 1/f111 << " " << 1/f112 << " " << 1/f211 << " " << 1/f212 << " " << 1/f121 << " " << 1/f122 << " " << 1/f222 << " " << 1/f211 << " " << r << " " << t << " " << j << " " << ixCoordinate << " " << x1 << " " << x2 << " " << _x << " " << nx << " " << L << endl;
cout << " ModelInterpolation::slowness3D, x1, x2 = " << x1 << " " << x2 << endl;
cout << " ModelInterpolation::slowness3D, y1, y2 = " << y1 << " " << y2 << endl;
cout << " ModelInterpolation::slowness3D, z1, z2 = " << z1 << " " << z2 << " " << _z << endl;
exit(EXIT_FAILURE);
}
*/
return (slow);
}
float slownessA(float *slowness, icoord size, float _x, float _z, float _y)
{
float slow;
if (size.y == 1)
slow = ModelInterpolation_slowness2D(slowness, size, _x, _z);
else
slow = ModelInterpolation_slowness3D(slowness, size, _x, _z, _y);
return(slow);
}
float greenIntP(const float _so, const float _s, const float _sL, float *slowness, icoord size, int nRay, fcoord r, fcoord s)
{
float greenIntP;
float uo = referenceSlowness(slowness, size, nRay, r, s);
if (_sL <= 0)
{
greenIntP = 0;
return(greenIntP);
}
if (_s <= _so)
greenIntP = (_so - _s)/uo;
else
greenIntP = 0;
return(greenIntP);
}
float secondDerivativeU1(float *slowness, icoord size, const float _x, const float _z, const float _angle, fcoord r, fcoord s)
{
float secondDerivativeU1 = 0;
float dphi, sl;
float qx, qz;
float dh, x1, z1, x2, z2;
dphi = DPHI_ANGLE*PI/180.0;
sl = sqrt(pow((r.x-s.x),2) + pow((r.z-s.z),2) + pow((r.y-s.y),2));
// Here qx and qz are perpendicular to the raz direction
qx = angle2qx(_angle);
qz = angle2qz(_angle);
dh = sl*tan(2*dphi);
x2 = _x + dh*qx;
z2 = _z + dh*qz;
x1 = _x - dh*qx;
z1 = _z - dh*qz;
if (x1 <= 0)
x1 = EPSMIN;
if (x1 >= L)
x1 = L - EPSMIN;
if (x2 <= 0)
x2 = EPSMIN;
if (x2 >= L)
x2 = L - EPSMIN;
if (z1 <= 0)
z1 = EPSMIN;
if (z1 >= H)
z1 = H - EPSMIN;
if (z2 <= 0)
z2 = EPSMIN;
if (z2 >= H)
z2 = H - EPSMIN;
secondDerivativeU1 = (slownessA(slowness, size, x2, z2, 0) + slownessA(slowness, size, x1, z1, 0) - 2*slownessA(slowness, size, _x, _z, 0))/(4*pow(dphi, 2));
if (fabs(secondDerivativeU1) <= minValueSecondDerivativeU1)
secondDerivativeU1 = 0;
return(secondDerivativeU1);
}
// Moving average filter
void applyMovingAverageFilter(float *slowness, icoord size, int window, int dim, float *averageModel)
{
float averageFilter;
int nsamp, iAverageX, iAverageY, iAverageZ;
int jWindowX, jWindowZ, jWindowY, ix, iy, iz, nw;
nw = window;
if (dim == 2) {
for (ix = 0; ix < size.x; ix++) {
for (iz = 0; iz < size.z; iz++) {
averageFilter = 0;
nsamp = 0;
for (jWindowX = -nw; jWindowX <= nw; jWindowX++) {
iAverageX = nw + ix + jWindowX;
// if (iAverageX < 0) iAverageX = 0;
// if (iAverageX > size.x-1) iAverageX = size.x-1;
for (jWindowZ = -nw; jWindowZ <= nw; jWindowZ++) {
iAverageZ = nw + iz + jWindowZ;
// if (iAverageZ < 0) iAverageZ = 0;
// if (iAverageZ > size.z-1) iAverageZ = size.z-1;
averageFilter += slowness[iAverageX*size.z+iAverageZ];
nsamp += 1;
}
}
if (nsamp > 0) {
averageFilter /= nsamp;
averageModel[ix*size.z+iz] = averageFilter;
}
else
averageModel[ix*size.z+iz] = slowness[(ix+nw)*size.z+iz+nw];
}
}
}
/* 3D ray-tracer not yet implemented
else {
for (iz = 0; iz < size.z; iz++) {
for (ix = 0; ix < size.x; ix++) {
for (iy = 0; iy < size.y; iy++) {
averageFilter = 0;
nsamp = 0;
for (jWindowZ = -window; jWindowZ <= window; jWindowZ++) {
iAverageZ = iz + jWindowZ;
if (iAverageZ < 0) iAverageZ = 0;
if (iAverageZ > size.z-1) iAverageZ = size.z-1;
for (jWindowX = -window; jWindowX <= window; jWindowX++) {
iAverageX = ix + jWindowX;
if (iAverageX < 0) iAverageX = 0;
if (iAverageX > size.x-1) iAverageX = size.x-1;
for (jWindowY = -window; jWindowY <= window; jWindowY++) {
iAverageY = iy + jWindowY;
if (iAverageY < 0) iAverageY = 0;
if (iAverageY > size.y-1) iAverageY = size.y-1;
averageFilter += slowness[iAverageZ+iAverageX*size.z+iAverageY*size.z*size.x];
nsamp += 1;
}
}
}
if (nsamp > 0) {
averageFilter /= nsamp;
averageModel[iz+ix*size.z+iy*size.z*size.x] = averageFilter;
}
else {
averageModel[iz+ix*size.z+iy*size.z*size.x] = slowness[iz+ix*size.z+iy*size.z*size.x];
}
}
}
}
}
*/
return;
}