基于Madagascar的二维地震声波波动方程正演模拟

最近在将SU写的地震勘探的程序迁移到Madagascar上,初步尝试,写了一个二维声波方程正演程序,很简单,也很基本,只能输出波场快照,没有吸收边界条件,贴出来,供大家参考。代码和脚本如下:

#include 
#include "rsf.h"
#define FSIZE sizeof(float)

static float ricker (float t, float fpeak);
void ptsrc (float saf,float xs,float zs,int nx,float dx,float fx,int nz,
    float dz,float fz,float dt,float t,float fmax,float fpeak,float tdelay,
    float **s);
void fd2d (float multis,float xs,float zs,int nx,float dx,float fx,int nz,
    float dz,float fz,int nt,float dt,float fmax,float fpeak,float tdelay,
    float **s,float **v,float **pf,float **p,float **pb);

int main (int argc, char *argv[])
{
    bool verb;              /* verbose flag */
    int T_beg,T_end,T_dur;  /* program run time  */

    int it,iz,ix;           /* index variables */
    
    int nz,nx;
    float dz,dx;
    float fz,fx;
    float h;

    int nt;
    float dt;
    float tmax;
    float mt;
    float t;

    int ns;
    int is;
    float dxs,dzs;
    float fxs,fzs;
    float *xs,*zs;

    float c0,c1,c2;         /* Laplacian coefficients */

    float vmin,vmax;
    float **v;    

    float fpeak,fmax;
    float saf;
    float tdelay;

    sf_axis at,az,ax;       /* cube axes */
    
    FILE *fv=NULL;          /* velocitu file */
    sf_file fo=NULL;        /* output file   */
    
    float **s;
    float **Pf;
    float **P;
    float **Pb;
    float **Ptmpt;
 
    sf_init(argc,argv);
    T_beg=clock();
    sf_warning("************ Program BEG! ***********.\n");

    /* get required parameters */    
    if(! sf_getint("nt",&nt))       sf_error(" must specify nt!");
    if(! sf_getint("ns",&ns))       sf_error(" must specify ns!");
    if(! sf_getint("nx",&nx))       sf_error(" must specify nx!");
    if(! sf_getint("nz",&nz))       sf_error(" must specify nz!");
    if(! sf_getfloat("dt",&dt))     sf_error(" must specify dt!");
    if(! sf_getfloat("dx",&dx))     sf_error(" must specify dx!");
    if(! sf_getfloat("dz",&dz))     sf_error(" must specify dz!");
    if(! sf_getfloat("dxs",&dxs))   sf_error(" must specify dxs!");
    if(! sf_getfloat("dzs",&dzs))   sf_error(" must specify dzs!");

    /* Input and output file information */
    if(! sf_getbool("verb",&verb))          verb=0;
    if(! sf_getfloat("fx",&fx))             fx=0;
    if(! sf_getfloat("fz",&fz))             fz=0;
    if(! sf_getfloat("fxs",&fxs))           fxs=0;
    if(! sf_getfloat("fzs",&fzs))           fzs=0;
    if(! sf_getfloat("saf",&saf))           saf=1;
    if(! sf_getfloat("tdelay",&tdelay))     tdelay=0.0;


    sf_warning("verb=%d\n",verb);
    sf_warning("nt=%d,nx=%d,nz=%d\n",nt,nx,nz);
    sf_warning("dt=%f,dx=%f,dz=%f\n",dt,dx,dz);

    /* allocate wavefield arrays */
    xs  = sf_floatalloc(ns);
    zs  = sf_floatalloc(ns);    
    v  = sf_floatalloc2(nz,nx);
    s  = sf_floatalloc2(nz,nx);
    Pf = sf_floatalloc2(nz,nx);
    P  = sf_floatalloc2(nz,nx);
    Pb = sf_floatalloc2(nz,nx);    

    memset((void *) v[0], 0,FSIZE*nz*nx);
    memset((void *) s[0], 0,FSIZE*nz*nx);
    memset((void *) Pf[0],0,FSIZE*nz*nx);
    memset((void *) P[0], 0,FSIZE*nz*nx);
    memset((void *) Pb[0],0,FSIZE*nz*nx);

    /* read velocity */
    fv=stdin;
    fread(v[0],sizeof(float),nx*nz,fv);
    sf_warning("*****v[%d][%d]=%f s*****.\n",1,1,v[1][1]);
    /* determine minimum and maximum velocities */
    vmin = vmax = v[0][0];
    for (ix=0; ix h/(2.0*vmax))
    {
        sf_error(" dt must <= %f!",h/(2.0*vmax));
    } 
    
    /* determine maximum temporal frequency to avoid dispersion */
    if(! sf_getfloat("fmax",&fmax)) sf_error(" must specify fmax!");    
    if (fmax > vmin/(10.0*h))       sf_error(" fmax must <= %f!",vmin/(10.0*h)); 
    
    /* compute or set peak frequency for ricker wavelet */
    if(! sf_getfloat("fpeak",&fpeak)) sf_error(" must specify fpeak!");    
    if (SF_NINT(fmax/fpeak) != 2)     sf_error(" fpeak must = fmax/2!");

    /* determine source coordinates */
    for (is=0;is2.0*tdelay) return;
    ts = ricker(t-tdelay,fpeak);
    
    /* let source contribute within limited distance */
    xsn = (xs-fx)/dx;
    zsn = (zs-fz)/dz;
    ixs = SF_NINT(xsn);
    izs = SF_NINT(zsn);

    for (ix=SF_MAX(0,ixs-3); ix<=SF_MIN(nx-1,ixs+3); ++ix) 
    {
        for (iz=SF_MAX(0,izs-3); iz<=SF_MIN(nz-1,izs+3); ++iz) 
        {
            xn = ix-xsn;
            zn = iz-zsn;
            s[ix][iz] = saf*ts*exp(-xn*xn-zn*zn);
        }
    }
}


