⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 triseis.c

📁 该程序主要用于三角网
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) Colorado School of Mines, 2001.*/
/* All rights reserved.                       */

/* TRISEIS: $Test Release: 1.1 $ ; $Date: 1997/10/29 17:23:49 $	*/

#include "par.h"
#include "Triangles/tri.h"
#include "Triangles/sloth.h"

/*********************** self documentation **********************/
char *sdoc[] = {
"									",
" TRISEIS - Gaussian beam synthetic seismograms for a sloth model	",
"									",
"  triseis <modelfile >seisfile xs= zs= xg= zg= [optional parameters]	",
"									",
" Required Parameters:							",
" xs=            x coordinates of source surface			",
" zs=            z coordinates of source surface			",
" xg=            x coordinates of receiver surface			",
" zg=            z coordinates of receiver surface			",
"									",
" Optional Parameters:							",
" ns=1           number of sources uniformly distributed along s surface",
" ds=            increment between source locations (see notes below)	",
" fs=0.0         first source location (relative to start of s surface)	",
" ng=101         number of receivers uniformly distributed along g surface",
" dg=            increment between receiver locations (see notes below)	",
" fg=0.0         first receiver location (relative to start of g surface)",
" dgds=0.0       change in receiver location with respect to source location",
" krecord=1      integer index of receiver surface (see notes below)	",
" kreflect=-1    integer index of reflecting surface (see notes below)	",
" prim           =1, only single-reflected rays are considered 		",     
"                =0, only direct hits are considered  			",
" bw=0           beamwidth at peak frequency				",
" nt=251         number of time samples					",
" dt=0.004       time sampling interval					",
" ft=0.0         first time sample					",
" nangle=101     number of ray takeoff angles				",
" fangle=-45     first ray takeoff angle (in degrees)			",
" langle=45      last ray takeoff angle (in degrees)			",
" reftrans=0     =1 complex refl/transm. coefficients considered 	",
" atten=0        =1 add noncausal attenuation 				",
"                =2 add causal attenuation 				",
" lscale=        if defined restricts range of extrapolation		",
" fpeak=0.1/dt   peak frequency of ricker wavelet 			",
" aperture=      maximum angle of receiver aperture 			",
"									",
" NOTES:								",
" Only rays that terminate with index krecord will contribute to the	",
" synthetic seismograms at the receiver (xg,zg) locations.  The		",
" source and receiver locations are determined by cubic spline		",
" interpolation of the specified (xs,zs) and (xg,zg) coordinates.	",
" The default source location increment (ds) is determined to span	",
" the source surface defined by (xs,zs).  Likewise for dg.		",
"									",
NULL};

/*
 * AUTHOR:  Dave Hale, Colorado School of Mines, 02/09/91
 * MODIFIED:  Andreas Rueger, Colorado School of Mines, 08/18/93
 *	Modifications include: 2.5-D amplitudes, correction for ref/transm,
 *			timewindow, lscale, aperture, beam width, etc.
 */
/**************** end self doc ***********************************/

#define TAPER 0.97
#define C 0.99
#define EPS 0.0001

/* parameters for one step of dynamic ray tracing */
typedef struct RSStruct {
	float sigma,x,z,px,pz,t;
	float q1,p1,q2,p2;
        float atten;
        float ampli,ampliphase;
	int kmah,nref;
	EdgeUse *eu;
	Face *f;
} RayStep;

/* prototypes for functions defined and used internally */
static void makexzs (int nu, float *xu, float *zu, 
	int ns, float ds, float fs, float *xs, float *zs);
static void makesyn (float fpeak,int prim,int nre, RayEnd *re, float lscale,
	int krecord, int ng, float *xg, float *zg,
	float bw, int nt, float dt, float ft,
        int natten, int reftrans, float aperture);
static complex cricker (float w, float wpeak, float delay);
static int insideModel (Model *m, float x, float z);
static void shootRays (Model *m, float xs, float zs,
	int nangle, float dangle, float fangle,
	int kstop, int kreflect,
	RayEnd re[]);
static void traceRayInTri (RayStep *rs, RayStep *rsnew);
static int traceRayAcrossEdge (RayStep *rs, RayStep *rsnew);
static void reflectRayFromEdge (RayStep *rs, RayStep *rsnew);
static void evaluateDynamic (float sigma, 
	float px, float pz, float dsdx, float dsdz,
	float *q1, float *p1, float *q2, float *p2, int *kmah);
int checkIfSourceOnEdge (Face *tris, float zs, float xs);

