// asg_ansol.cc // Author: Mario J. Bencomo // last modification: 11/10/16 #include "asg_defn.hh" #include "asg.hh" #include "MPS_includes.hh" #include "MPS_Space.hh" using RVL::valparse; using RVL::RVLException; using TSOpt::Rtuple; using TSOpt::Ituple; using TSOpt::ex_pos; const char *sdoc[] = { " ============================================================================", " asg_ansol.x ", " ============================================================================", " Authors: Mario J. Bencomo", " ", " Analytical solution for acoustics with variable density in first order form,", " for homogenous unbounded medium.", " ", " PDE system: ", " dp/dt + bulk{ div v } = f(t,x)", " dv/dt + buoy grad p = 0", " where p=pressure, v=velocity, and ", " 2-D, f(x,t) = f_0(t) (d/dx_0)^{s_0} (d/dx_1)^{s_1} delta(x-x^*)", " 3-D, f(x,t) = f_0(t) (d/dx_0)^{s_0} (d/dx_1)^{s_1} (d/dx_2)^{s_2} delta(x-x^*)", " Output is p(x_r,t) for given reciever locations specified by input SU file. ", " ", " Typical parameter list. May be copied, edited, and used for input: either", " include parameters on command line (for example in Flow), or place", " in file and include \"par=\" on command line. Any parameter", " included explicitly in command line overrides parameter with same key", " in par file.", " ", " Invoke single threaded execution by ", " \"asg_ansol.x [parameters] [standalone install]\"", " ", " --------------------------- begin parameters ---------------------------", " pressure = output SU file for writing in pressure field, must exist", " source = input SU file containing source time function", " bulk = 1.0 bulk modulus in GPa", " buoy = 1.0 buoyancy in cm^3/g", " dimension = 3 spatial dimension", " MPS_ord_0 = 0 MPS order in z-direction, s_0", " MPS_ord_1 = 0 MPS order in x-direction, s_1", " MPS_ord_2 = 0 MPS order in y-direction, s_2", " ---------------------------end parameters ------------------------------", NULL }; IOKEY IWaveInfo::iwave_iokeys[] = { {"bulkmod", 0, true, 1 }, {"buoyancy", 1, true, 1 }, {"source_p", 2, true, 2 }, {"data_p", 2, false, 2 }, {"", 0, false, 0 } }; float lininterp(int nt, float dt, float t0, float t, float *f) { float s = t/dt; int it = int(s); if (it < 0 || it > nt-2) return 0.0f; else return (s-float(it))*f[it]+(float(it)+1.0f-s)*f[it+1]; } /* */ //----------------------------------------------------------------------// void exact( int nt_out, int nt_src, float t0_out, float t0_src, float dt, RPNT x, float c, IPNT derv, int dim, float * f, float * p ){ //----------------------------------------------------------------------// try{ int d_ord = 0; for(int d=0; d1 ){ RVLException e; e << "Derivative order must be <= 1 for dim="<2 ){ RVLException e; e << "Derivative order must be <= 2 for dim="<0){ //compute ddf ddf = new float[nt_src]; ddf[0]=(df[1]-df[0])/dt; ddf[nt_src-1]=(df[nt_src-1]-df[nt_src-2])/dt; for (int i=1;i1){ //compute dddf dddf = new float[nt_src]; dddf[0]=(ddf[1]-ddf[0])/dt; dddf[nt_src-1]=(ddf[nt_src-1]-ddf[nt_src-2])/dt; for (int i=1;i=0 ){ float lim = sqrt(tau); int i_lim = int(lim/dt); float a = 0.0f; //integral over sigma for( int k=0; k<=i_lim; k++ ){ float sigma2 = k*dt; sigma2*=sigma2; float Omega_inv = sqrt( sigma2 + 2.0f*r/c ); float arg = tau - sigma2; if(d_ord==0){ a += lininterp(nt_src,dt,t0_src,arg,df)/Omega_inv; } else if(d_ord==1){ a += -(gamma/c) * lininterp(nt_src,dt,t0_src,arg,ddf)/Omega_inv -(gamma/c) * lininterp(nt_src,dt,t0_src,arg,df)/(Omega_inv*Omega_inv*Omega_inv); } } p[i] = dt*a/(pi*c*c); }//end if } } ///////////// // 3D case // ///////////// if( dim==3 ){ //time loop for( int i=0; i=t0_src && tau<=T_src ) { int j = int((tau+t0_src)/dt); if(d_ord==0){ p[i] = df[j]; } else if(d_ord==1){ p[i] = -ddf[j]*gamma/c - df[j]*gamma/r; } else if(d_ord==2){ p[i] = dddf[j]*gamma/(c*c) - ddf[j]*(delta-3.0f*gamma)/(c*r) - dddf[j]*(delta-3.0f*gamma)/(r*r); } p[i] /= 4.0f*pi*c*c*r; } } } // cleanup delete[] df; delete[] ddf; delete[] dddf; } catch(RVLException &e){ e << "ERROR from exact!\n"; throw e; } } int xargc; char **xargv; //----------------------------------------------------------------------// int main(int argc, char ** argv) { //----------------------------------------------------------------------// try { #ifdef IWAVE_USE_MPI int ts=0; MPI_Init_thread(&argc,&argv,MPI_THREAD_FUNNELED,&ts); #endif PARARRAY *pars=NULL; FILE *stream=NULL; char *str=NULL; Value val; FILE *fp_src=NULL; FILE *fp_trc=NULL; float bulk, buoy; string src, trc; segy tr_src, tr_trc; int nt_src, nt_trc; float dt_src, dt_trc, dt; float delrt_src, delrt_trc; float *pbuf=NULL; float *gbuf=NULL; fpos_t pos_trc; RPNT x; IPNT derv; int freesurf; float surf_z; str = (char *)usermalloc_(128*sizeof(char)); xargc=argc; xargv=argv; TSOpt::IWaveEnvironment(argc, argv, 0, &pars, &stream); #ifdef IWAVE_USE_MPI if(retrieveGlobalRank()==0){ #endif if(argc<2){ pagedoc(); exit(0); } cerr << "\n////////////////////////////////////////////////////////////\n" << "Running asg_ansol.x\n"; #ifdef IWAVE_USE_MPI } #endif //filenames src = valparse(*pars,"source"); trc = valparse(*pars,"pressure"); //spatial dimension int dim = valparse(*pars,"dimension"); //derivative information derv[0] = valparse(*pars,"MPS_ord_0"); derv[1] = valparse(*pars,"MPS_ord_1"); if(dim==3) derv[2] = valparse(*pars,"MPS_ord_2"); //location of free surface freesurf = valparse(*pars,"freesurf",0); surf_z = valparse(*pars,"surf_z",0.0); //extract nt, dt, delrt from source file if (!(fp_src=iwave_const_fopen(src.c_str(),"r",NULL,stderr))) { RVLException e; e<<"failed to open source trace file = "<(*pars,"bulk"); buoy = valparse(*pars,"buoy"); float c = sqrt(bulk*buoy); //extracting receiver positions and source position vector g_pos = ex_pos(trc,true); vector s_pos = ex_pos(trc,false); //data buffer for output pressure trace (and ghost) pbuf = (float *)usermalloc_(g_pos.size()*nt_trc*sizeof(float)); gbuf = (float *)usermalloc_(g_pos.size()*nt_trc*sizeof(float)); ///////////////////////// // loop over receivers // ///////////////////////// for( int i=0; is_pos[0].coor[0] && surf_zg_pos[i].coor[0] ) ){ RVLException e; e << "Surface depth ("<