void fd2d (float multis,float xs,float zs,int nx,float dx,float fx,
    int nz,float dz,float fz,
    int nt,float dt, float fmax, float fpeak, float tdelay, float **s,
    float **v,float **pf,float **p,float **pb)
/*******************************************************************************
update source pressure function for a point source
********************************************************************************/
{
    int ix,iz,it;
    int N;

    float a0,a1,a2,a3;
    

    float t;

    float **ptemp;

    char fname[BUFSIZ];
    FILE *fp = NULL;
    
    a0 = -2.7222;
    a1 =  1.5000;
    a2 = -0.1500;
    a3 =  1/90;
    N=6;

    for ( it = 0,t=0; it < nt; ++it,t+=dt)
    {
        ptsrc (multis,xs,zs,nx,dx,fx,nz,dz,fz,dt,t,fmax,fpeak,tdelay,s);

        for ( ix = N/2; ix < nx-N/2; ++ix)
        {
            for ( iz = N/2; iz < nz-N/2; ++iz)
            {
                pf[ix][iz]=2*p[ix][iz]-pb[ix][iz] +
                           v[ix][iz]*v[ix][iz]*(dt*dt)*
                           ( (a0*p[ix][iz]+
                              a1*(p[ix+1][iz]+p[ix-1][iz])+
                              a2*(p[ix+2][iz]+p[ix-2][iz])+
                              a3*(p[ix+3][iz]+p[ix-3][iz])
                             )/dx/dx/2+
                             (a0*p[ix][iz]+
                              a1*(p[ix][iz+1]+p[ix][iz-1])+
                              a2*(p[ix][iz+2]+p[ix][iz-2])+
                              a3*(p[ix][iz+3]+p[ix][iz-3])
                             )/dz/dz/2
                           )+
                           s[ix][iz]*v[ix][iz]*v[ix][iz]*(dt*dt);
            }
        }
        
        sprintf(fname,"fw_%d.bin",it);
        fp=fopen(fname,"wb");
        fwrite(p[0],sizeof(float),nx*nz,fp);
        fclose(fp); 

        ptemp=pb;
        pb=p;
        p=pf;
        pf=ptemp;
    }               
}

声明:本程序借鉴了SU的部分代码,本程序仅限于学习,如有他用,后果自负。
程序运行脚本:

#!/bin/sh
#

vel=Data/model/vel.bin

# model information
n1=201  d1=10  f1=0.0 label1="Depth (km)"
n2=401  d2=10 f2=0.0 label2="Distance (km)"

# seismic source information
ns=1 fxs=2000 fzs=1000 dxs=50 dzs=0

verb=1
nt=1000 dt=0.001

fmax=40 fpeak=20 saf=100 tdelay=0.1

./SRC/fdm2d_cpu < $vel  \
                verb=$verb nt=$nt dt=$dt \
                nx=$n2 dx=$d2 fx=$f2 nz=$n1 dz=$d1 fz=$f1 \
                fmax=$fmax fpeak=$fpeak saf=$saf tdelay=$tdelay \
                ns=$ns fxs=$fxs fzs=$fzs dxs=$dxs dzs=$dzs \
exit 0

你可能感兴趣的:(Madagascar学习,SU(seismic,Unix)专栏,C语言专栏)