/* the main program */
int main (int argc, char **argv)
{
	int nxs,nzs,nxzs,nxg,nzg,nxzg,
		ns,ng,krecord,kreflect,nt,nangle,it,is,ig;
	int natten,reftrans,prim;
	float ds,fs,dg,fg,dgds,s,bw,dt,ft,cpuray,cpuseis,
		fangle,langle,dangle,lscale,fpeak,aperture,
		*xsu,*zsu,*xgu,*zgu,
		*xs,*zs,*xg,*zg,*zeros;
	Model *m;	
	RayEnd *re;

	/* hook up getpar to handle the parameters */
	initargs(argc,argv);
	requestdoc(0);

	/* read sloth model */
	m = readModel(stdin);

	/* source location parameters */
	nxs = countparval("xs");
	nzs = countparval("zs");
	if (nxs==0 || nzs==0) err("must specify both xs and zs");
	if (nxs!=nzs) err("number of xs must equal number of zs");
	nxzs = nxs;
	xsu = ealloc1float(nxzs);
	zsu = ealloc1float(nxzs);
	getparfloat("xs",xsu);
	getparfloat("zs",zsu);
	if (!getparint("ns",&ns)) ns = 1;
	if (!getparfloat("ds",&ds)) ds = 0.0;
	if (!getparfloat("fs",&fs)) fs = 0.0;

	/* receiver location parameters */
	nxg = countparval("xg");
	nzg = countparval("zg");
	if (nxg==0 || nzg==0) err("must specify both xg and zg");
	if (nxg!=nzg) err("number of xg must equal number of zg");
	nxzg = nxg;
	xgu = ealloc1float(nxzg);
	zgu = ealloc1float(nxzg);
	getparfloat("xg",xgu);
	getparfloat("zg",zgu);
	if (!getparint("ng",&ng)) ng = 101;
	if (!getparfloat("dg",&dg)) dg = 0.0;
	if (!getparfloat("fg",&fg)) fg = 0.0;
	if (!getparfloat("dgds",&dgds)) dgds = 0.0;
	if (!getparint("krecord",&krecord)) krecord = 1;
	if (!getparint("prim",&prim)) prim = INT_MAX;

	/* other parameters */
	if (!getparint("kreflect",&kreflect)) kreflect = -1;
	if (!getparfloat("bw",&bw)) bw = 0.0;
	if (!getparint("nt",&nt)) nt = 251;
	if (!getparfloat("dt",&dt)) dt = 0.004;
	if (!getparfloat("ft",&ft)) ft = 0.0;
	if (!getparfloat("fpeak",&fpeak)) fpeak = 0.1/dt;

	if (0.5/dt<2.0*fpeak) {
		fprintf(stderr,"WARNING: ALIASING POSSIBLE\n");
		fprintf(stderr,"decrease dt or reduce fpeak\n");
	}

	if (!getparint("nangle",&nangle)) nangle = 101;
	if (!getparfloat("fangle",&fangle)) fangle = -45.0;
	if (!getparfloat("langle",&langle)) langle = 45.0;
	if (!getparint("reftrans",&reftrans)) reftrans = 0;
	if (!getparint("atten",&natten)) natten = 0;
	if (!getparfloat("aperture",&aperture)) aperture = FLT_MAX;
	if (!getparfloat("lscale",&lscale)) lscale = FLT_MAX;
	if (aperture != FLT_MAX) aperture = asin(aperture*PI/180.0);

	/* convert angles to radians and determine angle increment */
	fangle *= PI/180.0;
	langle *= PI/180.0;
	dangle = (nangle>1) ? (langle-fangle)/(nangle-1) : 1.0;

	/* allocate space */
	xs = ealloc1float(ns);
	zs = ealloc1float(ns);
	xg = ealloc1float(ng);
	zg = ealloc1float(ng);
	zeros = ealloc1float(nt);
	re = ealloc1(nangle,sizeof(RayEnd));

	/* determine source locations */
	makexzs(nxzs,xsu,zsu,ns,ds,fs,xs,zs);

	/* make trace with all zeros */
	for (it=0; it<nt; ++it)
		zeros[it] = 0.0;

	/* loop over source locations */
	for (is=0,s=fs,cpuray=cpuseis=0.0; is<ns; ++is,s+=ds) {

		/* uncomment for diagnostic print */
		fprintf(stderr,"shot %3d of %3d at x=%g\n",is,ns,xs[is]);
/*		fprintf(stderr,"shot %d at x=%.25g,z=%.25g\n",
			is,xs[is],zs[is]);
		fprintf(stderr,"rec %d at x=%.25g\n",is,fg+dgds*(s-fs));

		if (is<32 || is>33) continue;
*/
		/* if source is outside of model boundaries */
		if (!insideModel(m,xs[is],zs[is])) {

			/* write zeros */
			for (ig=0; ig<ng; ++ig)
				if (efwrite(zeros,sizeof(float),nt,stdout)!=nt)
					err("error writing output traces!\n");

			/* continue with next source location */
			continue;
		}

		/* shoot rays */
		/* cputemp = cpusec();*/
		shootRays(m,xs[is],zs[is],nangle,dangle,
				fangle,krecord,kreflect,re);
		/* cpuray += cpusec()-cputemp;*/

		/* compute receiver locations */
		makexzs(nxzg,xgu,zgu,ng,dg,fg+dgds*(s-fs),xg,zg);

		/* compute and write synthetic seismograms */
		/* cputemp = cpusec(); */
		makesyn(fpeak,prim,nangle,re,lscale,krecord,						
			ng,xg,zg,bw,nt,dt,ft,natten,reftrans,aperture);
	/*	cpuseis += cpusec()-cputemp; */
	}
	cpuray += 0.0;
	cpuseis += 0.0;

	/* cpu timings */
	/*
         * fprintf(stderr,"\ntriseis:  total cpu time = %g s\n",cpusec());
         * fprintf(stderr,"triseis:  ray tracing cpu time = %g s\n",cpuray);
         * fprintf(stderr,"triseis:  seismogram cpu time = %g s\n",cpuseis);
	 */

	return EXIT_SUCCESS;
}

