diff --git a/raytime3d/getModelInfo3d.c b/raytime3d/getModelInfo3d.c new file mode 100644 index 0000000000000000000000000000000000000000..000200c5cf3bf2d917cfa892b07618aacc6d0d96 --- /dev/null +++ b/raytime3d/getModelInfo3d.c @@ -0,0 +1,125 @@ +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <math.h> +#include "par.h" +#include "segy.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)) + +/** +* reads gridded model file to compute minimum and maximum values and sampling intervals +* +* AUTHOR: +* Jan Thorbecke (janth@xs4all.nl) +* The Netherlands +**/ + +int getModelInfo3d(char *file_name, int *n1, int *n2, int *n3, float *d1, float *d2, float *d3, float *f1, float *f2, float *f3, int *axis, int verbose) +{ + FILE *fp; + size_t nread, trace_sz; + off_t bytes, pos; + int ret, i, one_shot, ntraces, model, i2, i3; + float *trace, scl; + segy hdr, lasthdr; + + if (file_name == NULL) return; + + fp = fopen( file_name, "r" ); + assert( fp != NULL); + nread = fread( &hdr, 1, TRCBYTES, fp ); + assert(nread == TRCBYTES); + ret = fseeko( fp, 0, SEEK_END ); + if (ret<0) perror("fseeko"); + bytes = ftello( fp ); + rewind(fp); + pos = bytes-hdr.ns*sizeof(float)-TRCBYTES; + ret = fseeko( fp, pos, SEEK_SET ); + if (ret<0) perror("fseeko"); + nread = fread( &lasthdr, 1, TRCBYTES, fp ); + assert(nread == TRCBYTES); + + if (hdr.trid == TRID_DEPTH) *axis = 1; /* samples are z-axis */ + else *axis = 0; /* sample direction respresents the x-axis */ + + if (hdr.scalco < 0) scl = 1.0/fabs(hdr.scalco); + else if (hdr.scalco == 0) scl = 1.0; + else scl = hdr.scalco; + + *n1 = hdr.ns; + *d1 = hdr.d1; + *d2 = hdr.d2; + *f1 = hdr.f1; + *f2 = hdr.gx*scl; + *f3 = hdr.gy*scl; + + if ( NINT(100.0*((*d1)/(*d2)))!=100 ) { + verr("dx and dz are different in the model !"); + } + if ( NINT(1000.0*(*d1))==0 ) { + if(!getparfloat("dx",d1)) { + verr("dx is equal to zero use parameter h= to set value"); + } + *d2 = *d1; + } + trace_sz = sizeof(float)*(*n1)+TRCBYTES; + ntraces = (int) (bytes/trace_sz); + + if (ntraces == 1) { /* 1D medium */ + model = 1; + *n2 = 1; + *n3 = 1; + *d2 = *d1; + *d3 = *d1; + } + else { /* find out if this is a 2D or 3D model */ + if (hdr.gy == lasthdr.gy) { /* assume 2D model */ + *n3 = 1; + *n2 = ntraces; + *d3 = *d1; + } + else { /* 3D model */ + /* find the number of traces in the x-direction */ + rewind(fp); + one_shot = 1; + i3=0; + while (one_shot) { + i2=0; + lasthdr.gy = hdr.gy; + while (hdr.gy == lasthdr.gy) { /* number of samples in x */ + pos = i2*trace_sz; + ret = fseeko( fp, pos, SEEK_SET ); + nread = fread( &hdr, 1, TRCBYTES, fp ); + if (nread==0) break; + i2++; + } + fprintf(stderr,"3D model gy=%d %d traces in x = %d\n", lasthdr.gy, i3, i2-1); + if (nread==0) break; + i3++; + } + *n3=i3; + *n2=ntraces/i3; + } + } + + if (verbose>2) { + vmess("For file %s", file_name); + vmess("nz=%d nx=%d ny=%d ", *n1, *n2, *n3); + vmess("dz=%f dx=%f *dy=%f", *d1, *d2, *d3); + vmess("zstart=%f xstart=%f ystart=%f", *f1, *f2, *f3); + if (*axis) vmess("sample represent z-axis\n"); + else vmess("sample represent x-axis\n"); + } + + + return 0; +} + diff --git a/raytime3d/getParameters3d.c b/raytime3d/getParameters3d.c new file mode 100644 index 0000000000000000000000000000000000000000..10522518777dc64deee8ade8ca0e0f0009936949 --- /dev/null +++ b/raytime3d/getParameters3d.c @@ -0,0 +1,347 @@ +#include<stdlib.h> +#include<stdio.h> +#include<math.h> +#include<assert.h> +#include"par.h" +#include"raytime3d.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)) + +/** +* +* The routine getParameters reads in all parameters to set up a FD modeling. +* Model and source parameters are used to calculate stability and dispersion relations +* Source and receiver positions are calculated and checked if they fit into the model. +* +* AUTHOR: +* Jan Thorbecke (janth@xs4all.nl) +* The Netherlands +**/ + +int getModelInfo3d(char *file_name, int *n1, int *n2, int *n3, float *d1, float *d2, float *d3, float *f1, float *f2, float *f3, int *axis, int verbose); + +int recvPar3d(recPar *rec, float sub_x0, float sub_z0, float sub_y0, float dx, float dz, float dy, int nx, int nz, int ny); + +int getParameters3d(modPar *mod, recPar *rec, srcPar *src, shotPar *shot, rayPar *ray, int verbose) +{ + int nx, nz, ny, nsrc, ix, iy, axis, is0; + int n1, n2, n3; + int idzshot, idxshot, idyshot; + int src_ix0, src_iz0, src_iy0, src_ix1, src_iz1, src_iy1; + float cp_min, cp_max; + float sub_x0,sub_z0,sub_y0; + float srcendx, srcendz, srcendy, dy, dx, dz; + float xsrc, zsrc, ysrc, dxshot, dzshot, dyshot; + float dxrcv,dzrcv,dyrcv,dxspread,dzspread,dyspread; + float xmax, zmax, ymax; + float xsrc1, xsrc2, zsrc1, zsrc2, ysrc1, ysrc2; + float *xsrca, *zsrca, *ysrca; + float rsrc, oxsrc, ozsrc, oysrc, dphisrc, ncsrc; + size_t nsamp; + int nxsrc, nzsrc, nysrc; + int is; + char *src_positions, *file_cp=NULL; + + if (!getparint("verbose",&verbose)) verbose=0; + + if (!getparstring("file_cp", &file_cp)) { + vwarn("file_cp not defined, assuming homogeneous model"); + } + + if (!getparstring("file_rcv",&rec->file_rcv)) rec->file_rcv="recv.su"; + if (!getparint("src_at_rcv",&src->src_at_rcv)) src->src_at_rcv=1; + + /* read model parameters, which are used to set up source and receivers and check stability */ + + getModelInfo3d(mod->file_cp, &n1, &n2, &n3, &dz, &dx, &dy, &sub_z0, &sub_x0, &sub_y0, &axis, verbose); + mod->dz = dz; + mod->dx = dx; + mod->dy = dx; + mod->nz = nz; + mod->nx = nx; + mod->ny = nx; + + /* origin of model in real (non-grid) coordinates */ + mod->x0 = sub_x0; + mod->z0 = sub_z0; + mod->y0 = sub_y0; + xmax = sub_x0+(nx-1)*dx; + zmax = sub_z0+(nz-1)*dz; + ymax = sub_y0+(ny-1)*dy; + + if (verbose) { + vmess("*******************************************"); + vmess("*************** model info ****************"); + vmess("*******************************************"); + vmess("nz = %8d nx = %8d ny = %8d", nz, nx, ny); + vmess("dz = %8.4f dx = %8.4f dy = %8.4f", dz, dx, dy); + vmess("zmin = %8.4f zmax = %8.4f", sub_z0, zmax); + vmess("xmin = %8.4f xmax = %8.4f", sub_x0, xmax); + vmess("ymin = %8.4f ymax = %8.4f", sub_y0, ymax); + } + + /* define the number and type of shots to model */ + /* each shot can have multiple sources arranged in different ways */ + + if (!getparfloat("ysrc",&ysrc)) ysrc=sub_y0+((ny-1)*dy)/2.0; + if (!getparfloat("xsrc",&xsrc)) xsrc=sub_x0+((nx-1)*dx)/2.0; + if (!getparfloat("zsrc",&zsrc)) zsrc=sub_z0; + if (!getparint("nyshot",&shot->ny)) shot->ny=1; + if (!getparint("nxshot",&shot->nx)) shot->nx=1; + if (!getparint("nzshot",&shot->nz)) shot->nz=1; + if (!getparfloat("dyshot",&dyshot)) dyshot=dy; + if (!getparfloat("dxshot",&dxshot)) dxshot=dx; + if (!getparfloat("dzshot",&dzshot)) dzshot=dz; + + shot->n = (shot->nx)*(shot->nz)*(shot->ny); + + if (shot->nx>1) { + idxshot=MAX(0,NINT(dxshot/dx)); + } + else { + idxshot=0.0; + } + if (shot->nz>1) { + idzshot=MAX(0,NINT(dzshot/dz)); + } + else { + idzshot=0.0; + } + if (shot->ny>1) { + idyshot=MAX(0,NINT(dyshot/dy)); + } + else { + idyshot=0.0; + } + + /* calculate the shot positions */ + + src_iy0=MAX(0,NINT((ysrc-sub_y0)/dy)); + src_iy0=MIN(src_iy0,ny); + src_ix0=MAX(0,NINT((xsrc-sub_x0)/dx)); + src_ix0=MIN(src_ix0,nx); + src_iz0=MAX(0,NINT((zsrc-sub_z0)/dz)); + src_iz0=MIN(src_iz0,nz); + srcendy=(shot->ny-1)*dyshot+ysrc; + srcendx=(shot->nx-1)*dxshot+xsrc; + srcendz=(shot->nz-1)*dzshot+zsrc; + src_iy1=MAX(0,NINT((srcendy-sub_y0)/dy)); + src_iy1=MIN(src_iy1,ny); + src_ix1=MAX(0,NINT((srcendx-sub_x0)/dx)); + src_ix1=MIN(src_ix1,nx); + src_iz1=MAX(0,NINT((srcendz-sub_z0)/dz)); + src_iz1=MIN(src_iz1,nz); + + shot->y = (int *)calloc(shot->ny,sizeof(int)); + shot->x = (int *)calloc(shot->nx,sizeof(int)); + shot->z = (int *)calloc(shot->nz,sizeof(int)); + for (is=0; is<shot->ny; is++) { + shot->y[is] = src_iy0+is*idyshot; + if (shot->y[is] > ny-1) shot->ny = is-1; + } + for (is=0; is<shot->nx; is++) { + shot->x[is] = src_ix0+is*idxshot; + if (shot->x[is] > nx-1) shot->nx = is-1; + } + for (is=0; is<shot->nz; is++) { + shot->z[is] = src_iz0+is*idzshot; + if (shot->z[is] > nz-1) shot->nz = is-1; + } + + /* check if source array is defined */ + + nysrc = countparval("xyrca"); + nxsrc = countparval("xsrca"); + nzsrc = countparval("zsrca"); + if (nxsrc != nzsrc || nxsrc != nysrc) { + verr("Number of sources in array xsrca (%d), zsrca(%d) are not equal",nxsrc, nzsrc); + } + + /* check if sources on a circle are defined */ + + if (getparfloat("rsrc", &rsrc)) { + if (!getparfloat("dphisrc",&dphisrc)) dphisrc=2.0; + if (!getparfloat("oysrc",&oysrc)) oysrc=0.0; + if (!getparfloat("oxsrc",&oxsrc)) oxsrc=0.0; + if (!getparfloat("ozsrc",&ozsrc)) ozsrc=0.0; + ncsrc = NINT(360.0/dphisrc); + src->n = nsrc; + + src->y = (int *)malloc(ncsrc*sizeof(int)); + src->x = (int *)malloc(ncsrc*sizeof(int)); + src->z = (int *)malloc(ncsrc*sizeof(int)); + + for (ix=0; ix<ncsrc; ix++) { + src->y[ix] = NINT((oysrc-sub_y0+rsrc*cos(((iy*dphisrc)/360.0)*(2.0*M_PI)))/dy); + src->x[ix] = NINT((oxsrc-sub_x0+rsrc*cos(((ix*dphisrc)/360.0)*(2.0*M_PI)))/dx); + src->z[ix] = NINT((ozsrc-sub_z0+rsrc*sin(((ix*dphisrc)/360.0)*(2.0*M_PI)))/dz); + if (verbose>4) fprintf(stderr,"Source on Circle: ysrc[%d]=%d xsrc[%d]=%d zsrc=%d\n", iy, src->y[iy], ix, src->x[ix], src->z[ix]); + } + + } + + /* TO DO propagate src_positions parameter and structure through code */ + + if (!getparstring("src_positions",&src_positions)) src_positions="single"; + src->random=0; + src->plane=0; + src->array=0; + src->single=0; + if (strstr(src_positions, "single")) src->single=1; + else if (strstr(src_positions, "array")) src->array=1; + else if (strstr(src_positions, "random")) src->random=1; + else if (strstr(src_positions, "plane")) src->plane=1; + else src->single=1; + + /* to maintain functionality of older parameters usage */ + if (!getparint("src_random",&src->random)) src->random=0; + if (!getparint("plane_wave",&src->plane)) src->plane=0; + + if (src->random) { + src->plane=0; + src->array=0; + src->single=0; + } + if (src->plane) { + src->random=0; + src->array=0; + src->single=0; + } + + + /* number of sources per shot modeling */ + + if (!getparint("src_window",&src->window)) src->window=0; + if (!getparint("distribution",&src->distribution)) src->distribution=0; + if (!getparfloat("amplitude", &src->amplitude)) src->amplitude=0.0; + if (src->random && nxsrc==0) { + if (!getparint("nsrc",&nsrc)) nsrc=1; + if (!getparfloat("ysrc1", &ysrc1)) ysrc1=sub_y0; + if (!getparfloat("ysrc2", &ysrc2)) ysrc2=ymax; + if (!getparfloat("xsrc1", &xsrc1)) xsrc1=sub_x0; + if (!getparfloat("xsrc2", &xsrc2)) xsrc2=xmax; + if (!getparfloat("zsrc1", &zsrc1)) zsrc1=sub_z0; + if (!getparfloat("zsrc2", &zsrc2)) zsrc2=zmax; + dyshot = ysrc2-ysrc1; + dxshot = xsrc2-xsrc1; + dzshot = zsrc2-zsrc1; + src->y = (int *)malloc(nsrc*sizeof(int)); + src->x = (int *)malloc(nsrc*sizeof(int)); + src->z = (int *)malloc(nsrc*sizeof(int)); + nsamp = 0; + + } + else if (nxsrc != 0) { + /* source array is defined */ + nsrc=nxsrc; + src->y = (int *)malloc(nsrc*sizeof(int)); + src->x = (int *)malloc(nsrc*sizeof(int)); + src->z = (int *)malloc(nsrc*sizeof(int)); + ysrca = (float *)malloc(nsrc*sizeof(float)); + xsrca = (float *)malloc(nsrc*sizeof(float)); + zsrca = (float *)malloc(nsrc*sizeof(float)); + getparfloat("ysrca", ysrca); + getparfloat("xsrca", xsrca); + getparfloat("zsrca", zsrca); + for (is=0; is<nsrc; is++) { + src->y[is] = NINT((ysrca[is]-sub_y0)/dy); + src->x[is] = NINT((xsrca[is]-sub_x0)/dx); + src->z[is] = NINT((zsrca[is]-sub_z0)/dz); + if (verbose>3) fprintf(stderr,"Source Array: ysrc[%d]=%f xsrc=%f zsrc=%f\n", is, ysrca[is], xsrca[is], zsrca[is]); + } + src->random = 1; + free(ysrca); + free(xsrca); + free(zsrca); + } + else { + if (src->plane) { if (!getparint("nsrc",&nsrc)) nsrc=1;} + else nsrc=1; + + if (nsrc > nx) { + vwarn("Number of sources used in plane wave is larger than "); + vwarn("number of gridpoints in X. Plane wave will be clipped to the edges of the model"); + nsrc = mod->nx; + } + + /* for a source defined on mutliple gridpoint calculate p delay factor */ + + src->y = (int *)malloc(nsrc*sizeof(int)); + src->x = (int *)malloc(nsrc*sizeof(int)); + src->z = (int *)malloc(nsrc*sizeof(int)); + is0 = -1*floor((nsrc-1)/2); + for (is=0; is<nsrc; is++) { + src->y[is] = is0 + is; + src->x[is] = is0 + is; + src->z[is] = 0; + } + + } + + src->n=nsrc; + + if (verbose) { + if (src->n>1) { + vmess("*******************************************"); + vmess("*********** source array info *************"); + vmess("*******************************************"); + vmess("Areal source array is defined with %d sources.",nsrc); + vmess("Memory requirement for sources = %.2f MB.",sizeof(float)*(nsamp/(1024.0*1024.0))); + } + if (src->random) { + vmess("Sources are placed at random locations in domain: "); + vmess(" x[%.2f : %.2f] z[%.2f : %.2f] ", xsrc1, xsrc2, zsrc1, zsrc2); + } + } + + /* define receivers */ + + if (!getparint("sinkdepth",&rec->sinkdepth)) rec->sinkdepth=0; + if (!getparint("sinkdepth_src",&src->sinkdepth)) src->sinkdepth=0; + if (!getparint("sinkvel",&rec->sinkvel)) rec->sinkvel=0; + if (!getparint("max_nrec",&rec->max_nrec)) rec->max_nrec=15000; + if (!getparfloat("dyspread",&dyspread)) dyspread=0; + if (!getparfloat("dxspread",&dxspread)) dxspread=0; + if (!getparfloat("dzspread",&dzspread)) dzspread=0; + if (!getparint("nt",&rec->nt)) rec->nt=1024; + + /* calculates the receiver coordinates */ + + recvPar3d(rec, sub_x0, sub_z0, sub_y0, dx, dz, dy, nx, nz, ny); + + if (verbose) { + if (rec->n) { + dyrcv = rec->yr[MIN(1,rec->n-1)]-rec->yr[0]; + dxrcv = rec->xr[MIN(1,rec->n-1)]-rec->xr[0]; + dzrcv = rec->zr[MIN(1,rec->n-1)]-rec->zr[0]; + vmess("*******************************************"); + vmess("************* receiver info ***************"); + vmess("*******************************************"); + vmess("ntrcv = %d nrcv = %d ", rec->nt, rec->n); + vmess("dzrcv = %f dxrcv = %f dyrcv = %f ", dzrcv, dxrcv, dyrcv); + vmess("Receiver array at coordinates: "); + vmess("zmin = %f zmax = %f ", rec->zr[0]+sub_z0, rec->zr[rec->n-1]+sub_z0); + vmess("xmin = %f xmax = %f ", rec->xr[0]+sub_x0, rec->xr[rec->n-1]+sub_x0); + vmess("ymin = %f ymax = %f ", rec->yr[0]+sub_y0, rec->yr[rec->n-1]+sub_y0); + vmess("which are gridpoints: "); + vmess("izmin = %d izmax = %d ", rec->z[0], rec->z[rec->n-1]); + vmess("ixmin = %d ixmax = %d ", rec->x[0], rec->x[rec->n-1]); + vmess("iymin = %d iymax = %d ", rec->y[0], rec->y[rec->n-1]); + fprintf(stderr,"\n"); + } + else { + vmess("*************** no receivers **************"); + } + } + + /* Ray tracing parameters */ + if (!getparint("smoothwindow",&ray->smoothwindow)) ray->smoothwindow=0; + if (!getparint("useT2",&ray->useT2)) ray->useT2=0; + if (!getparint("geomspread",&ray->geomspread)) ray->geomspread=1; + if (!getparint("nraystep",&ray->nray)) ray->nray=5; + + return 0; +} + diff --git a/raytime3d/raytime3d.c b/raytime3d/raytime3d.c index 73e57f41822da6bec2322f85b0b943e25afad73f..b1735d85dc72268229f9e5d3e9c0a93329e7b8c2 100644 --- a/raytime3d/raytime3d.c +++ b/raytime3d/raytime3d.c @@ -146,46 +146,44 @@ void main(int argc, char *argv[]) getParameters3d(&mod, &rec, &src, &shot, &ray, verbose); - /*---------------------------------------------------------------------------* * Open velocity file *---------------------------------------------------------------------------*/ - if (file_cp != NULL) { + if (mod.file_cp != NULL) { if (n2==1) { /* 1D model */ if(!getparint("nx",&nx)) verr("for 1D medium nx not defined"); if(!getparint("ny",&nx)) verr("for 1D medium ny not defined"); nz = n1; oz = f1; ox = ((nx-1)/2)*d1; oy = ((ny-1)/2)*d1; - dz = d1; dx = d1; dy = d1; } else if (n3==1) { /* 2D model */ if(!getparint("ny",&nx)) verr("for 2D medium ny not defined"); nz = n1; nx = n2; oz = f1; ox = f2; oy = ((ny-1)/2)*d1; - dz = d1; dx = d1; dy = d1; } else { /* Full 3D model */ nz = n1; nx = n2; nz = n3; oz = f1; ox = f2; oy = f3; - dz = d1; dx = d1; dy = d1; } - h = d1; + h = mod.dx; slow0 = (float *)malloc(nz*nx*ny*sizeof(float)); if (slow0 == NULL) verr("Out of memory for slow0 array!"); - readModel3d(file_cp, slow0, n1, n2, n3, nz, nx, ny, h, verbose); + readModel3d(mod.file_cp, slow0, n1, n2, n3, nz, nx, ny, h, verbose); if (verbose) vmess("h = %.2f nx = %d nz = %d ny = %d", h, nx, nz, ny); } else { - nxy = nx * ny; + if(!getparfloat("c",&c)) verr("c not defined"); + if(!getparfloat("h",&h)) verr("h not defined"); if(!getparint("nx",&nx)) verr("for homogenoeus medium nx not defined"); if(!getparint("ny",&nx)) verr("for homogenoeus medium ny not defined"); if(!getparint("nz",&nx)) verr("for homogenoeus medium nz not defined"); + nxy = nx * ny; oz = 0; ox = ((nx-1)/2)*d1; oy = ((ny-1)/2)*d1; slow0 = (float *)malloc(nx*nz*ny*sizeof(float)); @@ -264,7 +262,6 @@ void main(int argc, char *argv[]) for (i = 0; i < ny; i++) { hdrs[i].scalco = -1000; hdrs[i].scalel = -1000; -/* hdrs[i].offset = xi[0]*dx + is*ispr*dx - xsrc;*/ hdrs[i].sx = (int)(ox+xs*h)*1000; hdrs[i].sy = (int)(oy+ys*h)*1000; hdrs[i].gy = (int)(oy+i*d2)*1000; diff --git a/raytime3d/raytime3d.h b/raytime3d/raytime3d.h new file mode 100644 index 0000000000000000000000000000000000000000..9900d8b13315c9b5ec7662a053d8eb25973e7915 --- /dev/null +++ b/raytime3d/raytime3d.h @@ -0,0 +1,144 @@ +#include<stdlib.h> +#include<stdio.h> +#include<limits.h> +#include<float.h> +#include<math.h> + +#ifndef COMPLEX +typedef struct _complexStruct { /* complex number */ + float r,i; +} complex; +typedef struct _dcomplexStruct { /* complex number */ + double r,i; +} dcomplex; +#endif/* complex */ + + +typedef struct _icoord { /* 3D coordinate integer */ + int z; + int x; + int y; +} icoord; + +typedef struct _fcoord { /* 3D coordinate float */ + float z; + float x; + float y; +} fcoord; + +struct s_ecount { + int corner,corner_min,side; +}; + +typedef struct _receiverPar { /* Receiver Parameters */ + char *file_rcv; + int n; + int nt; + int max_nrec; + int *z; + int *x; + int *y; + float *zr; + float *xr; + float *yr; + int scale; + int sinkdepth; + int sinkvel; + float cp; + float rho; +} recPar; + +typedef struct _modelPar { /* Model Parameters */ + int sh; + char *file_cp; + float dz; + float dx; + float dy; + float dt; + float z0; + float x0; + float y0; + /* medium max/min values */ + float cp_min; + float cp_max; + int nz; + int nx; + int ny; +} modPar; + +typedef struct _waveletPar { /* Wavelet Parameters */ + char *file_src; /* general source */ + int nsrcf; + int nt; + int ns; + int nx; + int ny; + float dt; + float ds; + float fmax; + int random; + int seed; + int nst; + size_t *nsamp; +} wavPar; + +typedef struct _sourcePar { /* Source Array Parameters */ + int n; + int type; + int orient; + int *z; + int *x; + int *y; + int single; + int plane; + int circle; + int array; + int random; + int multiwav; + float angle; + float velo; + float amplitude; + int distribution; + int window; + int injectionrate; + int sinkdepth; + int src_at_rcv; /* Indicates that wavefield should be injected at receivers */ +} srcPar; + +typedef struct _shotPar { /* Shot Parameters */ + int n; + int ny; + int nx; + int nz; + int *z; + int *x; + int *y; +} shotPar; + +typedef struct _raypar { /* ray-tracing parameters */ + int smoothwindow; + int useT2; + int geomspread; + int nray; +} rayPar; + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +#define equal(x,y) !strcmp(x,y) +#define min2(a,b) (((a) < (b)) ? (a) : (b)) +#define max2(a,b) (((a) > (b)) ? (a) : (b)) + +#define Infinity FLT_MAX + +#if __STDC_VERSION__ >= 199901L + /* "restrict" is a keyword */ +#else +#define restrict +#endif + diff --git a/raytime3d/readModel3d.c b/raytime3d/readModel3d.c new file mode 100644 index 0000000000000000000000000000000000000000..e8f4f9a98148717742210409df1f2d6358982f77 --- /dev/null +++ b/raytime3d/readModel3d.c @@ -0,0 +1,87 @@ +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <math.h> +#include "segy.h" +#include "par.h" +#include "raytime3d.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)) + +/** +* Reads gridded model files and compute from them medium parameters used in the FD kernels. +* The files read in contain the P (and S) wave velocity and density. +* The medium parameters calculated are lambda, mu, lambda+2mu, and 1/ro. +* +* AUTHOR: +* Jan Thorbecke (janth@xs4all.nl) +* The Netherlands +**/ + +int readModel3d(char *file_name, float *slowness, int n1, int n2, int n3, int nz, int nx, int ny, float h, int verbose) +{ + FILE *fpcp; + size_t nread; + int i, j, k, tracesToDo; + int nxy, nxz; + float *tmp; + segy hdr; + + nxy = nx * ny; + tmp = (float *)malloc(n1*sizeof(float)); + +/* open files and read first header */ + + fpcp = fopen( file_name, "r" ); + assert( fpcp != NULL); + nread = fread(&hdr, 1, TRCBYTES, fpcp); + assert(nread == TRCBYTES); + assert(hdr.ns == n1); + + if (n2==1) { /* 1D model */ + nread = fread(&tmp[0], sizeof(float), hdr.ns, fpcp); + for (j = 0; j < nz; j++) { + for (k = 0; k < ny; k++) { + for (i = 0; i < nx; i++) { + slowness[j*nxy+k*nx+i] = h/tmp[j]; + } + } + } + } + else if (n3==1) { /* 2D model */ + for (i = 0; i < nx; i++) { + nread = fread(&tmp[0], sizeof(float), hdr.ns, fpcp); + for (j = 0; j < nz; j++) { + for (k = 0; k < ny; k++) { + slowness[j*nxy+k*nx+i] = h/tmp[j]; + } + } + nread = fread(&hdr, 1, TRCBYTES, fpcp); + } + } + else { /* Full 3D model */ + /* read all traces */ + for (k = 0; k < ny; k++) { + for (i = 0; i < nx; i++) { + nread = fread(&tmp[0], sizeof(float), hdr.ns, fpcp); + for (j = 0; j < nz; j++) { + slowness[j*nxy+k*nx+i] = h/tmp[j]; + } + nread = fread(&hdr, 1, TRCBYTES, fpcp); + } + } + } + + fclose(fpcp); + + return 0; +} + + diff --git a/raytime3d/recvPar3d.c b/raytime3d/recvPar3d.c new file mode 100644 index 0000000000000000000000000000000000000000..65dd258e5c95c0086fbdbf247ecfd084b22647c8 --- /dev/null +++ b/raytime3d/recvPar3d.c @@ -0,0 +1,616 @@ +#include <stdio.h> +#include <assert.h> +#include <math.h> + +#include "raytime3d.h" +#include "par.h" + +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5)) + +/** +* Calculates the receiver positions based on the input parameters +* +* AUTHOR: +* Jan Thorbecke (janth@xs4all.nl) +* +* Ammendments: +* Max Holicki changing the allocation receiver array (2-2016) +* The Netherlands +**/ + + +void name_ext(char *filename, char *extension); + +int recvPar3d(recPar *rec, float sub_x0, float sub_z0, float sub_y0, float dx, float dz, float dy, int nx, int nz, int ny) +{ + float *yrcv1, *yrcv2, *xrcv1, *xrcv2, *zrcv1, *zrcv2; + int i, ix, iy, ir, verbose; + float dxrcv, dzrcv, dyrcv, *dxr, *dzr, *dyr; + float rrcv, dphi, oxrcv, ozrcv, oyrcv, arcv; + double circ, h, a, b, e, s, xr, zr, yr, dr, srun, phase; + float xrange, zrange, yrange, sub_x1, sub_z1, sub_y1; + int Nx1, Nx2, Nz1, Nz2, Ny1, Ny2, Ndx, Ndz, Ndy, iarray, nrec, nh; + int nxrcv, nzrcv, nyrcv, ncrcv, nrcv, ntrcv, *nlrcv; + float *xrcva, *zrcva, *yrcva; + char* rcv_txt; + FILE *fp; + + if (!getparint("verbose", &verbose)) verbose = 0; + + /* Calculate Model Dimensions */ + sub_x1=sub_x0+(nx-1)*dx; + sub_z1=sub_z0+(nz-1)*dz; + sub_y1=sub_y0+(ny-1)*dy; + +/* Compute how many receivers are defined and then allocate the receiver arrays */ + + /* Receivers on a Circle */ + if (getparfloat("rrcv",&rrcv)) { + if (!getparfloat("dphi",&dphi)) dphi=2.0; + ncrcv=NINT(360.0/dphi); + if (verbose) vmess("Total number of receivers on a circle: %d",ncrcv); + } + else { + ncrcv=0; + } + + /* Receivers from a File */ + ntrcv=0; + if (!getparstring("rcv_txt",&rcv_txt)) rcv_txt=NULL; + if (rcv_txt!=NULL) { + /* Open text file */ + fp=fopen(rcv_txt,"r"); + assert(fp!=NULL); + /* Get number of lines */ + while (!feof(fp)) if (fgetc(fp)=='\n') ntrcv++; + fseek(fp,-1,SEEK_CUR); + if (fgetc(fp)!='\n') ntrcv++; /* Checks if last line terminated by /n */ + if (verbose) vmess("Number of receivers in rcv_txt file: %d",ntrcv); + rewind(fp); + } + + /* Receiver Array */ + nyrcv=countparval("yrcva"); + nxrcv=countparval("xrcva"); + nzrcv=countparval("zrcva"); + if (nxrcv!=nzrcv) verr("Number of receivers in array xrcva (%d), zrcva(%d) are not equal",nxrcv,nzrcv); + if (nxrcv!=nyrcv) verr("Number of receivers in array xrcva (%d), yrcva(%d) are not equal",nxrcv,nyrcv); + if (verbose&&nxrcv) vmess("Total number of array receivers: %d",nxrcv); + + /* Linear Receiver Arrays */ + Ny1 = countparval("yrcv1"); + Ny2 = countparval("yrcv2"); + Nx1 = countparval("xrcv1"); + Nx2 = countparval("xrcv2"); + Nz1 = countparval("zrcv1"); + Nz2 = countparval("zrcv2"); + if (Ny1!=Ny2) verr("Number of receivers starting points in 'yrcv1' (%d) and number of endpoint in 'yrcv2' (%d) are not equal",Ny1,Ny2); + if (Nx1!=Nx2) verr("Number of receivers starting points in 'xrcv1' (%d) and number of endpoint in 'xrcv2' (%d) are not equal",Nx1,Nx2); + if (Nz1!=Nz2) verr("Number of receivers starting points in 'zrcv1' (%d) and number of endpoint in 'zrcv2' (%d) are not equal",Nz1,Nz2); + if (Nx1!=Nz2) verr("Number of receivers starting points in 'xrcv1' (%d) and number of endpoint in 'zrcv2' (%d) are not equal",Nx1,Nz2); + if (Nx1!=Ny2) verr("Number of receivers starting points in 'xrcv1' (%d) and number of endpoint in 'yrcv2' (%d) are not equal",Nx1,Ny2); + + rec->max_nrec=ncrcv+ntrcv+nxrcv; + + /* no receivers are defined use default linear array of receivers on top of model */ + if (!rec->max_nrec && Nx1==0) Nx1=1; // Default is to use top of model to record data + + if (Nx1) { + /* Allocate Start & End Points of Linear Arrays */ + yrcv1=(float *)malloc(Nx1*sizeof(float)); + yrcv2=(float *)malloc(Nx1*sizeof(float)); + xrcv1=(float *)malloc(Nx1*sizeof(float)); + xrcv2=(float *)malloc(Nx1*sizeof(float)); + zrcv1=(float *)malloc(Nx1*sizeof(float)); + zrcv2=(float *)malloc(Nx1*sizeof(float)); + if (!getparfloat("yrcv1",yrcv1)) yrcv1[0]=sub_y0; + if (!getparfloat("yrcv2",yrcv2)) yrcv2[0]=sub_y1; + if (!getparfloat("xrcv1",xrcv1)) xrcv1[0]=sub_x0; + if (!getparfloat("xrcv2",xrcv2)) xrcv2[0]=sub_x1; + if (!getparfloat("zrcv1",zrcv1)) zrcv1[0]=sub_z0; + if (!getparfloat("zrcv2",zrcv2)) zrcv2[0]=zrcv1[0]; + + /* check if receiver arrays fit into model */ + for (iarray=0; iarray<Nx1; iarray++) { + yrcv1[iarray] = MAX(sub_y0, yrcv1[iarray]); + yrcv1[iarray] = MIN(sub_y0+ny*dy,yrcv1[iarray]); + yrcv2[iarray] = MAX(sub_y0, yrcv2[iarray]); + yrcv2[iarray] = MIN(sub_y0+ny*dy,yrcv2[iarray]); + + xrcv1[iarray] = MAX(sub_x0, xrcv1[iarray]); + xrcv1[iarray] = MIN(sub_x0+nx*dx,xrcv1[iarray]); + xrcv2[iarray] = MAX(sub_x0, xrcv2[iarray]); + xrcv2[iarray] = MIN(sub_x0+nx*dx,xrcv2[iarray]); + + zrcv1[iarray] = MAX(sub_z0, zrcv1[iarray]); + zrcv1[iarray] = MIN(sub_z0+nz*dz,zrcv1[iarray]); + zrcv2[iarray] = MAX(sub_z0, zrcv2[iarray]); + zrcv2[iarray] = MIN(sub_z0+nz*dz,zrcv2[iarray]); + } + + /* Crop to Fit Model */ +/* Max's addtion still have to check if it has the same fucntionality */ + for (iarray=0;iarray<Nx1;iarray++) { + if (yrcv1[iarray]<sub_y0) { + if (yrcv2[iarray]<sub_y0) { + verr("Linear array %d outside model bounds",iarray); + } + else { + vwarn("Cropping element %d of 'yrcv1' (%f) to model bounds (%f)",iarray,yrcv1[iarray],sub_y0); + yrcv1[iarray]=sub_y0; + } + } + else if (yrcv1[iarray] > sub_y1) { + verr("Linear array %d outside model bounds",iarray); + } + if ( (yrcv2[iarray] < yrcv1[iarray]) ) { + verr("Ill defined linear array %d, 'yrcv1' (%f) greater than 'yrcv2' (%f)",iarray,yrcv1[iarray],yrcv2[iarray]); + } + else if (yrcv2[iarray]>sub_y1) { + vwarn("Cropping element %d of 'yrcv2' (%f) to model bounds (%f)",iarray,yrcv2[iarray],sub_y1); + yrcv2[iarray]=sub_y1; + } + + if (xrcv1[iarray]<sub_x0) { + if (xrcv2[iarray]<sub_x0) { + verr("Linear array %d outside model bounds",iarray); + } + else { + vwarn("Cropping element %d of 'xrcv1' (%f) to model bounds (%f)",iarray,xrcv1[iarray],sub_x0); + xrcv1[iarray]=sub_x0; + } + } + else if (xrcv1[iarray] > sub_x1) { + verr("Linear array %d outside model bounds",iarray); + } + if ( (xrcv2[iarray] < xrcv1[iarray]) ) { + verr("Ill defined linear array %d, 'xrcv1' (%f) greater than 'xrcv2' (%f)",iarray,xrcv1[iarray],xrcv2[iarray]); + } + else if (xrcv2[iarray]>sub_x1) { + vwarn("Cropping element %d of 'xrcv2' (%f) to model bounds (%f)",iarray,xrcv2[iarray],sub_x1); + xrcv2[iarray]=sub_x1; + } + + if (zrcv1[iarray] < sub_z0) { + if (zrcv2[iarray] < sub_z0) { + verr("Linear array %d outside model bounds",iarray); + } + else { + vwarn("Cropping element %d of 'zrcv1' (%f) to model bounds (%f)",iarray,zrcv1[iarray],sub_z0); + zrcv1[iarray]=sub_z0; + } + } + else if (zrcv1[iarray] > sub_z1) { + verr("Linear array %d outside model bounds",iarray); + } + if ( (zrcv2[iarray] < zrcv1[iarray]) ) { + verr("Ill defined linear array %d, 'zrcv1' (%f) greater than 'zrcv2' (%f)",iarray,zrcv1[iarray],zrcv2[iarray]); + } + else if (zrcv2[iarray]>sub_z1) { + vwarn("Cropping element %d of 'xrcv2' (%f) to model bounds (%f)",iarray,zrcv2[iarray],sub_z1); + zrcv2[iarray]=sub_z1; + } + } + + /* Get Sampling Rates */ + Ndy = countparval("dyrcv"); + Ndx = countparval("dxrcv"); + Ndz = countparval("dzrcv"); + + dyr = (float *)malloc(Nx1*sizeof(float)); + dxr = (float *)malloc(Nx1*sizeof(float)); + dzr = (float *)malloc(Nx1*sizeof(float)); + if(!getparfloat("dyrcv", dyr)) dyr[0]=dy; + if(!getparfloat("dxrcv", dxr)) dxr[0]=dx; + if(!getparfloat("dzrcv", dzr)) dzr[0]=0.0; +/* TODO logic extended to 3D */ + if ( (Ndx<=1) && (Ndz==0) ){ /* default values are set */ + for (i=1; i<Nx1; i++) { + dxr[i] = dxr[0]; + dzr[i] = dzr[0]; + } + Ndx=1; + Ndz=1; + } + else if ( (Ndz==1) && (Ndx==0) ){ /* default values are set */ + for (i=1; i<Nx1; i++) { + dxr[i] = dxr[0]; + dzr[i] = dzr[0]; + } + Ndz=1; + Ndx=1; + } +/* end TODO */ + else { /* make sure that each array has dzrcv or dxrcv defined for each line or receivers */ + if (Ndx!=Ndz) { + verr("Number of 'dxrcv' (%d) is not equal to number of 'dzrcv' (%d) or 1",Ndx,Ndz); + } + if (Ndx!=Nx1 && Ndx!=1) { + verr("Number of 'dxrcv' (%d) is not equal to number of starting points in 'xrcv1' (%d) or 1",Ndx,Nx1); + } + if (Ndy!=Ndz) { + verr("Number of 'dyrcv' (%d) is not equal to number of 'dzrcv' (%d) or 1",Ndy,Ndz); + } + } + + /* check consistency of receiver steps */ + for (iarray=0; iarray<Ndy; iarray++) { + if (dyr[iarray]<0) { + dyr[i]=dy; + vwarn("'dyrcv' element %d (%f) is less than zero, changing it to %f'",iarray,dyr[iarray],dy); + } + } + for (iarray=0; iarray<Ndx; iarray++) { + if (dxr[iarray]<0) { + dxr[i]=dx; + vwarn("'dxrcv' element %d (%f) is less than zero, changing it to %f'",iarray,dxr[iarray],dx); + } + } + for (iarray=0;iarray<Ndz;iarray++) { + if (dzr[iarray]<0) { + dzr[iarray]=dz; + vwarn("'dzrcv' element %d (%f) is less than zero, changing it to %f'",iarray,dzr[iarray],dz); + } + } + for (iarray=0;iarray<Ndx;iarray++){ + if (dxr[iarray]==0 && dzr[iarray]==0) { + xrcv2[iarray]=xrcv1[iarray]; + dxr[iarray]=1.; + vwarn("'dxrcv' element %d & 'dzrcv' element 1 are both 0.",iarray+1); + vmess("Placing 1 receiver at (%d,%d)",xrcv1[iarray],zrcv1[iarray]); + } + } + for (iarray=0;iarray<Ndx;iarray++){ + if (xrcv1[iarray]==xrcv2[iarray] && dxr[iarray]!=0) { + dxr[iarray]=0.; + vwarn("Linear array %d: 'xrcv1'='xrcv2' and 'dxrcv' is not 0. Setting 'dxrcv'=0",iarray+1); + } + } + for (iarray=0;iarray<Ndx;iarray++){ + if (zrcv1[iarray]==zrcv2[iarray] && dzr[iarray]!=0.){ + dzr[iarray]=0.; + vwarn("Linear array %d: 'zrcv1'='zrcv2' and 'dzrcv' is not 0. Setting 'dzrcv'=0",iarray+1); + } + } + + /* Calculate Number of Receivers */ + nrcv = 0; + nlrcv=(int *)malloc(Nx1*sizeof(int)); + for (iarray=0; iarray<Nx1; iarray++) { + yrange = (yrcv2[iarray]-yrcv1[iarray]); + xrange = (xrcv2[iarray]-xrcv1[iarray]); + zrange = (zrcv2[iarray]-zrcv1[iarray]); + if (dyr[iarray] != 0.0) { + nlrcv[iarray] = NINT(fabs(yrange/dyr[iarray]))+1; + } + if (dxr[iarray] != 0.0) { + nlrcv[iarray] = NINT(fabs(xrange/dxr[iarray]))+1; + } + else { + if (dzr[iarray] == 0) { + verr("For receiver array %d: receiver distance dzrcv is not given", iarray); + } + nlrcv[iarray] = NINT(fabs(zrange/dzr[iarray]))+1; + } + nrcv+=nlrcv[iarray]; + } + + /* Calculate Number of Receivers */ +/* + nlrcv=(int *)malloc(Nx1*sizeof(int)); + if (!isnan(*xrcv1)) *nlrcv=MIN(NINT((*xrcv2-*xrcv1)/(*dxr)),NINT((*zrcv2-*zrcv1)/(*dzr)))+1; + else *nlrcv=0; + nrcv=*nlrcv; + if (verbose>4 && nlrcv[iarray]!=0) vmess("Linear receiver array 1 has final bounds: (X: %f -> %f,Z: %f -> +%f)",xrcv1[iarray],xrcv1[iarray]+nlrcv[iarray]*(*dxr),zrcv1[iarray],zrcv1[iarray]+nlrcv[iarray]*(*dzr)); + if (Ndx>1) { + for (iarray=1;iarray<Nx1;iarray++) { + if (!isnan(xrcv1[iarray])) { + nlrcv[iarray]=MIN(NINT((xrcv2[iarray]-xrcv1[iarray])/dxr[iarray]),NINT((zrcv2[iarray]-zrcv1[iarray])/dzr[iarray]))+1; + } + else { + nlrcv[iarray]=0; + } + nrcv+=nlrcv[iarray]; + if (verbose>4&&nlrcv[iarray]!=0) vmess("Linear receiver array %d has final bounds: (X: %f -> %f,Z: %f -> +%f)",iarray,xrcv1[iarray],xrcv1[iarray]+nlrcv[iarray]*dxr[iarray],zrcv1[iarray],zrcv1[iarray]+nlrcv[iarray]*dzr[iarray]); + } + } + else { + for (iarray=1;iarray<Nx1;iarray++) { + if (!isnan(xrcv1[iarray])) nlrcv[iarray]=MIN(NINT((xrcv2[iarray]-xrcv1[iarray])/(*dxr)),NINT((zrcv2[iarray]-zrcv1[iarray])/(*dzr)))+1; + else nlrcv[iarray]=0; + nrcv+=nlrcv[iarray]; + if (verbose>4&&nlrcv[iarray]!=0) vmess("Linear receiver array %d has final bounds: (X: %f -> %f,Z: %f -> +%f)",iarray,xrcv1[iarray],xrcv1[iarray]+nlrcv[iarray]**dxr,zrcv1[iarray],zrcv1[iarray]+nlrcv[iarray]**dzr); + } + } +*/ + if (verbose) vmess("Total number of linear array receivers: %d",nrcv); + if (!nrcv) { + free(yrcv1); + free(yrcv2); + free(xrcv1); + free(xrcv2); + free(zrcv1); + free(zrcv2); + free(dyr); + free(dxr); + free(dzr); + free(nlrcv); + } + rec->max_nrec+=nrcv; + } + else { + nrcv=0; + } + +/* allocate the receiver arrays */ + + /* Total Number of Receivers */ + if (verbose) vmess("Total number of receivers: %d",rec->max_nrec); + + /* Allocate Arrays */ + rec->y = (int *)calloc(rec->max_nrec,sizeof(int)); + rec->x = (int *)calloc(rec->max_nrec,sizeof(int)); + rec->z = (int *)calloc(rec->max_nrec,sizeof(int)); + rec->yr = (float *)calloc(rec->max_nrec,sizeof(float)); + rec->xr = (float *)calloc(rec->max_nrec,sizeof(float)); + rec->zr = (float *)calloc(rec->max_nrec,sizeof(float)); + +/* read in the receiver postions */ + + nrec=0; + /* Receivers on a Circle */ + if (ncrcv) { + if (!getparfloat("oyrcv",&oxrcv)) oyrcv=0.0; + if (!getparfloat("oxrcv",&oxrcv)) oxrcv=0.0; + if (!getparfloat("ozrcv",&ozrcv)) ozrcv=0.0; + if (!getparfloat("arcv",&arcv)) { + arcv=rrcv; + for (ix=0; ix<ncrcv; ix++) { + rec->yr[ix] = oyrcv-sub_y0+rrcv*cos(((iy*dphi)/360.0)*(2.0*M_PI)); + rec->xr[ix] = oxrcv-sub_x0+rrcv*cos(((ix*dphi)/360.0)*(2.0*M_PI)); + rec->zr[ix] = ozrcv-sub_z0+arcv*sin(((ix*dphi)/360.0)*(2.0*M_PI)); + rec->y[ix] = NINT(rec->yr[ix]/dy); + rec->x[ix] = NINT(rec->xr[ix]/dx); + rec->z[ix] = NINT(rec->zr[ix]/dz); + //rec->x[ix] = NINT((oxrcv-sub_x0+rrcv*cos(((ix*dphi)/360.0)*(2.0*M_PI)))/dx); + //rec->z[ix] = NINT((ozrcv-sub_z0+arcv*sin(((ix*dphi)/360.0)*(2.0*M_PI)))/dz); + if (verbose>4) fprintf(stderr,"Receiver Circle: yrcv[%d]=%f xrcv=%f zrcv=%f\n", ix, rec->yr[ix]+sub_y0, rec->xr[ix]+sub_x0, rec->zr[ix]+sub_z0); + } + } + else { /* an ellipse */ +/*TODO fix for 3D */ + /* simple numerical solution to find equidistant points on an ellipse */ + nh = (ncrcv)*1000; /* should be fine enough for most configurations */ + h = 2.0*M_PI/nh; + a = MAX(rrcv, arcv); + b = MIN(rrcv, arcv); + e = sqrt(a*a-b*b)/a; + //fprintf(stderr,"a=%f b=%f e=%f\n", a, b, e); + circ = 0.0; + for (ir=0; ir<nh; ir++) { + s = sin(ir*h); + circ += sqrt(1.0-e*e*s*s); + } + circ = a*h*circ; + //fprintf(stderr,"circ = %f circle=%f\n", circ, 2.0*M_PI*rrcv); + /* define distance between receivers on ellipse */ + dr = circ/ncrcv; + ix = 0; + srun = 0.0; + if (arcv >= rrcv) phase=0.0; + else phase=0.5*M_PI; + for (ir=0; ir<nh; ir++) { + s = sin(ir*h); + srun += sqrt(1.0-e*e*s*s); + if (a*h*srun >= ix*dr ) { + yr = rrcv*cos(ir*h+phase); + xr = rrcv*cos(ir*h+phase); + zr = arcv*sin(ir*h+phase); + rec->yr[ix] = oyrcv-sub_y0+xr; + rec->xr[ix] = oxrcv-sub_x0+xr; + rec->zr[ix] = ozrcv-sub_z0+zr; + rec->y[ix] = NINT(rec->yr[ix]/dy); + rec->x[ix] = NINT(rec->xr[ix]/dx); + rec->z[ix] = NINT(rec->zr[ix]/dz); + if (verbose>4) fprintf(stderr,"Receiver Ellipse: xrcv[%d]=%f zrcv=%f\n", ix, rec->xr[ix]+sub_x0, rec->zr[ix]+sub_z0); + ix++; + } + if (ix == ncrcv) break; + } + } + + /* check if receivers fit into the model otherwise clip to edges */ + for (ix=0; ix<ncrcv; ix++) { + rec->y[ix] = MIN(ny-1, MAX(rec->y[ix], 0)); + rec->x[ix] = MIN(nx-1, MAX(rec->x[ix], 0)); + rec->z[ix] = MIN(nz-1, MAX(rec->z[ix], 0)); + } + nrec += ncrcv; + } + + /* Receiver Text File */ + + if (ntrcv) { + /* Allocate arrays */ + yrcva = (float *)malloc(nrcv*sizeof(float)); + xrcva = (float *)malloc(nrcv*sizeof(float)); + zrcva = (float *)malloc(nrcv*sizeof(float)); + /* Read in receiver coordinates */ + for (i=0;i<nrcv;i++) { + if (fscanf(fp,"%e %e %e\n",&yrcva[i],&xrcva[i],&zrcva[i])!=3) vmess("Receiver Text File: Can not parse coordinates on line %d.",i); + } + /* Close file */ + fclose(fp); + /* Process coordinates */ + for (ix=0; ix<nrcv; ix++) { + rec->yr[nrec+ix] = yrcva[ix]-sub_y0; + rec->xr[nrec+ix] = xrcva[ix]-sub_x0; + rec->zr[nrec+ix] = zrcva[ix]-sub_z0; + rec->y[nrec+ix] = NINT((yrcva[ix]-sub_y0)/dy); + rec->x[nrec+ix] = NINT((xrcva[ix]-sub_x0)/dx); + rec->z[nrec+ix] = NINT((zrcva[ix]-sub_z0)/dz); + if (verbose>4) fprintf(stderr,"Receiver Text Array: yrcv[%d]=%f xrcv=%f zrcv=%f\n", ix, rec->yr[ix]+sub_y0, rec->xr[ix]+sub_x0, rec->zr[ix]+sub_z0); + } + free(yrcva); + free(xrcva); + free(zrcva); + nrec += ntrcv; + } + + /* Receiver Array */ + if (nxrcv != 0) { + /* receiver array is defined */ + yrcva = (float *)malloc(nxrcv*sizeof(float)); + xrcva = (float *)malloc(nxrcv*sizeof(float)); + zrcva = (float *)malloc(nxrcv*sizeof(float)); + getparfloat("yrcva", yrcva); + getparfloat("xrcva", xrcva); + getparfloat("zrcva", zrcva); + for (ix=0; ix<nxrcv; ix++) { + rec->yr[nrec+ix] = yrcva[ix]-sub_y0; + rec->xr[nrec+ix] = xrcva[ix]-sub_x0; + rec->zr[nrec+ix] = zrcva[ix]-sub_z0; + rec->y[nrec+ix] = NINT((yrcva[ix]-sub_y0)/dy); + rec->x[nrec+ix] = NINT((xrcva[ix]-sub_x0)/dx); + rec->z[nrec+ix] = NINT((zrcva[ix]-sub_z0)/dz); + if (verbose>4) fprintf(stderr,"Receiver Array: yrcv[%d]=%f xrcv=%f zrcv=%f\n", ix, rec->yr[ix]+sub_y0, rec->xr[ix]+sub_x0, rec->zr[ix]+sub_z0); + } + free(yrcva); + free(xrcva); + free(zrcva); + nrec += nxrcv; + } + + /* Linear Receiver Arrays */ + if (nrcv!=0) { + yrcv1 = (float *)malloc(Nx1*sizeof(float)); + yrcv2 = (float *)malloc(Nx1*sizeof(float)); + xrcv1 = (float *)malloc(Nx1*sizeof(float)); + xrcv2 = (float *)malloc(Nx1*sizeof(float)); + zrcv1 = (float *)malloc(Nx1*sizeof(float)); + zrcv2 = (float *)malloc(Nx1*sizeof(float)); + + if(!getparfloat("yrcv1", yrcv1)) yrcv1[0]=sub_y0; + if(!getparfloat("yrcv2", yrcv2)) yrcv2[0]=(ny-1)*dy+sub_y0; + if(!getparfloat("xrcv1", xrcv1)) xrcv1[0]=sub_x0; + if(!getparfloat("xrcv2", xrcv2)) xrcv2[0]=(nx-1)*dx+sub_x0; + if(!getparfloat("zrcv1", zrcv1)) zrcv1[0]=sub_z0; + if(!getparfloat("zrcv2", zrcv2)) zrcv2[0]=zrcv1[0]; + + Ndy = countparval("dyrcv"); + Ndx = countparval("dxrcv"); + Ndz = countparval("dzrcv"); + + dyr = (float *)malloc(Nx1*sizeof(float)); + dxr = (float *)malloc(Nx1*sizeof(float)); + dzr = (float *)malloc(Nx1*sizeof(float)); + if(!getparfloat("dyrcv", dyr)) dyr[0]=dy; + if(!getparfloat("dxrcv", dxr)) dxr[0]=dx; + if(!getparfloat("dzrcv", dzr)) dzr[0]=0.0; + if ( (Ndx<=1) && (Ndz==0) ){ /* default values are set */ + for (i=1; i<Nx1; i++) { + dyr[i] = dyr[0]; + dxr[i] = dxr[0]; + dzr[i] = dzr[0]; + } + Ndx=1; + } + else if ( (Ndz==1) && (Ndx==0) ){ /* default values are set */ + for (i=1; i<Nx1; i++) { + dyr[i] = dyr[0]; + dxr[i] = dxr[0]; + dzr[i] = dzr[0]; + } + Ndz=1; + } + else { /* make sure that each array has dzrcv or dxrcv defined for each line or receivers */ + if (Ndx>1) assert(Ndx==Nx1); + if (Ndz>1) assert(Ndz==Nx1); + if (Ndy>1) assert(Ndy==Nx1); + } + +/* + if ( (Ndx!=0) && (Ndz!=0) ) { + vwarn("Both dzrcv and dxrcv are set: dxrcv value is used"); + Ndz=0; + for (i=0; i<Nx1; i++) dzr[i] = 0.0; + } +*/ + /* check if receiver arrays fit into model */ + for (iarray=0; iarray<Nx1; iarray++) { + yrcv1[iarray] = MAX(sub_y0, yrcv1[iarray]); + yrcv1[iarray] = MIN(sub_y0+ny*dy,yrcv1[iarray]); + yrcv2[iarray] = MAX(sub_y0, yrcv2[iarray]); + yrcv2[iarray] = MIN(sub_y0+ny*dy,yrcv2[iarray]); + + xrcv1[iarray] = MAX(sub_x0, xrcv1[iarray]); + xrcv1[iarray] = MIN(sub_x0+nx*dx,xrcv1[iarray]); + xrcv2[iarray] = MAX(sub_x0, xrcv2[iarray]); + xrcv2[iarray] = MIN(sub_x0+nx*dx,xrcv2[iarray]); + + zrcv1[iarray] = MAX(sub_z0, zrcv1[iarray]); + zrcv1[iarray] = MIN(sub_z0+nz*dz,zrcv1[iarray]); + zrcv2[iarray] = MAX(sub_z0, zrcv2[iarray]); + zrcv2[iarray] = MIN(sub_z0+nz*dz,zrcv2[iarray]); + } + + /* calculate receiver array and store into rec->x,z */ + + for (iarray=0; iarray<Nx1; iarray++) { + yrange = (yrcv2[iarray]-yrcv1[iarray]); + xrange = (xrcv2[iarray]-xrcv1[iarray]); + zrange = (zrcv2[iarray]-zrcv1[iarray]); + if (dxr[iarray] != 0.0) { + nrcv = nlrcv[iarray]; + dxrcv=dxr[iarray]; + dzrcv = zrange/(nrcv-1); + if (dzrcv != dzr[iarray]) { + vwarn("For receiver array %d: calculated dzrcv=%f given=%f", iarray, dzrcv, dzr[iarray]); + vwarn("The calculated receiver distance %f is used", dzrcv); + } + } + else { + if (dzr[iarray] == 0) { + verr("For receiver array %d: receiver distance dzrcv is not given", iarray); + } + nrcv = nlrcv[iarray]; + dxrcv = xrange/(nrcv-1); + dzrcv = dzr[iarray]; + if (dxrcv != dxr[iarray]) { + vwarn("For receiver array %d: calculated dxrcv=%f given=%f", iarray, dxrcv, dxr[iarray]); + vwarn("The calculated receiver distance %f is used", dxrcv); + } + } + + // calculate coordinates + for (ir=0; ir<nrcv; ir++) { + rec->yr[nrec]=yrcv1[iarray]-sub_y0+ir*dyrcv; + rec->xr[nrec]=xrcv1[iarray]-sub_x0+ir*dxrcv; + rec->zr[nrec]=zrcv1[iarray]-sub_z0+ir*dzrcv; + + rec->y[nrec]=NINT((rec->yr[nrec])/dy); + rec->x[nrec]=NINT((rec->xr[nrec])/dx); + rec->z[nrec]=NINT((rec->zr[nrec])/dz); + nrec++; + } + } + free(yrcv1); + free(yrcv2); + free(xrcv1); + free(xrcv2); + free(zrcv1); + free(zrcv2); + free(dyr); + free(dxr); + free(dzr); + free(nlrcv); + } + + rec->n=rec->max_nrec; + return 0; +}