Homework 1 |
For extra credit, you can modify the wave modeling program to include
anisotropic wave propagation effects. The program below (slightly
modified from the original version by Paul Sava) implements wave
modeling with equation
/* 2-D finite-difference acoustic wave propagation */ #include <rsf.h> #ifdef _OPENMP #include <omp.h> #endif static int n1, n2; static float c0, c11, c21, c12, c22; static void laplacian(float **uin /* [n2][n1] */, float **uout /* [n2][n1] */) /* Laplacian operator, 4th-order finite-difference */ { int i1, i2; #ifdef _OPENMP #pragma omp parallel for private(i2,i1) shared(n2,n1,uout,uin,c11,c12,c21,c22,c0) #endif for (i2=2; i2 < n2-2; i2++) { for (i1=2; i1 < n1-2; i1++) { uout[i2][i1] = c11*(uin[i2][i1-1]+uin[i2][i1+1]) + c12*(uin[i2][i1-2]+uin[i2][i1+2]) + c21*(uin[i2-1][i1]+uin[i2+1][i1]) + c22*(uin[i2-2][i1]+uin[i2+2][i1]) + c0*uin[i2][i1]; } } } int main(int argc, char* argv[]) { int it,i1,i2; /* index variables */ int nt,n12,ft,jt; float dt,d1,d2,dt2; float *ww,**vv,**rr; float **u0,**u1,**u2,**ud; sf_file Fw,Fv,Fr,Fo; /* I/O files */ /* initialize Madagascar */ sf_init(argc,argv); /* initialize OpenMP support */ omp_init(); /* setup I/O files */ Fr = sf_input ("in"); /* source position */ Fo = sf_output("out"); /* output wavefield */ Fw = sf_input ("wav"); /* source wavelet */ Fv = sf_input ("v"); /* velocity */ /* Read/Write axes */ if (!sf_histint(Fr,"n1",&n1)) sf_error("No n1= in inp"); if (!sf_histint(Fr,"n2",&n2)) sf_error("No n2= in inp"); if (!sf_histfloat(Fr,"d1",&d1)) sf_error("No d1= in inp"); if (!sf_histfloat(Fr,"d2",&d2)) sf_error("No d2= in inp"); if (!sf_histint(Fw,"n1",&nt)) sf_error("No n1= in wav"); if (!sf_histfloat(Fw,"d1",&dt)) sf_error("No d1= in wav"); n12 = n1*n2; if (!sf_getint("ft",&ft)) ft=0; /* first recorded time */ if (!sf_getint("jt",&jt)) jt=1; /* time interval */ sf_putint(Fo,"n3",(nt-ft)/jt); sf_putfloat(Fo,"d3",jt*dt); sf_putfloat(Fo,"o3",ft*dt); dt2 = dt*dt; /* set Laplacian coefficients */ d1 = 1.0/(d1*d1); d2 = 1.0/(d2*d2); c11 = 4.0*d1/3.0; c12= -d1/12.0; c21 = 4.0*d2/3.0; c22= -d2/12.0; c0 = -2.0 * (c11+c12+c21+c22); /* read wavelet, velocity & source position */ ww=sf_floatalloc(nt); sf_floatread(ww ,nt ,Fw); vv=sf_floatalloc2(n1,n2); sf_floatread(vv[0],n12,Fv); rr=sf_floatalloc2(n1,n2); sf_floatread(rr[0],n12,Fr); /* allocate temporary arrays */ u0=sf_floatalloc2(n1,n2); u1=sf_floatalloc2(n1,n2); u2=sf_floatalloc2(n1,n2); ud=sf_floatalloc2(n1,n2); for (i2=0; i2<n2; i2++) { for (i1=0; i1<n1; i1++) { u0[i2][i1]=0.0; u1[i2][i1]=0.0; u2[i2][i1]=0.0; ud[i2][i1]=0.0; vv[i2][i1] *= vv[i2][i1]*dt2; } } /* Time loop */ for (it=0; it<nt; it++) { laplacian(u1,ud); #ifdef _OPENMP #pragma omp parallel for private(i2,i1) shared(ud,vv,ww,it,rr,u2,u1,u0) #endif for (i2=0; i2<n2; i2++) { for (i1=0; i1<n1; i1++) { /* scale by velocity */ ud[i2][i1] *= vv[i2][i1]; /* inject wavelet */ ud[i2][i1] += ww[it] * rr[i2][i1]; /* time step */ u2[i2][i1] = 2*u1[i2][i1] - u0[i2][i1] + ud[i2][i1]; u0[i2][i1] = u1[i2][i1]; u1[i2][i1] = u2[i2][i1]; } } /* write wavefield to output */ if (it >= ft && 0 == (it-ft)%jt) { sf_warning("%d;",it+1); sf_floatwrite(u1[0],n12,Fo); } } sf_warning("."); exit (0); } |
! 2-D finite-difference acoustic wave propagation module laplace ! Laplacian operator, 4th-order finite-difference implicit none real :: c0, c11, c21, c12, c22 contains subroutine laplacian_set(d1,d2) real, intent (in) :: d1,d2 c11 = 4.0*d1/3.0 c12= -d1/12.0 c21 = 4.0*d2/3.0 c22= -d2/12.0 c0 = -2.0 * (c11+c12+c21+c22) end subroutine laplacian_set subroutine laplacian(uin, uout) real, dimension (:,:), intent (in) :: uin real, dimension (:,:), intent (out) :: uout integer n1, n2 n1 = size(uin,1) n2 = size(uin,2) uout(3:n1-2,3:n2-2) = & c11*(uin(2:n1-3,3:n2-2) + uin(4:n1-1,3:n2-2)) + & c12*(uin(1:n1-4,3:n2-2) + uin(5:n1, 3:n2-2)) + & c21*(uin(3:n1-2,2:n2-3) + uin(3:n1-2,4:n2-1)) + & c22*(uin(3:n1-2,1:n2-4) + uin(3:n1-2,5:n2 )) + & c0*uin(3:n1-2,3:n2-2) end subroutine laplacian end module laplace program Wave use rsf use laplace implicit none integer :: it, nt, ft, jt, n1, n2 real :: dt, d1, d2, dt2 real, dimension (:), allocatable :: ww real, dimension (:,:), allocatable :: vv, rr real, dimension (:,:), allocatable :: u0,u1,u2,ud type(file) :: Fw,Fv,Fr,Fo ! I/O files call sf_init() ! initialize Madagascar ! setup I/O files Fr = rsf_input ("in") ! source position Fo = rsf_output("out") ! output wavefield Fw = rsf_input ("wav") ! source wavelet Fv = rsf_input ("v") ! velocity ! Read/Write axes call from_par(Fr,"n1",n1) call from_par(Fr,"n2",n2) call from_par(Fr,"d1",d1) call from_par(Fr,"d2",d2) call from_par(Fw,"n1",nt) call from_par(Fw,"d1",dt) call from_par("ft",ft,0) ! first recorded time call from_par("jt",jt,0) ! time interval call to_par(Fo,"n3",(nt-ft)/jt) call to_par(Fo,"d3",jt*dt) call to_par(Fo,"o3",ft*dt) dt2 = dt*dt ft = ft+1 ! set Laplacian coefficients call laplacian_set(1.0/(d1*d1),1.0/(d2*d2)) ! read wavelet, velocity & source position allocate (ww(nt), vv(n1,n2), rr(n1,n2)) call rsf_read(Fw,ww) call rsf_read(Fv,vv) call rsf_read(Fr,rr) ! allocate temporary arrays */ allocate (u0(n1,n2), u1(n1,n2), u2(n1,n2), ud(n1,n2)) u0=0.0 u1=0.0 u2=0.0 ud=0.0 vv = vv*vv*dt2 ! Time loop do it=1,nt call laplacian(u1,ud) ! scale by velocity ud = ud*vv ! inject wavelet ud = ud + ww(it) * rr ! time step u2 = 2*u1 - u0 + ud u0 = u1 u1 = u2 ! write wavefield to output if (it >= ft .and. 0 == mod(it-ft,jt)) then write(0,'(a,i4)',advance='no') achar(13), it call rsf_write(Fo,u1) end if end do write (0,*) call exit(0) end program Wave |
#!/usr/bin/env python import sys import numpy import m8r class Laplacian: 'Laplacian operator, 4th-order finite-difference' def __init__(self,d1,d2): self.c11 = 4.0*d1/3.0 self.c12= -d1/12.0 self.c21 = 4.0*d2/3.0 self.c22= -d2/12.0 self.c0 = -2.0*(self.c11+self.c12+self.c21+self.c22) def apply(self,uin,uout): n1,n2 = uin.shape uout[2:n1-2,2:n2-2] = self.c11*(uin[1:n1-3,2:n2-2]+uin[3:n1-1,2:n2-2]) + self.c12*(uin[0:n1-4,2:n2-2]+uin[4:n1 ,2:n2-2]) + self.c21*(uin[2:n1-2,1:n2-3]+uin[2:n1-2,3:n2-1]) + self.c22*(uin[2:n1-2,0:n2-4]+uin[2:n1-2,4:n2 ]) + self.c0*uin[2:n1-2,2:n2-2] par = m8r.Par() # setup I/O files Fr=m8r.Input() # source position Fo=m8r.Output() # output wavefield Fv=m8r.Input ("v") # velocity Fw=m8r.Input ("wav") # source wavefield # Read/Write axes a1 = Fr.axis(1); n1 = a1['n']; d1 = a1['d'] a2 = Fr.axis(2); n2 = a2['n']; d2 = a2['d'] at = Fw.axis(1); nt = at['n']; dt = at['d'] ft = par.int('ft',0) jt = par.int('jt',0) Fo.put('n3',(nt-ft)/jt) Fo.put('d3',jt*dt) Fo.put('o3',ft*dt) dt2 = dt*dt # set Laplacian coefficients laplace = Laplacian(1.0/(d1*d1),1.0/(d2*d2)) # read wavelet, velocity & source position ww = numpy.zeros(nt,'f'); Fw.read(ww) vv = numpy.zeros([n2,n1],'f'); Fv.read(vv) rr = numpy.zeros([n2,n1],'f'); Fr.read(rr) # allocate temporary arrays u0 = numpy.zeros([n2,n1],'f') u1 = numpy.zeros([n2,n1],'f') u2 = numpy.zeros([n2,n1],'f') ud = numpy.zeros([n2,n1],'f') vv = vv*vv*dt2 # Time loop for it in range(nt): laplace.apply(u1,ud) # scale by velocity ud = ud*vv # inject wavelet ud = ud + ww[it] * rr # time step u2 = 2*u1 - u0 + ud u0 = u1 u1 = u2 # write wavefield to output if it >= ft and 0 == (it-ft)%jt: sys.stderr.write("%d" % it) Fo.write(u1) |
Your task is to modify the code to implement elliptically-anisotropic wave propagation according to equation
wave
Figure 2. Wavefield snapshot for propagation from a point-source in a homogeneous medium. Modify the code to make wave propagation anisotropic. | |
---|---|
scons wave.vplto compile and run the program and to observe a propagating wave on your screen.
scons wave.vplagain to compile and test your program.
vp,vx
Figure 3. Vertical velocity (a) and horizontal velocity (b) in the Hess VTI model. |
---|
from rsf.proj import * from rsf.prog import RSFROOT # Program compilation ##################### proj = Project() # To do the coding assignment in Fortran, # comment the next line and uncomment the lines below exe = proj.Program('wave.c') # UNCOMMENT BELOW IF YOU WANT TO USE FORTRAN #exe = proj.Program('wave.f90', # F90PATH=os.path.join(RSFROOT,'include'), # LIBS=['rsff90']+proj.get('LIBS')) # UNCOMMENT BELOW IF YOU WANT TO USE PYTHON #exe = proj.Command('wave.exe','wave.py','cp $SOURCE $TARGET') #AddPostAction(exe,Chmod(exe,0o755)) # Constant velocity test ######################## # Source wavelet Flow('wavelet',None, ''' spike n1=1000 d1=0.001 k1=201 | ricker1 frequency=10 ''') # Source location Flow('source',None, ''' spike n1=201 n2=301 d1=0.01 d2=0.01 label1=x1 unit1=km label2=x2 unit2=km k1=101 k2=151 ''') # Velocity model Flow('v1','source','math output=1') Flow('v2','source','math output=1.5') # Modeling Flow('wave','source %s wavelet v1 v2' % exe[0], ''' ./${SOURCES[1]} wav=${SOURCES[2]} v=${SOURCES[3]} vx=${SOURCES[4]} ft=200 jt=5 ''') Plot('wave','grey gainpanel=all title=Wave',view=1) Result('wave', ''' window n3=1 min3=0.9 | grey title=Wave screenht=8 screenwd=12 ''') # Download Hess VTI model ######################### zcat = WhereIs('gzcat') or WhereIs('zcat') for case in ('vp','epsilon'): sgy = 'timodel_%s.segy' % case sgyz = sgy + '.gz' Fetch(sgyz,dir='hessvti', server='https://s3.amazonaws.com', top='open.source.geoscience/open_data') # Uncompress Flow(sgy,sgyz,zcat + ' $SOURCE',stdin=0) # Convert to RSF format Flow(case,sgy, ''' segyread read=data | window j1=2 j2=2 | put d1=40 d2=40 unit1=ft label1=Depth unit2=ft label2=Distance ''') # Horizontal velocity Flow('vx','vp epsilon', 'math e=${SOURCES[1]} output="input*sqrt(1+2*e)"') for case in ('vp','vx'): Result(case, ''' grey color=j pclip=100 allpos=y bias=5000 scalebar=y barreverse=y wanttitle=n barlabel=Velocity barunit=ft/s screenht=5 screenwd=12 labelsz=6 ''') Flow('hsource','vp','spike k1=300 k2=900') Flow('hess','hsource %s wavelet vp vx' % exe[0], ''' ./${SOURCES[1]} wav=${SOURCES[2]} v=${SOURCES[3]} vx=${SOURCES[4]} ft=200 jt=5 ''') End() |
Homework 1 |