static void makexzs (int nu, float *xu, float *zu, 
	int ns, float ds, float fs, float *xs, float *zs)
/* interpolate (x,z) coordinates uniformly sampled in distance s */
{
	int iu,nuu,iuu,is,js;
	float x,z,xlast,zlast,dx,dz,duu,uu,temp,
		*u,*s,(*xud)[4],(*zud)[4],*us;

	xud = (float(*)[4])ealloc1float(4*nu);
	zud = (float(*)[4])ealloc1float(4*nu);
	u = ealloc1float(nu);
	for (iu=0; iu<nu; ++iu)
		u[iu] = iu;
	csplin(nu,u,xu,xud);
	csplin(nu,u,zu,zud);
	nuu = 10*nu;
	duu = (u[nu-1]-u[0])/(nuu-1);
	s = ealloc1float(nuu);
	s[0] = 0.0;
	xlast = xu[0];
	zlast = zu[0];
	for (iuu=0,uu=0.0,s[0]=0.0; iuu<nuu; ++iuu,uu+=duu) {
		intcub(0,nu,u,xud,1,&uu,&x);
		intcub(0,nu,u,zud,1,&uu,&z);
		dx = x-xlast;
		dz = z-zlast;
		s[iuu] = s[iuu-1]+sqrt(dx*dx+dz*dz);
		xlast = x;
		zlast = z;
	}			
	us = ealloc1float(ns);
	if (ds==0.0) ds = (s[nuu-1]-s[0])/((ns>1)?ns-1:1);
	if (ds<0.0) {
		yxtoxy(nuu,duu,0.0,s,ns,-ds,fs+(ns-1)*ds,0.0,(float)(nu-1),us);
		for (is=0,js=ns-1; is<js; ++is,--js) {
			temp = us[is];
			us[is] = us[js];
			us[js] = temp;
		}
	} else {
		yxtoxy(nuu,duu,0.0,s,ns,ds,fs,0.0,(float)(nu-1),us);
	}
	intcub(0,nu,u,xud,ns,us,xs);
	intcub(0,nu,u,zud,ns,us,zs);
	free1float(us);
	free1float(s);
	free1float(u);
	free1float((float*)xud);
	free1float((float*)zud);
}

static void makesyn (float fpeak, int prim, int nre, RayEnd *re, float lscale,
	int krecord, int ng, float *xg, float *zg, float bw,
	int nt, float dt, float ft, int natten, int reftrans, float aperture)
