📄 triseis.c
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* 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 + -