/* make and write synthetic seismograms */
{
	int ntfft,nw,iw,ig,ire,kend,kmah,nref;
	float dw,w,wpeak,delay,scale,wref,eps1,eps2,n,
		t,x,z,px,pz,q1,p1,q2,p2,v0,v,dsdx,dsdz,
		dx,dz,delt,dels,nn,phase,ta,cpoqr,cpoqi,disq,
		*syn,sigma,*lnvec,sqlscale,dangle;
        float ampli,ampliphase,atten,temp,c,eps,v2,v4,dvds,dvdn;
	double campr,campi,cosw,sinw,expw,cosd,sind,expd,tempd;
	complex ceps,cq,cp,cpoq,cqr,camp,
		*cwave,**csyn;
	
	/* constants */
	ntfft = npfaro(nt,2*nt);
	nw = ntfft/2+1;
	dw = 2.0*PI/(ntfft*dt);
	wpeak = 2*PI*fpeak;
	wref = 1000.0;
	delay = 0.0;
	sqlscale = lscale*lscale;
	c = C;
	eps = EPS;

	/* allocate workspace */
	syn = ealloc1float(ntfft);
	cwave = ealloc1complex(nw);
	csyn = ealloc2complex(nw,ng);
	lnvec = ealloc1float(nw);

	/* initialize synthetics */
	for (ig=0; ig<ng; ++ig)
		for (iw=0; iw<nw; ++iw)
			csyn[ig][iw] = cmplx(0.0,0.0);

	/* precomputing causal attenuation term */
	if (natten==2) {
		temp = 1.0/PI;
		lnvec[0] = -1.0;
		for(iw=1,w=dw; iw<nw; ++iw,w+=dw)
			lnvec[iw] = log(w/wref)*temp;
	}

	/* loop over rays */
	for (ire=0; ire<nre; ++ire) {

		/* determine index of ray end */
		kend = re[ire].kend;

		/* if not the end index we want, skip this ray */
		if (kend!=krecord) continue;

		nref = re[ire].nref;

		/* if ray was not reflected */
		if (nref!=prim && prim!=INT_MAX) continue;

		px = re[ire].px;
		v = 1.0/sqrt(re[ire].se);

		/* if not within aperture, skip this ray */
		if (ABS(px*v)>aperture) continue;

		/* ray end parameters */
		sigma = 1/sqrt(re[ire].sigma);
		x = re[ire].x;
		z = re[ire].z;
		t = re[ire].t;
		pz = re[ire].pz;
		q1 = re[ire].q1;
		p1 = re[ire].p1;
		q2 = re[ire].q2;
		p2 = re[ire].p2;
		kmah = re[ire].kmah;
		atten = re[ire].atten;
		ampli = re[ire].ampli;
		ampliphase = re[ire].ampliphase;
		dangle = re[ire].dangle;
		dsdx = re[ire].dsdxe;
		dsdz = re[ire].dsdze;
		v0 = 1.0/sqrt(re[ire].sb);

		/* compute ray dependant constants */
		v2 = v*v;
		v4 = v2*v2;
		dvds = -0.5*v4*(dsdx*px+dsdz*pz);
		dvdn = -0.5*v4*(dsdx*pz-dsdz*px);

		scale = sigma*dangle*sqrt(v/(v0*2*PI));

		/* complex beam epsilon */
		if (bw!=0.0) {
			eps1 = 0.0;
			eps2 = -0.5*wpeak*bw*bw;
		} else {
			temp = c * ABS(p2/q2) + eps;
			eps1 = -q2/q1 * (p2*p1/(q2*q1) + temp*temp);
			eps1 = eps1/(p1*p1/(q1*q1) + temp*temp);
			eps2 = -temp/(p1*p1+q1*q1*temp*temp);		
		}
		ceps = cmplx(eps1,eps2);

		/* complex p, q, and p/q */
		cp = crmul(ceps,p1);  cp.r += p2;
		cq = crmul(ceps,q1);  cq.r += q2;
		cpoq = cdiv(cp,cq);
		cpoqr = cpoq.r;
		cpoqi = cpoq.i;

		/* if cpoqi negative, skip ray */
		/* (cpoqi<0 leads to exponential growth!) */
		if (cpoqi<0.0) {
			continue;
		}

		/* complex q, adjusted for reflections */
		cqr = (nref%2) ? cneg(cq) : cq;

		/* frequency- and ray-independent amplitude factor */
		phase = -PI*((kmah+1)/2);
		camp = csqrt(cdiv(ceps,cqr));

		/* correction for cmplex reflection/transmission */
		if (reftrans) {
			phase += ampliphase;
			camp = crmul(camp,ampli);
		}

                /* correction for 2.5-D Spreading */
        	phase += PI/4.0;

                camp = crmul(camp,scale);
		camp = cmul(camp,cmplx(cos(phase),sin(phase)));
		campr = camp.r;
		campi = camp.i;

		/* save computing time */
     		if (natten == 2)
			for (iw=0; iw<nw; ++iw)
				lnvec[iw] = atten*lnvec[iw];

		/* loop over receiver locations */
		for (ig=0; ig<ng; ++ig) {

			/* delta x and delta z */
			dx = xg[ig]-x;
			dz = zg[ig]-z;
			disq = dx*dx+dz*dz;

			/* delta t and delta s */
			n = v*(pz*dx-px*dz);
			nn = n*n;

			/* do not extrapolate too far */
			if (lscale!=FLT_MAX && disq>sqlscale) continue;

			dels = v*(px*dx+pz*dz)*(1-dvdn/v*n);
			delt = dels/v-0.5*dvds*dels*dels/v2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -